1

Closed

date validation problem

description

I created a new MVC4 project in VS2012 with the basic template. I created a model class with a DateTime property. I added a default controller that sets the property to DateTime.Today and a default view that displays the editor for this property. I also included the jqueryval script bundle in my layout, they were in my project by default. When I run the project, there is a textbox with the value "2013.12.12. 0:00:00". But when I press submit, it says its invalid.

file attachments

Closed May 28 at 10:46 PM by yishaigalatzer

comments

fejesjoco wrote Dec 13, 2013 at 8:39 AM

doubgu commented in a misplaced issue (aspnet:10373) that he cannot reproduce the problem. I think it is because I live in Hungary, this is my actual date format, and this is perfectly normal. So even though this is the default behavior for me, you may need to change the culture and uiculture to hu-HU in order to reproduce this issue.

nowakra wrote Dec 17, 2013 at 8:39 PM

Doug, can you investigate and see what's going on here? Looks similar to other issues you've looked into.

dougbu wrote Dec 18, 2013 at 8:51 PM

Problem may be browser-specific or fixed in more recent packages. I'm still unable to reproduce the problem. Have sent a private request for clarification of the scenario to fejesjoco.
Moving to 5.2 at least for now.

fejesjoco wrote Dec 27, 2013 at 9:02 PM

I updated all package versions as Doug suggested in his private message and I'm attaching a repro solution here, but I also uploaded it here just in case: http://joco.name/repro1503.zip

When the culture is hu-HU, I get a client side validation error, the textbox turns red when I press submit. It works when the culture is en-US. The date formats are different of course. I explicitly set the culture in web.config to make sure you can reproduce it, but that line wasn't there in the web.config, it is my default culture.

There are no validation attributes or anything extra, just what I wrote originally: a simple model with a date value, and the unobtrusive validation is broken by default.

By the way, I just noticed this: when I change the value of the property during the POST, DisplayFor displays the changed value, but EditorFor still displays the original POST'ed value, is that normal?

dougbu wrote Dec 31, 2013 at 7:24 AM

Problem is a client-side validation error: Generated code uses the jQuery.Validation date method by default. That method is not recommended due to different behavior across browsers and regions. But this is the best MVC and jQuery.Validation can do without additional packages.

Solution is to install the jQuery.Validation.Globalize package and extend the jqueryval bundle to include those scripts. Details below.

DisplayFor is intended for read-only (or delete) views and it uses only the provided Model to determine display. EditorFor is used in create / update views and in that context the server-side Model may contain last-known-good values rather than the attempted submission. EditorFor therefore also pays attention to the validation information and to the view data.

I will resolve this bug late this week unless you have a specific suggestion for unobtrusive or MVC.

(FYI my previous attempted repros failed because nothing created the jqueryval bundle.)

Globalize details:
public class BundleConfig
{
    public static void RegisterBundles(BundleCollection bundles)
    {
        // See http://stackoverflow.com/questions/19323409/asp-net-mvc-bundle-config-order for more on overriding
        // default order within this bundle.
        Bundle validationBundle = new ScriptBundle("~/bundles/jqueryval")
        {
            Orderer = new NonOrderingBundleOrderer(),
        };
        validationBundle.Include("~/Scripts/globalize/globalize.js",
            "~/Scripts/globalize/cultures/globalize.cultures.js",
            "~/Scripts/jquery.unobtrusive*",
            "~/Scripts/jquery.validate.js",
            "~/Scripts/jquery.validate.globalize.js",
            "~/Scripts/jquery.validate.unobtrusive.js");
        bundles.Add(validationBundle);
    }

    private class NonOrderingBundleOrderer : IBundleOrderer
    {
        public IEnumerable<BundleFile> OrderFiles(BundleContext context, IEnumerable<BundleFile> files)
        {
            // do no ordering overrides; trust the provided enumeration
            return files;
        }
    }
You may also need <script>Globalize.culture("hu-HU")</script> in the relevant layout file.

fejesjoco wrote Dec 31, 2013 at 8:55 AM

I personally don't agree with providing a bad default behavior if that's the easiest. I don't have any non-trivial suggestions, except adding a hard dependency on the globalized validators or not using the built-in validators at all. It is broken my default, even that link says that it shouldn't be used. American developers are being misled because they may think they have a working validator for their culture, when in fact they get a validation that is browser specific and may accept 30/30/2008, and non-Americans will just find that it doesn't work at all.

If there is no default validation, it will raise the awareness of American and non-American developers alike to install a working validator library. And if there is a hard dependency, it could just work for everyone, given they are told how to include those scripts nicely. Sometimes I don't even recognize some packages that are added as dependencies, so I don't think it would be a big deal. But maybe the best would be if the jQuery validation package was bundled together with the globalization support, to me it seems to make little sense not to include it by default. Handling dates properly is a big deal in my opinion, and all the primitive type validations should just work by default, even if it meant adding a new dependency.

Anyway, thanks for the info and feel free to close the issue, I understand if it may not be solved here and now. I hope it will be solved someday, and until that I'll make it work in my project by using the globalized validators.

dougbu wrote Feb 12 at 9:09 PM

Proposed improvement we'll hopefully be able to provide in our next release:
  • Add another HtmlHelper property, right next to ClientValidationEnabled and Html5DateRenderingMode.
    • The property would be bool ClientDateValidationEnabled { get; set; }.
    • The property will default to true, to maintain current behavior by default -- no backward compatibility issue.
    • When the property is false, our helpers won’t generate data-val-date HTML attributes. This means sometimes-incorrect client-side validations of date values will be completely disabled.
  • Plumb this through ViewContext (to make it available to ClientDataTypeModelValidatorProvider). But, unlike ClientValidationEnabled, the new property doesn’t need to be visible in web.config files and so we shouldn't enable that option.
As a follow-up, we may wish to have writers create articles or posts about using jQuery.Validation.Globalization or Moment.js and perhaps how to convert client-side date validation into something akin to [Remote("IsDateValid", "ValidateController", areaName: null, HttpMethod="POST")].

yishaigalatzer wrote May 28 at 10:46 PM

Here is a link to a globalization mini guide by Hanselman.