Costin
Costin

Reputation: 773

CompareValidator issue on Firefox

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

Answers (4)

Michael Liu
Michael Liu

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

pghcpa
pghcpa

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

Costin
Costin

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

Tim Schmelter
Tim Schmelter

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

Related Questions