Reputation: 773
I need to validate a date in a web forms application. For this I use a CompareValidator with
Operator="DataTypeCheck" Type="Date"
The problem is that this Validator doesn't work properly on Firefox with 2 digit years. ( javascript error: m[2] is undefined) With a 4 digits year it's working properly.
This problem is described also here: https://connect.microsoft.com/VisualStudio/feedback/details/355573/comparevalidator-client-side-bug-two-digit-year-in-mozilla-based-browsers-throws-js-exception
Does anyone know a nice workaround for this?
Thanks
Upvotes: 4
Views: 1081
Reputation: 55339
This is a bug in ASP.NET 3.5 and earlier, in the client-side validation script. (The script works correctly in older versions of Internet Explorer but not in newer standards-compliant browsers.)
Microsoft has fixed the bug in ASP.NET 4.0.
If you cannot upgrade to ASP.NET 4.0, you can export the WebUIValidation.js resource from the version of System.Web.dll that comes with .NET 4.0, and then register the script in your page's PreRender
event:
this.ClientScript.RegisterClientScriptInclude(
typeof(System.Web.UI.WebControls.BaseValidator), "WebUIValidation.js",
"url-to-the-4.0-WebUIValidation.js-script");
Alternately, you can override the buggy ValidatorConvert
function by adding the following to a <script type="text/javascript">
block on your page:
function ValidatorConvert(op, dataType, val) {
function GetFullYear(year) {
var twoDigitCutoffYear = val.cutoffyear % 100;
var cutoffYearCentury = val.cutoffyear - twoDigitCutoffYear;
return ((year > twoDigitCutoffYear) ? (cutoffYearCentury - 100 + year) : (cutoffYearCentury + year));
}
var num, cleanInput, m, exp;
if (dataType == "Integer") {
exp = /^\s*[-\+]?\d+\s*$/;
if (op.match(exp) == null)
return null;
num = parseInt(op, 10);
return (isNaN(num) ? null : num);
}
else if(dataType == "Double") {
exp = new RegExp("^\\s*([-\\+])?(\\d*)\\" + val.decimalchar + "?(\\d*)\\s*$");
m = op.match(exp);
if (m == null)
return null;
if (m[2].length == 0 && m[3].length == 0)
return null;
cleanInput = (m[1] != null ? m[1] : "") + (m[2].length>0 ? m[2] : "0") + (m[3].length>0 ? "." + m[3] : "");
num = parseFloat(cleanInput);
return (isNaN(num) ? null : num);
}
else if (dataType == "Currency") {
var hasDigits = (val.digits > 0);
var beginGroupSize, subsequentGroupSize;
var groupSizeNum = parseInt(val.groupsize, 10);
if (!isNaN(groupSizeNum) && groupSizeNum > 0) {
beginGroupSize = "{1," + groupSizeNum + "}";
subsequentGroupSize = "{" + groupSizeNum + "}";
}
else {
beginGroupSize = subsequentGroupSize = "+";
}
exp = new RegExp("^\\s*([-\\+])?((\\d" + beginGroupSize + "(\\" + val.groupchar + "\\d" + subsequentGroupSize + ")+)|\\d*)"
+ (hasDigits ? "\\" + val.decimalchar + "?(\\d{0," + val.digits + "})" : "")
+ "\\s*$");
m = op.match(exp);
if (m == null)
return null;
if (m[2].length == 0 && hasDigits && m[5].length == 0)
return null;
cleanInput = (m[1] != null ? m[1] : "") + m[2].replace(new RegExp("(\\" + val.groupchar + ")", "g"), "") + ((hasDigits && m[5].length > 0) ? "." + m[5] : "");
num = parseFloat(cleanInput);
return (isNaN(num) ? null : num);
}
else if (dataType == "Date") {
var yearFirstExp = new RegExp("^\\s*((\\d{4})|(\\d{2}))([-/]|\\. ?)(\\d{1,2})\\4(\\d{1,2})\\.?\\s*$");
m = op.match(yearFirstExp);
var day, month, year;
if (m != null && (((typeof(m[2]) != "undefined") && (m[2].length == 4)) || val.dateorder == "ymd")) {
day = m[6];
month = m[5];
year = (m[2].length == 4) ? m[2] : GetFullYear(parseInt(m[3], 10));
}
else {
if (val.dateorder == "ymd"){
return null;
}
var yearLastExp = new RegExp("^\\s*(\\d{1,2})([-/]|\\. ?)(\\d{1,2})(?:\\s|\\2)((\\d{4})|(\\d{2}))(?:\\s\u0433\\.|\\.)?\\s*$");
m = op.match(yearLastExp);
if (m == null) {
return null;
}
if (val.dateorder == "mdy") {
day = m[3];
month = m[1];
}
else {
day = m[1];
month = m[3];
}
year = ((typeof(m[5]) != "undefined") && (m[5].length == 4)) ? m[5] : GetFullYear(parseInt(m[6], 10));
}
month -= 1;
var date = new Date(year, month, day);
if (year < 100) {
date.setFullYear(year);
}
return (typeof(date) == "object" && year == date.getFullYear() && month == date.getMonth() && day == date.getDate()) ? date.valueOf() : null;
}
else {
return op.toString();
}
}
Upvotes: 3
Reputation: 843
Use a custom validator
Imports System.Globalization
Private Sub CustomValidator1_ServerValidate(source As Object, args As System.Web.UI.WebControls.ServerValidateEventArgs) Handles CustomValidator1.ServerValidate
Dim dateResult As Date
If Date.TryParse(TextBox1.Text, CultureInfo.CreateSpecificCulture("zh-CN"), DateTimeStyles.None, dateResult) Then
args.IsValid = True
Else
args.IsValid = False
End If
End Sub
Could do the equivalent with on client-side in JS if preferred.
Upvotes: 0
Reputation: 773
My solution was to create a date validator which inherits from BaseValidator
and overwrites the ControlPropertiesValid(), EvaluateIsValid() and OnPreRender(EventArgs e)
.
If you have other ideas please shot.
Upvotes: 0
Reputation: 460018
Perhaps this helps you(last post, only dataType == "Date" needed), but i havent tested it: http://forums.asp.net/t/1358621.aspx
Upvotes: 1