1

I want to test the data picket on my asp.net mvc web application.

1.So I created the following test model:-

public class TestClass
    {
        [DataType(DataType.Date)]
        public DateTime D { get; set; }
    }

2.I added the following script:-

  $(function () {
    $(".datefield").datepicker();
});

3.And on my view I have the folliwng :-

@model MvcApplication6.Models.TestClass


@Html.EditorFor(item=>item.D)

Now the calender will be displayed well, but I have these two problems:-

1.If inside the action method I specify the data time to equal today date as follow:-

 public ActionResult Index()
            {
                TestClass t = new TestClass();
               t.D = DateTime.Now.Date;

                return View(t);
            }

Then the calender it will switch the day & month, so 12 june become 6 december as follow:- enter image description here

2.If I remove the dataitme to be equal to today date I will get the following default value:-

01/01/0001

3.If I specify the datetime to allow null, and i do not specify any defualt value I will get the following exception

[DataType(DataType.Date)]
        public DateTime? D { get; set; }

The model item passed into the dictionary is null, but this dictionary requires a non-null model item of type 'System.DateTime'.

So can anyone advice on what is causing these three problems ? Thanks

EDIT Ok i changed my property to be String instead of date-time , as follow:-

[DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
        public string CreateDate { get; set; }

But this did not solve the data validation , and still i can not enter date such as 26/06/2014 !! so i try to remove the [DataType(DataType.Date)] so my property becomes:-

    [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
    public string CreateDate { get; set; }

but in this way the date picker will not be populated,, since the date picker is defined to get populated on fields of type date,, i think i am missing something , in my understanding to the way things should work ??

John John
  • 1
  • 72
  • 238
  • 501
  • but if i chnage the format of the defualt date inside my date picker to be dd/mm, then .net Datetime will read it as mm/dd ? is this right? as the default format for the Datetime is mm/dd ? – John John Jun 12 '14 at 12:57

3 Answers3

5

The main problem is localization. The datepicker widget takes by default the localization set by your browser, which I'm guessing is set to "English US" and has the date format as "MM/DD/YYYY". The documentation specifies that the default date format of the widget is "mm/dd/yy". Please note that the date format of the jQuery DatePicker is different from that used by the .Net Framework. Change the constructor:

$(function () {
    $(".datefield").datepicker({ dateFormat: "dd/mm/yy" });
});

The problem however will shift to the jQuery Validation plugin, which might not understand what's happening. You can get around by either writing your own validation method and overwriting the default one, or using strings instead of actual dates.


EDIT (addressing your edit):
Please checkout this fidlle. I'm not doing anything special to it. There's just an input element with a specific value "13/06/2014" (June 13th 2014). When you click inside the input, the jQuery Datepicker pops-up and has the correct date selected.

You now have a string property in your model. You don't need to have any other data annotations that refer to DateTime objects. Razor will create an input element for your property and set the value inside. That's it. The only thing that you need to do, is to convert the actual DateTime object, loaded from the database, with the appropriate format:

public ActionResult DisplayMyData()
{
    MyModelType model = new MyModelType();
    DateTime createDateDBObject = //get the date from your database

    model.CreateDate = createDateDBObject.ToString("dd/MM/yyyy");
    //or, for setting the current date
    //model.CreateDate = DateTime.Now.ToString("dd/MM/yyyy");

    return View(model);  
}

This next fiddle shows you how to make your input as readonly. This means that the user cannot directly type in a date. They must use the Datepicker instead. Which in turn means that you will always have the correct date format ("dd/MM/yyyy") returned to the controller.


EDIT no. 2 (addressing the template) I'm actually glad you created your own template for DateTime. This is what I always do and requires little effort for solving a relatively big problem. In our (your) case, this makes things even simpler. What you need to do is to tell the Razor engine to use the template you wrote for the DateTime objects. For this, just add a DataType attribute to every property that represents a "string date":

[DataType("your_template_name")]
public string CreateDate { get; set; }

Additionally, if in your template you set @model DateTime please change to @model string. If you intend to use classes as selectors for jQuery ($(".datefield")) make sure that your template sets the class on every input.

Andrei V
  • 7,306
  • 6
  • 44
  • 64
  • Correct and spot on answer - and funnily enough, this is exactly what I do on various projects and clients of mine. – Ahmed ilyas Jun 12 '14 at 12:26
  • Unfortunately so do I :) – Andrei V Jun 12 '14 at 12:28
  • @johnG, you can try setting the format on the DateTime property of your model. Please have a look at [this answer](http://stackoverflow.com/questions/11272851/format-datetime-in-asp-net-mvc-4). If you decide to go with strings instead of dates you just need to parse the string using the "dd/MM/yyyy" format. – Andrei V Jun 12 '14 at 12:58
  • so if i chnage the values to be .datepicker({ dateFormat: "dd/mm/yy" }); . how will this value get added inside the database as dd/mm/yy or as the defualt value mm/dd/yy ? since the default format for the asp.net mvc Datetime is mm/dd , and if i chnage the format for my datepicker willnot solve the problem. so i need to chnage the defualt format for the DateTime also ? – John John Jun 12 '14 at 12:58
  • 1
    There's no easy way when dealing with localization, especially when using different frameworks, with different "views" concerning dates. I would recommend that you use strings instead of dates, configure the `datepicker` with the format you need and inside your controller, parse the string into a `DateTime` using that format. Additionally, make the `input` read-only; you can then be sure that you'll always have the correct format (set by the `datepicker`). Remember that you know the format and that you can use it to convert your "model string" into a `DateTime` object. – Andrei V Jun 12 '14 at 13:08
  • @AndreiV I have noted that if i select 1 june 2014 from calender it will be saved inside the DB as 6 January 2014 (the day & month will be exchnaged) !!! not sure what is the standard way of dealing with dates , starting from selecting it from the calender , mapping it to asp.net then adding it to sql server ?? – John John Jun 12 '14 at 14:10
  • @johnG: I think I wasn't explaining it clear enough. If you set the format date of the `datepicker` to "dd/mm/yy", you will see the 1st of June as "01/06/2014" (my birthday, btw.) in your `input`. If you change your property to `public string D { get; set; }`, in your controller action you will get back a string, namely `01/06/2014`. (1/2) – Andrei V Jun 12 '14 at 14:21
  • @johnG: Now, since you know the format you use, you can just parse it before you save it in the database: `DateTime theDate = DateTime.ParseExact(model.D. "dd/MM/yyyy", CultureInfo.InvariantCulture);`. The value of `theDate` can now be saved to the database. When retrieving the data from the database, convert the `DateTime` to string. (2/2) – Andrei V Jun 12 '14 at 14:21
  • not sure if i understand what do u mean . as currently i changed both the date picker and the proprty to be dd/mm/yyyy, but it will be populated inside the DB as year-month-day and the month and day will be exchanged . second problem i am facig is that incase i select as data such as 26/06/2014 , i will get a format error from the model binder that 26/06/2014 is not a valid Date !!! – John John Jun 12 '14 at 14:45
  • The "yyyy-mm-dd" is the SQL standard and has nothing to do with how you store your dates inside a programing environment. What API do you use for database interaction? Entity Framework? ADO.Net? Both APIs will correctly read the value of a date from teh database and will correctly create a `DateTime` object. This interaction between with the database has nothing to do with the way in which you display your dates with jQuery. As far as I understand from your question, your problem regards formating the value with jQuery and getting the right value back. This is exactly what my answer proposes. – Andrei V Jun 12 '14 at 18:25
  • i am using entity framework , and currently i chnaged both the date picker format and the proprty format to be dd/mm/yyyy. but when i select a date such as 26/06/2014 i will get a validation error that 26/6/2014 is not a valid date, and if a enter a date such as 01/06/2014 it wil be stored as 06/01/2014 inside the sql server !! – John John Jun 13 '14 at 10:02
  • 1
    @johnG, I'm starting to think that you do not read what I post, so this will be the last time I'm going to say this: change the type of your property from `DateTime` to `string`. This will "deactivate" the jQuery Validator method for dates on your property. The validator will see the property as a string and will not bicker about an invalid date format. Please read my answer and comments carefully. – Andrei V Jun 13 '14 at 10:09
  • @AndreiV but i do not want to change the date to be string ,, i still want the jquery validation on dates .. – John John Jun 13 '14 at 10:45
  • 1
    @johnG, if the validation of your date is the only problem, as I wrote before, make your input field `readonly`. You're using jQuery Datepicker so you'll always have a *valid* date. If the user is not able to edit the date directly but only trough the widget, then there's nothing left to validate. Except if there's a date selected, which can be achieved by using the `[Required]` attribute on your model. – Andrei V Jun 13 '14 at 10:50
  • @AndreiV can you check my edit inside my original question ,, thanks – John John Jun 13 '14 at 11:16
  • @AndreiV Ok in your approach i will have to manually add the script to each field that should contain a date. but in my original approach which did not work, i have created an Editor template which will automatically populate a Datepicker on all the Date field .but i think in your approach i have to add this code $(".datefield").datepicker on all the string fields that should contain Date ?? did u get my problem ?? – John John Jun 13 '14 at 11:46
  • @johnG, that's not really a problem; it's part of the "better" solution. See my edit. – Andrei V Jun 13 '14 at 12:01
  • but changing the Model Datetime to be Model string ,, will break my template code !! – John John Jun 13 '14 at 13:18
1

1) Problem

cause :your browser/JQUI take by default dd/mm/yy and you are passing mm/dd/yy format .

there fore this problem occured Solution

public ActionResult Index()
            {
                TestClass t = new TestClass();
               t.D = DateTime.Now.ToString("MM/dd/yyyy");

                return View(t);
            }

OR same as @andri

  $(".datefield").datepicker({ dateFormat: "dd/mm/yy" });

2)If I remove the dataitme to be equal to today date I will get the following default value:

cause :You take date time as datatype .therefore you cant assign any value then it will take by default 01/01/0001

Solution Assign value ,same as 1 solution

3)cause you give date time datatype there fore it needed any value as date time format

MSTdev
  • 4,507
  • 2
  • 23
  • 40
0

You can change date to desired formats in action results as per below:

public ActionResult Index()
            {     
TestClass t = new TestClass();
            string dt = DateTime.Now.ToString("MM/dd/yyyy");
            t.D = DateTime.ParseExact(dt, "d/MM/yyyy", null, System.Globalization.DateTimeStyles.None);
            return View(t);
}
ashish
  • 247
  • 2
  • 3