Monday, April 20, 2009

.NET FileUpload control throws a javascript error in IE when a non-existent filename is entered

I ran into an interesting bug with .NET/IE the other day and didn't readily find a comprehensive solution, so I thought I'd post what I came up with to hopefully guide some poor soul home. I've tried to pare my code down to the bare basics so that it can be modified to your specific circumstance. This is specifically for IE7. Other browsers (Chrome, Firefox, Safari) don't exhibit this behavior and should be handled differently.

My solution involves using client side scripting to validate the existence of a valid filename in the control, and halting the submission of the form in the case of a poorly formed filename (permitting a blank control). I've written it in such a way as to permit multiple FileUpload controls on the page all subscribing to the same validation mechanism.

-Registering the controls to be validated.
-Validating said controls
-Capturing a PostBack action
-Ignoring other browsers

Registering the controls to be validated

Since the listeners and function pointers (more on these later) should only appear once, I created an array to house the FileUpload controls of interest. It's the responsibility of the control to register.


/*this should go in your main script section, outside of the browser checking area*/

var FileUploadControls = new Array();
function RegisterFileUploadControls(fcobj)
{
FileUploadControls[FileUploadControls.length] = fcobj;
}




/*this can appear at any later point in the document, because of the way my controls would render, I had them register at the same time that they render. */

RegisterFileUploadControls(document.getElementById("fileupload_clientid"));



Validating the FileUploadControls

I opted to use a regular expression style to validate the format of whatever is in the textbox of the fileupload control. Write whatever test you feel is appropriate. I kept it relatively basic, most of the errors that I was getting from users were people putting in garbage in the textbox. There's additional error checking on the server side for the actual receipt of a file, but that's beyond the scope of this post.


//put this in your main script area, inside the browser checking

function CheckFileUploadControls()
{

/*boolean that will return false if the text doesn't pass the test.
a false return value is intended to halt submission of the form, true will permit the sumission. */
bFileUploadValidation=true;

/*put in a regular expression that fits the amount of validation that you're looking for, this one is
just looking for an alpha character, max two, followed by a “:” and “\” and whatever comes
after is permitted. Pretty loose validation, but you can get as fancy as you'd like. */

pAlphaLower = new RegExp("^([a-z][A-Z]){1,2}:\\.*");

//loop through the controls that have registered

for(x=0;x {
oElement=FileUploadControls[x];
oMessage=FileUploadControlsMessages[x];

/*we're only interested in elements that have specified a value. Blank fileuploads
are permitted. */

if(oElement.value!='')
{
//regex test against the value
if(!pAlphaLower.test(oElement.value))
{
//insert your error messaging here//
bFileUploadValidation=false;
}
}
}
//otherwise permit the form submission to continue
return bFileUploadValidation;
}



Capturing a PostBack action

Traditionally, a postback is going to be initiated from the Form in one of two ways, a “submit” button that invokes standard HTML behavior, or a call to __doPostBack which invokes the behavior through something like document.forms[n].submit();

The standard HTML behavior can be approached by adding an event listener to the FORM object. IE does this differently than the other browsers and this code will cause an error outside of IE (google: javascript addEventListener for examples).


//put this in your main script area, inside the browser checking
function AttachFormListner()
{
document.forms[0].attachEvent('onsubmit',CheckFileUploadControls);
}



The second most common way that ASP.NET is going to raise a postback is by calling their javascript function __doPostBack(obj,args). What I did was create a function pointer to Microsoft's version of __doPostBack, then overrode __doPostBack with my error handling finishing with a call to the base class.



/*insert this code in your main script area, inside the browser checking
this is the function pointer to the standard version of the method */
var base_post_back = __doPostBack;

/*here I create another function pointer that overrides the standard version
the function just calls our validation routine and aborts the form submission in the case of a
filename that doesn't match our rule. insert this code in your main script area */

__doPostBack = function(obj, objj){if(CheckFileUploadControls()){base_post_back(obj,objj);}}



Ignoring other browsers

The best way to sift the browsers is based on the javascript functionality rather than getting into the mess of versions. If I can't use “attachEvent” on a FORM object, then I'm not interested in continuing further with the code.


//this should surround all the code that is subject to browser checking

if(document.forms[0].attachEvent){
//all those code snippets should go in here
};



Hope this was a help, feel free to use the comments to talk w/me.

Thursday, July 10, 2008

Hello World

Sorry nerds, I couldn't resist.

Allow me to introduce myself and this blog. I'm Ben Barraza, my official title at work is Web Systems Architect. I'm at Weber State University in Ogden, Utah and have been so since 1996. As a young pup, they tasked me with creating a website for the office I worked in at the time. The bug caught and I went into the Computer Science program at said university, later on took a full time position, and voila, here we are.

Birth of a Blog

Recently we've had a lot of chatter on campus about Web 2.0. Also, we've just hired a new Vice President for Information Technology. There has been a lot of interesting discussion, and there has been a lot of crazy talk. I decided that I'd like to formally throw my hat into the ring. I plan to discuss my thoughts and views on all things Web, especially how they relate to higher ed. I also plan to discuss some of the projects that I work on, or detail some past projects good, bad and ugly, in the hopes that some poor underfunded sap at a university can either learn from my mistakes, or commiserate in our failures, or rejoice in all things web. This blog is not sanctioned by WSU, and the thoughts and opinions expressed herein are my own and have nothing to do with University policy, procedure or direction.

A few of the things that I have on tap: Web 2.0 and the Modern University; The Challenge of Online Graduate Admissions; Build, Borrow, or Buy? The answer is simple; The HyperConnected Student vs Everyone Else.

I hope this is useful, if you'd like to get involved in the discussion comment it up, if you'd like me to initiate a discussion...comment it up. Thanks the Internet.