9

I need to store in th SQL-Server DB a date format "29-12-2014" using datepicker but I get the message The field XXX must be a date.

My last try was Regular Expression:

Model #1:

[RegularExpression(@"([3][0,1]|[0-2]\d)-([1][0-2]|[0]\d)-(\d\d\d\d)", ErrorMessage = "Valor inválido.")]
public Nullable<DateTime> ETD { get; set; }

Model #2:

[DataType(DataType.DateTime)]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd-MM-yyyy}")]
public Nullable<DateTime> ETD { get; set; }

View:

<div class="editor-field">
    @Html.TextBoxFor(model => model.ETD)
    @Html.ValidationMessageFor(model => model.ETD)
</div>

jQuery:

$(function () {
     $("#ETD").datepicker();
});

I always get the message "The field ETD must be a date."

Any idea?

Thanks.

Patrick
  • 2,995
  • 14
  • 64
  • 125

3 Answers3

7

Its my understanding that the format 'dd-MM-yyyy' is the problem, here. The jquery unobtrusive validation is trying to instantiate a new Date(strVal) object, and it doesn't know what to do with the string '29-12-2014'.

See Unobtrusive validation in Chrome won't validate with dd/mm/yyyy

magritte answered that redefining the unobtrusive validator's date method, using the jQuery Globalize library, to parse with the desired format string should solve the issue:

$.validator.methods.date = function (value, element) {
    return this.optional(element) || Globalize.parseDate(value, "dd-MM-yyyy", "en");
}

Update

I recreated your problem locally, and was able to replicate the 'required field validation not firing prior to form post' issue, when the Globalization library was not installed. Once I installed and loaded the library, the front-end worked as expected, with unobtrusive validation accepting the modified dd-MM-yyyy date.

The library can be installed using the NuGet package manager and the following package: http://www.nuget.org/packages/jquery-globalize/. Then you need to update your html to include the globalize.js script.

The back-end was another story, which is going to rely on your local machine's globalization profile. I am assuming you are running a non-en/us machine where this format might parse? My machine is english/us and does not natively parse the modified date format, however using the below command, I successfully got a valid datetime:

DateTime.ParseExact(Request.Form["ETD"], "dd-MM-yyyy", System.Globalization.CultureInfo.InvariantCulture);
Community
  • 1
  • 1
DanS
  • 792
  • 5
  • 10
  • Hi thanks but if I apply this code to my page, all other Required fields in the View are ignored and the page is submited – Patrick Mar 13 '14 at 16:27
  • Sounds like there's a javascript error-- check your console. You would need to download/include the jQuery globalize library for this to work. https://github.com/jquery/globalize and on NuGet @ http://www.nuget.org/packages/jquery-globalize/ – DanS Mar 13 '14 at 16:30
  • Hi thanks but it seems that the answer from @sipwiz is working fine for me, jQuery.validator.methods["date"] = function (value, element) { return true; }, so any idea why yours in not working? it seems the same. What can be the consequences in other parts of the site regarding validation? maybe none because we are applying only to date types? – Patrick Mar 13 '14 at 17:02
  • From a high level overview, it appears that 'return true' will validate -any- input as valid, defeating the point of validation entirely.Did you try installing the globalization plugin? I haven't implemented your particular solution locally, but if you are able to post any JavaScript errors from your console, it would probably help. – DanS Mar 13 '14 at 17:06
  • I don't have any error, only the message from the jquery.validate.unobtrusive library. But maybe as I have the format defined "dd-MM-yy" in the datepicker jQuqery plug-in I don't have to worry about anything else? – Patrick Mar 13 '14 at 17:15
  • @Patrick updated w/ some further info. I'm able to get it working locally-- You can check the installation of the globalization library in a JavaScript console by seeing if the variable 'Globalize' is defined. – DanS Mar 13 '14 at 18:30
  • What files do I need to put the Globalize.parseDate function working for my country's format dd-MM-yy? – Patrick Mar 13 '14 at 19:01
  • @Patrick Updated answer. You need the NuGet package installed, and to include the globalize.js. That should hopefully get your front-end working. – DanS Mar 13 '14 at 20:13
  • Working fine, thanks. I have also decorated the ValidationMessageFor with the message in any case of invalid format because the "[DataType(DataType.Date, ErrorMessage = "Formato de data inválido.")]" don't pass the message to the View. I'm gona set your answer as correct but also put the complete solution. Thanks again for your help ;) – Patrick Mar 14 '14 at 10:42
2

This should work to set your format in the box:

$("#ETD").datepicker({
    dateFormat    : 'dd-mm-yy'
});

Is the validation message coming from jQuery or C#? See this answer with respect to the former: https://stackoverflow.com/a/19519745/1803682

Community
  • 1
  • 1
Matthew
  • 9,851
  • 4
  • 46
  • 77
  • Hi thanks, but I had already test this but did not solve the problem. For now I think DanS response solves it – Patrick Mar 13 '14 at 17:04
  • Agreed - I upvoted @DanS as it is a better specific implementation of the solution I linked (*I think*). – Matthew Mar 13 '14 at 17:08
2

With the help of @DanS I was able to elaborate a solution for the Date Validation for my country, Portugal (pt-PT) and here is the complete solution for anybody that have a problem validating a date:

First of all, you need to install the nuget package:

http://www.nuget.org/packages/jquery-globalize/

Then include in the page where you want to make the validation (or in the Bundle like me) the links to the core library and your country's culture file (note:put always first the core and then the culture file or else you will get an undefined error)

bundles.Add(new ScriptBundle("~/bundles/saida").Include(
            "~/Scripts/Presenter/Saida/create.js",
            "~/Scripts/Globalize/globalize.js",
            "~/Scripts/Globalize/Cultures/globalize.culture.pt-PT.js",
            "~/Scripts/Common/date.js"));

Set the Model:

[Required(ErrorMessage = "Preenchimento obrigatório.")]
[DataType(DataType.Date)]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd-MM-yyyy}")]
[Display(Name = "Data da DAU")]
public DateTime? DAUData { get; set; }

I did not put any ErrorMessage in the DataType property because it's not passed to the View, instead, you can put a custom message in the View:

<div class="editor-field">
    @Html.EditorFor(model => model.DAUData)
    @Html.ValidationMessageFor(model => model.DAUData, "Formato de data inválido.")
</div>

But if you use the jQuery datepicker function with the definition of the format, you don't need to worry about the format:

$(function ()
{
    $(".datefield").datepicker({ dateFormat: 'dd-mm-yy', changeYear: true });
});

The property changeYear is to presente a dropdown to choose the year (not mandatory, only a nice option to garanty that the value is always valid), and don't forget to inlcude the jQuery and jQueryUI references in your file to presente the calendar correctly.

To complete the client side script, I have the culture's format validation:

$.validator.methods.date = function (value, element)
{
    return this.optional(element) || Globalize.parseDate(value, "dd-MM-yyyy", "pt-PT");
 }

I also have a template for the date format in the View (place it in the Shared/EditorTemplates/ folder and don't forget to user the @Html.EditorFor razor method in the View:

@{
    var value = "";

    if (Model.HasValue) 
    {
        value = String.Format("{0:d}", Model.Value.ToString("dd-MM-yyyy"));
    }
}

@Html.TextBox("", value, new { @class = "datefield", type = "text", autocomplete = "off"     })

Now anytime that you will need a date, use the Template, and the class "datepicker", and that's it!

Thanks again DanS ;)

Patrick
  • 2,995
  • 14
  • 64
  • 125
  • Glad you got it up and running! Globalization & formatting is always a tricky problem to solve :-D – DanS Mar 14 '14 at 13:28