Okay, I just had to blog this one.. not because I have an
amazing solution that will save people lots of hassle, but because
of the complete bizarness of it. There's very little
information online about this problem, so hopefully if anybody else
has this problem, they'll find this, share their experience, and
best case scenario come up with a solution that we can blog for the
rest of the world. I wouldn't wish what I've gone through
today on anybody else... it wasn't fun!
The Symptom:
Running an ASP.Net 1.1 web form which has some validation controls
on it throws the following Javascript error in Firefox
Only:
"ValidatorHookupControlID is not defined"
The Problem:
After much investigation (see below), deliberation and
various other tions, I have determined, conclusively, the
following:
- ASP.Net 1.x does not render useful client-side
validation for non-Microsoft browsers.
- There are various ways to get ASP.Net 1.x to render useful
client-side validaiton code for non-MS browsers, including:
- Create a new class that overrides the
RegisterValidatorDeclaration() function, and then create a new
class for each validator which inherits from this new class
(tedious at best)
- Rebuild all the validation from scratch (I'd be more inclined to
do this, using a solid javascript library such as jQuery
perhaps)
- Use one of the available control libraries (including the free DomValidators
controls written by Paul Glavich )
- ASP.Net 1.x is quote obviously a very young framework, and
should be treated as such. If you're considering building an
application on .Net 1.x, DON'T! If you come across a .Net 1.x
application in a production environment that requires maintenance
and new features, run the other way! Trust
me, it's not pretty.
- If you must use and extend a .Net 1.x web application, I'd
recommend learning a library such as jQuery and doing away with the
built in validation all together. They're more trouble than
they're worth IMO.
This article at 4
4uys From Rolla does a good job of explaining this limitation
of ASP.Net 1.x, and is what convinced me to stop trying to find a
solution to this problem and seek a fix elsewhere...
The Investigation:
If you're interested in how i came to the above
conclusions, feel free to read on...
It would seem that the page is unable to load the script file
containing the ValidatorHookupControlID function is not loading,
hence the function being "not defined". The code in my web form
calling this function is some custom validators at the point where
they are getting hooked up, like this:
// hook up
javascript validation for custom validtors
string script = String.Format(
"ValidatorHookupControlID({0}, document.getElementById({1}));\n" +
"ValidatorHookupControlID({2},
document.getElementById({3}));\n" +
"ValidatorHookupControlID({4},
document.getElementById({5}));",
"txtAccountNumber", "cuvAccount",
"txtLastName", "cuvLastName",
"txtPostcode", "cuvPostcode");
if (!Page.IsStartupScriptRegistered("AccountStartupScript"))
{
// place at end of form
Page.RegisterStartupScript("AccountStartupScript",
Util.GenerateJavascriptBlock(script));
}
BUT, why does it work in IE, but not in Firefox??
The Investigation:
Googling the error code didn't offer much help, except for this
forum discussion:
http://www.developpez.net/forums/showthread.php?t=578584
It's in French unfortunately, but using BabelFish i was able to
make some sense if it... After skipping the talk of implementing
IValidator (if it works in IE then it can't be a .Net problem -
must be something client-side), I found a suggestion to manually
register the Client Validation Script file (which should
automatically be registered under the .Net Framework). Nice
tip, but unfortunately specific to .Net 2+, as .Net 1.1 does not
contain a RegisterClientScriptResource function.
Dammit! (At this point I'm starting to get rather irate, and
cursing the forces of nature that led me to work on .Net 1.1
code!).
Looking over the options in .Net 1.1, there's little of
assistance with respect to registering a javascript file via
code-behind, so I went down the path of manually registering it on
the aspx page. I copied the file from the
"aspnet_client\system_web\1_1_4322" folder, and referenced it, but
no joy... An interesting result no less - Firefox now complains
with the following error: "Non-standard document.all property was
used. Use W3C standard document.getElementById() instead."
Naughty Microsoft using some dodgy antiquated javascript code..
then again, naughty (unnamed) employer for using an antiquated
framework. Following that path led to a whole new set of issues,
but those will have to wait for another day, right now I must
soldier on with the problem at hand.... Which still remains -
manually referencing the file with the function required did not
solve this problem - client-side validation still doesn't
work!! So even when FireFox can see the
ValidatorHookupControlID function, it doesn't use it... IE, on the
other hand, is quite happy with or without that explicit script
reference, and plays nicely with Document.All() function.
Change of direction required... lets look at the
environment. Next step was to roll back any changes I'd made
to see if I introduced this bug... luckily there's a previous
(apparently working) version on Source Control that I can
use. I rolled back my changes to the previous version, and
found that the problem remained. I then disabled the current
IIS site (i'm using XP Pro IIS Admin for this - www.jetstat.com)
and enabled the Default Website (which is the one I use for most
things), copied the code base from Source Control to this new site,
and ran it - it worked fine!! Next copied my new changes to
the default IIS site - and, yes, it worked fine!!
The Cause:
So after a stupid number of incredibly frustrating hours of
troubleshooting, I've discovered that the problem lies in IIS
itself. It seems that the site that's running this
application is corrupted somehow. The javascript file
(WebUIValidation.js) required by the ValidatorHookupControlID()
function is there - so I dont know why Firefox has an issue.
I've tried numerous times during the day to restart IIS (both
restarting the service, and running "aspnet_regiis -i" at command
prompt, to no avail.
Then, comparing the Default site to the new one, I found that
the settings were almost identical. As i went I made sure the
settings were identical... The only thing I couldn't easily copy
across was Server Extensions (not installed on the new site), so I
disabled that on the old site, and it still worked, so ruled that
one out.
The Solution:
Basically, after many hours of messing around, I still don't have
a solution. I have a working solution for my current
situation (use the Default Website, and whatever I do don't change
any settings on it!!).
The questions [answered inline] were:
- Why does Firefox complain about ValidatorHookupControlID() not
being defined, while IE doesn't?
Because of Microsoft's wonderful "Adaptive Rendering" - if it
determines that the browser is not capable of using its client side
validation controls, it just won't render the code.
- Why does validation still not work in Firefox even when it has
ValidatorHookupControlID() available to it?
Because of Microsofts wonderful use of non-standard
document.all() code, which no browsers other than IE actually
understand.
- What is it that is different about my Default Website to the
new Working website in IIS?
Because of Microsofts... errrr... well I honestly still don't
know. Thing is its (client side validation in IE) working
now, and I have no idea how i fixed it.
The Wrap-Up:
Well this has been quite an adventure... If you've had
similar experiences, or would like to share your thoughts on all of
this, or even just some of it, please leave a comment below. It'd
be nice to know that I'm not the only one that's been through this
incredibly tedious process, and come out the other end frustrated
as hell...
Update:
I found an interesting
article about similar (but not quite exactly the same) javascript
validation problems ... there was a suggestion
to re-register the client-side validation scripts using the
following commands:
aspnet_regiis -ea (remove client-side validation scripts)
aspnet_regiis -c (copy client-side validation scripts back)
While i was quite hopeful that this might work, it didn't.
So back to wondering what the hell is wrong!?
Update 2:
Problem solved (updated above under The Problem).
Closing this file for now...