Javascript Validation in ASP.Net

I am writing an ASP.Net application that needs validation for certain fields. I found a Javascript routine that will examine a text box for uppercase, lowercase, and numerics. I can split up the validation to return a value based on what is found.
The problem is that I cannot figure out how to incorporate this Javascript with my custom error handler. The custom error handler for ASP.Net cannot be used to weed numbers and/or special characters out of a text field. That is why I am using the Javascript routine.
This is what I am trying to add to the HTML code of my project:

var numb = '0123456789';
var lwr = 'abcdefghijklmnopqrstuvwxyz';
var upr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
function isValid(parm,val) {
if (parm == "") return false;
for (i=0; i<parm.length; i++) {
if (val.indexOf(parm.charAt(i),0) == -1) return false;
}
return true;
}
function isNum(parm) {return isValid(parm,numb);}
function isLower(parm) {return isValid(parm,lwr);}
function isUpper(parm) {return isValid(parm,upr);}
function isAlpha(parm) {return isValid(parm,lwr+upr);}
function isAlphanum(parm) {return isValid(parm,lwr+upr+numb);}

How do I write my serverside routine to pass the parameter to the Javascript for validation? And example of the above function is
isNum(field).
Thanks,
Mr. Finkle
[1496 byte] By [Mr.Finkle] at [2008-2-17]
# 1
The Javascript should be posted to the client to evaluate the value in the web browser. You can validate the values on the server side (which you should do in addition so that attackers don't submit HTTP GET or POST and bypass your page validation) by using the various methods of the System.Char class. Everything you are doing in Javascript above you can do in C# (or whatever language you wish to use that supports ASP.NET).

To do client-side validation, either type the script into the static content of our .aspx or .ascx or use Page.RegisterClientScriptBlock (this is obsolete for .NET 2.0, so use the ClientScriptManager class). Then add a CustomValidator to your page or control and set the CustomValidator.ClientValidationFunction to the function name to validate your input. See http://msdn.microsoft.com/library/en-us/cpref/html/frlrfSystemWebUIWebControlsCustomValidatorClassClientValidationFunctionTopic.asp for an example.

HeathStewart at 2007-10-6 > top of Msdn Tech,.NET Development,JScript for the .NET Framework...
# 2
I figured out what was wrong with my validation. It appears that Javascript has to be written "just so" for .Net.
Now, I have a new problem. I have a form that required three boxes for the date. Month goes in one box, date goes in the second box, and the four digit year goes in the third box. The reason for this is the system being written is replacing a mainframe system, and dinosaurs are hesitant to change.
When the date fields have been entered, I want to concatenate the date fields into one variable and them perform date validation. The problem is that I my Javascript abends when I try to use var gDate=document.Form1.txtFormMM.value
Am I missing am Imports statement? Every example of Javascript I find on the Web shows me that the above line of code is correct; however the error I get states that 'document.DateTest.txt.FormMM' is null or not an object. DateTest is what I called my form. Anyone have any ideas?
Thanks,
Finkle.
Mr.Finkle at 2007-10-6 > top of Msdn Tech,.NET Development,JScript for the .NET Framework...
# 3
It's important to undersatnd that the JavaScript only runs on the client and is not compiled to manage code. It's no different than JavaScript output to a page in ASP, PGP, or even static HTML. JavaScript/JScript doesn't support an "imports" statement. You're not using this JavaScript on the server, are you? If you're outputting it in the HTML then it's only for the client browser's benefit and is not managed code - just script.

Because ASP.NET names it's objects according to their hierarchy, chances are that in your page document.Form1.txtFormMM is the not an object. Look at the resultant HTML. You might find it something closer to document.theForm.ctl0_ctl0_blah_blah_blah.txtFormMM. Use the UniqueID property of the control on the server to output into the HTML so that JavaScript has the correct ID.

HeathStewart at 2007-10-6 > top of Msdn Tech,.NET Development,JScript for the .NET Framework...
# 4
OK, I think there's some confusion here. What I need to do is establish an error validation event the fires when the user has finished entering the year of the date. The date has to be broken up into three separate text boxes. .Net appears to insist that variables have to be passed as follows:
}
function isValidDate(oSrc, args){
alert(document.FOrm1.txtFromYear.Value);
if (isDate(args.Value)==false){
args.isValid = flase
}
}
Now, I want to be ablet to concatenate the month and date with the year further into the Javascript function in order to execute my date validation. Here is the Body portion of my code:
<body MS_POSITIONING="GridLayout">
<form id="Form1" method="post" runat="server">
<asp:customvalidator id="CustomValidator1" style="Z-INDEX: 101; LEFT: 408px; POSITION: absolute; TOP: 184px"
runat="server" ClientValidationFunction="isValidDate" ControlToValidate="txtFromYear" ErrorMessage="Invalid Date Format"></asp:customvalidator>
<asp:TextBox id="txtFromDD" style="Z-INDEX: 104; LEFT: 304px; POSITION: absolute; TOP: 184px"
runat="server" Width="25px" MaxLength="2"></asp:TextBox>
<asp:TextBox id="txtFromMM" style="Z-INDEX: 103; LEFT: 264px; POSITION: absolute; TOP: 184px"
runat="server" Width="28px" MaxLength="2"></asp:TextBox><asp:textbox id="txtFromYear" style="Z-INDEX: 102; LEFT: 336px; POSITION: absolute; TOP: 184px"
runat="server" Width="52px" MaxLength="4"></asp:textbox></form>
</body>
Mr.Finkle at 2007-10-6 > top of Msdn Tech,.NET Development,JScript for the .NET Framework...
# 5
No, the args parameter as you have it above is the element to be validated so use that. The args contains the value to check so you don't even need to use document.Form1.txtFormYear.Value. What I said still holds true, though: the object ID of the field you want to validate probably does not have that client ID. For each nested control under another control that implements the INamingContaining marker interface (no methods), the ID is mangled. The Control.UniqueID gets the final ID of the control, so you must output that to your page to refer to it correctly. Take a look at your HTML and find your control and I'm pretty sure you'll find the control ID is very different than what you expect. That assert probably will not work, but the rest of your code looks correct. If you're trying to validate parts of the date, though, you can't validate each piece as a date because it's not. Is 2005 a date? No. Is 12 a date? No. Make sure each piece of the date based on the control you're validating is correct, that the year is a valid year (not like "a45f" or 1 is something like that), that the month is between 1 and 12 inclusive, etc. If you want to evaluate all of them at the same time then you must output the Control.UniqueID for each of the controls into your client-side JavaScript so that the right ID can be used. It's not simply the ID you typed in your ASP.NET source code. Again, look at the HTML for your page in the browser.

