MVC DateTime validation failing

14,903

Solution 1

The problem was jQuery validation and localization. It seems that there are localization files for messages and methods of the jQuery plugin. See my blog for a detail explaination of the problem and how I solved it.

http://www.locktar.nl/programming/mvc/localization-validation-in-mvc/

Edit: I just released a new blog post with a refresh of all the localization problems and how to fix it for a DateTime property. See my new post MVC localization validation.

Solution 2

I was able to fix this by modifying the jQuery validator function for dates:

 <script type="text/javascript">

  $(function () {

    var dateFormat="dd/mm/yy"; // en-gb date format, substitute your own

    $("#Birthday").datepicker({
        "dateFormat": dateFormat
    });

    jQuery.validator.addMethod(
        'date',
        function (value, element, params) {
            if (this.optional(element)) {
                return true;
            };
            var result = false;
            try {
                $.datepicker.parseDate(dateFormat, value);
                result = true;
            } catch (err) {
                result = false;
            }
            return result;
        },
        ''
    );

});

Solution 3

The globalization tag isn't set in web.config so it must be using the default. Im from Holland so it should get the client culture I guess.

No, that's not correct. You could be perfectly fine from Holland and have configured your browser to use Chinese culture. The reason you cannot get this to work is probably because in FF and Chrome you don't have the correct culture.

Since you haven't specified a culture in your globalization element in web.config, ASP.NET MVC will use the one sent from the browser in the request header. For example if you configure your browser for en-US culture the following header will be set along each request:

Accept-Language:en-US,en;q=0.8

Here's how this is configured in Chrome:

enter image description here

So make sure you've put your desired language first in the list.

And if you want a reliable way to use the same syntax as the one defined in your DisplayFormat attribute during model binding you could write a custom model binder as shown here: https://stackoverflow.com/a/7836093/29407

Share:
14,903
LockTar
Author by

LockTar

Updated on June 24, 2022

Comments

  • LockTar
    LockTar about 2 years

    I found a lot of simulair questions but not a good clean solution that is working. I see a lot of custom code for getting this to work but why is that? Should this not working from the start?

    What I think is strange, is that in IE9 it works but in Firefox and Chrome it is failing. Everytime that im trying in Firefox or Chrome, I get the message "The field Birthday must be a date".

    When I try the code below in a new MVC 4 RTM project, I can't get it to work. I see the DateTime.Now default as dd-MM-yyyy (Holland) in all the browsers but I can't submit it in Firefox and Chrome.

    The globalization tag isn't set in web.config so it must be using the default. Im from Holland so it should get the client culture I guess.

    public class RegisterModel
    {
        [Required]
        [Display(Name = "User name")]
        public string UserName { get; set; }
    
        [Required]
        [DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
        //[DataType(DataType.Date)]
        public DateTime Birthday { get; set; }
    }
    
    [AllowAnonymous]
        public ActionResult Register()
        {
            RegisterModel vm = new RegisterModel()
            {
                Birthday = DateTime.Now
            };
            return View(vm);
        }
    
        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public ActionResult Register(RegisterModel model)
        {
            if (ModelState.IsValid)
            {
                // Attempt to register the user
                try
                {
                    //WebSecurity.CreateUserAndAccount(model.UserName, model.Password);
                    //WebSecurity.Login(model.UserName, model.Password);
                    return RedirectToAction("Index", "Home");
                }
                catch (MembershipCreateUserException e)
                {
                    ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
                }
            }
    
            // If we got this far, something failed, redisplay form
            return View(model);
        }
    

    Markup

    <!-- language: lang-none -->
    @model DateTimeWithDatePicker.Models.RegisterModel
    @{
       ViewBag.Title = "Register";
    }
    
    <hgroup class="title">
        <h1>@ViewBag.Title.</h1>
        <h2>Create a new account.</h2>
    </hgroup>
    
    @using (Html.BeginForm()) {
        @Html.AntiForgeryToken()
        @Html.ValidationSummary()
    
        <fieldset>
            <legend>Registration Form</legend>
            <ol>
                <li>
                    @Html.LabelFor(m => m.UserName)
                    @Html.TextBoxFor(m => m.UserName)
                </li>
                <li>
                    @Html.LabelFor(m => m.Birthday)
                    @Html.EditorFor(m => m.Birthday)
                </li>
            </ol>
            <input type="submit" value="Register" />
        </fieldset>
    }
    
    @section Scripts {
        @Scripts.Render("~/bundles/jqueryval")
    }
    
  • LockTar
    LockTar almost 12 years
    My culture was good in firefox and chrome so that wasn't the problem. The problem was jQuery validation that wasn't working in Firefox and Chrome the same as in Internet Explorer. See the answer of this post and my blog the goes into details.
  • LockTar
    LockTar over 11 years
    See my response on my own topic. I made a blogpost about it stackoverflow.com/a/12346915/801005
  • gls123
    gls123 over 11 years
    I tried your blog post when trying to solve this problem. I am sure that its the best solution when you want a conclusive solution for many users in different countries. But the script above is suitable when you need a two minute solution and you dont care about localisation for multi country user base.
  • R. Schreurs
    R. Schreurs about 11 years
    I have used ajax.aspnetcdn.com/ajax/jquery.validate/1.7/localization/…, I found following your link. This worked fine in IE and Firefox, but not in Chrome. Chrome supports html5 date input and stores the value in format "yyyy-mm-dd". I have changed the test to: if (Modernizr.inputtypes.date) { return true; } else { <original test> }
  • LockTar
    LockTar about 11 years
    Have you changed 1.7 to the newest version? It it some time ago i've written that blog. I just launched my new blog site at www.locktar.nl.