A common solution to this problem is to output a block of script in the <HEAD> (where page script is actually supposed to go anyway) that defines all the controls or browser capabilities. That way your client-side script can use those global ID variables in the page and you don't have to output the control's UniqueID every time you need it - only once. The result would look like the following in your page header:

<script language="javascript" type="text/javascript"><!--
var g_ctrlYearID = 'ctl0_ctl0_txtYear';
var g_ctrlMonthID = 'ctl0_ctl0_txtMonth';
var g_ctrlDayID = 'ctl0_ctl0_txtDay';
//--></script>

Of course, those values for the variables are output using the Control.UniqueID property of each one. Then you can use those like so elsewhere:

<script language="javascript" type="text/javascript"><!--
var eYear = document.getElementById(g_ctrlYearID);
var eMonth = document.getElementById(g_ctrlMonthID);
var eDay = document.getElementById(g_ctrlDayID);
var date = new Date(eYear.value, eMonth.value, eDay.value);
//...
//--></script>

It doesn't matter, though, since the args parameters contains the value to validate. Read Walkthrough: Validating User Input in a Web Forms Page. It's even pretty similar to what you're trying to do.

As far as passing the year as a single object I would highly recommend against that because of how page processing works. On the server validate them again (like I said in a previous post, attackers could pass bad data to your server and bypass your client-side script, or Javascript may even be disabled in the browser) and build your DateTime object on the server using the individual pieces. If you try to combine them and pass them to the server AND you rely on that, then for the same reasons I mentioned above you may not get what you expect back because javascript is disabled or an attacker sent you bad data. An attacker could even be an accidental user who made a mistake or used the page in a way you didn't expect.

This allows the page to handle post-back data as it should. Messing with this mechanism can have disastrous results. Just re-combine them on the server to get your date.

HeathStewart at 2007-10-6 > top of Msdn Tech,.NET Development,JScript for the .NET Framework...
# 6
OK, some of what you say makes sense. One item that trips me up is that for the Custom Validation to execute, I have to code the following:
function val_From(oSrc, args){
var fDateMM = document.Form1.TextBox1.value
var fDateDD = document.Form1.TextBox2.value
var fDateYY = document.Form1.TextBox2.value
args.Value = (fDateMM) + '/' + (fDateDD) + '/' + (fDateYY)
if (isDate(args.Value)==false){
args.IsValid = false
}
}
The isDate function is the function I pass my formatted date for for validation. I learned through trial and error that on .Net a custom function has to have (oSrc, args) coded. I don't understand what oSrc uses, nor do I understand what args uses. I also learned that I have to concatenate my values into args.Value in order to pass data to my other functions.
Here is my current challenge: I have a "From" date and a "Thru" date on my page. Not only do I have to ensure both dates fall within specific date minimums and maximums, but I also have to generate and error if the "Thru" date is less than the "From" date. The only solution I currently have is to re-code my isDate function to use two dates. The way I forsee succeeding is to concatenate both dates with a '*' between them (01/01/2001*1/21/2005). That way, the asterisk will serve as my reference point for the start and stop of a date. The page is already going to validate the "From" date while the user is entering it, so when it validates the "Thru" date it looks like the "From" date will have to be run through again, as Javascript variables are static. The trick is to enable the isDate function to loop through and process the second date, and return either a 'True' or 'False' for validity.
I don't believe anyone would be able to bypass the date edits, because I have server side validation that will not allow blank dates to be entered. Should someone enter garbage, then the inquiry most likely will not yield anything useful.
Mr.Finkle at 2007-10-6 > top of Msdn Tech,.NET Development,JScript for the .NET Framework...
# 7
The link I gave you before explains those two arguments; they are documented and similar in nature to the standard argument-style of any other event handler in .NET.

Again, though - the control ID you're using is most likely not valid. You MUST use Control.UniqueID for the control you're trying to access in script. In your browser with the page open click Edit->View Source and find your control ID. You'll find the control ID is very different, and that document.Form1.TextBox2.value will not refer to the control. This is because many controls (including the page, panels, DataGrid, etc.) are naming containers that add their own control ID to make up a unique control ID on the page, since a unique ID for every control is required in correctly-formatted HTML and XML.

The validation function is called for each textbox to be validated where a CustomValidator is attached, too. The link I posted before explains more and has a walkthrough. I recommend you read through that.

HeathStewart at 2007-10-6 > top of Msdn Tech,.NET Development,JScript for the .NET Framework...
# 8
To show you an example, you can look at the HTML source of this page and you'll find element IDs like the following:

<span id="_ctl0_MainContent_PostFlatView">

Now, pretend you developed the code for this page. you made a control called PostFlatView, so you'd expect to find it by doing document.all.PostFlatView (IE only) or document.getElementById("PostFlatView") (standard). That wouldn't work, however, because the control's UniqueID property value is _ctl0_MainContent_PostFlatView, which means that the PostFlatView control is inside a naming container called MainContent, which is inside another naming container called ctl0 (most likely the actual control wasn't given a unique ID so the default format of ctlNNN is used, where NNN is an incremental number).

That's the ID you have to use, and that can be obtained by using the Control.UniqueID property of the control you want, and outputing the return value into the HTML itself to be used.

This isn't encessary for validation controls, however. Your client-side script validation function is called for each control to be validated using that function name (so you could have different client-side script functions for different controls). The second parameter (which you've called "args") has a Value and IsValid property. If you want to validate all text boxes at once you should have a CustomValidator for one with an associated client-side validation function (again - don't forget to validate it on the server to be sure and not rely on client-side scripting which can be thwarted or turned off) and output the Control.UniqueID property of the other controls so that you can access them correctly. Outputing these as global variables in a <script></script> block is most helpful and many sites on the Internet do this. For an example, go to http://msdn2.microsoft.com, view source, and look at the bottom. You'll find a lot of variables defined in a JavaScript block. The value of these variables is written to the page on the server, and the variables can easily be used by client-side script. This is what I'm recommending to you using the Control.UniqueID property value of all three controls that comprise the date. You would then end up writing a script block like I posted in a previous reply in this thread.

HeathStewart at 2007-10-6 > top of Msdn Tech,.NET Development,JScript for the .NET Framework...
# 9
I have figured out most of what I am trying to accomplish. The co-worker who has been guiding me through learning Javascript mentioned Global variables. I had never thought of that before, but that made perfect sense. I have now rewritten my routines to utilize global variables for the From date when performing the comparision with the Thru date.
Thank you for your assistance, Heath.
Mr.Finkle at 2007-10-6 > top of Msdn Tech,.NET Development,JScript for the .NET Framework...

.NET Development

Site Classified