35

In my ASP.net MVC app I have a view that looks like this:

...
<label>Due Date</label>
<%=Html.TextBox("due")%>
...

I am using a ModelBinder to bind the post to my model (the due property is of DateTime type). The problem is when I put "01/01/2009" into the textbox, and the post does not validate (due to other data being input incorrectly). The binder repopulates it with the date and time "01/01/2009 00:00:00".

Is there any way to tell the binder to format the date correctly (i.e. ToShortDateString())?

2
  • I hit this yesterday as well. I wish they had an overload that let you pass in a format string. Commented Sep 25, 2008 at 14:27
  • I think the solution provided here is cleaner: stackoverflow.com/questions/8089316/… Commented Mar 29, 2012 at 9:24

12 Answers 12

55

I just came across this very simple and elegant solution, available in MVC 2:

Link

Basically if you are using MVC 2.0, use the following in your view.

 <%=Html.LabelFor(m => m.due) %>
 <%=Html.EditorFor(m => m.due)%>

then create a partial view in /Views/Shared/EditorTemplates, called DateTime.ascx

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<System.DateTime?>" %>
<%=Html.TextBox("", (Model.HasValue ? Model.Value.ToShortDateString() : string.Empty), new { @class = "datePicker" }) %>

When the EditorFor<> is called it will find a matching Editor Template.

Sign up to request clarification or add additional context in comments.

2 Comments

This worked for me, but surely it will replace all instances of DateTimes... what if you have different formatting requirements for different instances?
@saw-lau: you can create multiple templates as above with different names, then pass in the template name as the second argument to Html.EditorFor() as required.
24

Decorate the property in your model with the DataType attribute, and specify that its a Date, and not a DateTime:

public class Model {
  [DataType(DataType.Date)]
  public DateTime? Due { get; set; }
}

You do have to use EditorFor instead of TextBoxFor in the view as well:

@Html.EditorFor(m => m.Due)

Comments

9

It's a dirty hack, but it seems to work.

<%= Html.TextBoxFor(model => model.SomeDate,
    new Dictionary<string, object> { { "Value", Model.SomeDate.ToShortDateString() } })%>

You get the model binding, and are able to override the HTML "value" property of the text field with a formatted string.

3 Comments

me likey. short and sweet. here's my slight variation: <%= Html.TextBoxFor( model => model.SomeDate, new { @Value = Model.SomeDate.ToShortDateString() } )%>
+1 for both of you, this little trick saved me a lot of time :).
Does not work with client side validation enabled, as that one will use the date from the model and if it is different in format for that locale it's validating against, it will block the submit.
4

I found this question while searching for the answer myself. The solutions above did not work for me because my DateTime is nullable. Here's how I solved it with support for nullable DateTime objects.

<%= Html.TextBox(String.Format("{0:d}", Model.Property)) %>

2 Comments

Wrong, @Quoo's answer works perfectly with nullable DateTime too. Just tested it.
Look at the dates, internet hero. His answer was posted over a year after mine.
4

Why don't you use

<% =Html.TextBox("due", Model.due.ToShortDateString()) %>

1 Comment

Corin wants to input date and not just show date. The issue is related to binding date in the required format.
3

First, add this extension for getting property path:

public static class ExpressionParseHelper
{
    public static string GetPropertyPath<TEntity, TProperty>(Expression<Func<TEntity, TProperty>> property)
    {                       
         Match match = Regex.Match(property.ToString(), @"^[^\.]+\.([^\(\)]+)$");
         return match.Groups[1].Value;
    }
}

Than add this extension for HtmlHelper:

 public static MvcHtmlString DateBoxFor<TEntity>(
                this HtmlHelper helper,
                TEntity model,
                Expression<Func<TEntity, DateTime?>> property,
                object htmlAttributes)
            {
                DateTime? date = property.Compile().Invoke(model);
                var value = date.HasValue ? date.Value.ToShortDateString() : string.Empty;
                var name = ExpressionParseHelper.GetPropertyPath(property);

                return helper.TextBox(name, value, htmlAttributes);
            }

Also you should add this jQuery code:

$(function() {
    $("input.datebox").datepicker();
});

datepicker is a jQuery plugin.

And now you can use it:

<%= Html.DateBoxFor(Model, (x => x.Entity.SomeDate), new { @class = "datebox" }) %>

ASP.NET MVC2 and DateTime Format

Comments

1

In order to get strongly typed access to your model in the code behind of your view you can do this:

public partial class SomethingView : ViewPage<T>
{
}

Where T is the ViewData type that you want to pass in from your Action.

Then in your controller you would have an action :

public ActionResult Something(){
    T myObject = new T();
    T.Property = DateTime.Today();

    Return View("Something", myObject);
}

After that you have nice strongly typed model data in your view so you can do :

<label>My Property</label>
<%=Html.TextBox(ViewData.Model.Property.ToShortDateString())%>

1 Comment

Thanks for the reply. I am aware of strongly typed pages and the benefits they bring, I believe this is more applicable in an editing view. I was specifically after information that is applicable to using a modelbinder (in a creation view) .
1

I find the best way to do this is to reset the ModelValue

ModelState.SetModelValue("due", new ValueProviderResult(
       due.ToShortDateString(), 
       due.ToShortDateString(), 
       null));

Comments

0

I guess personally I'd say its best or easiest to do it via a strongly typed page and some defined model class but if you want it to be something that lives in the binder I would do it this way:

public class SomeTypeBinder : IModelBinder
{
    public object GetValue(ControllerContext controllerContext, string modelName,
                              Type modelType, ModelStateDictionary modelState)
    {
        SomeType temp = new SomeType();
        //assign values normally
        //If an error then add formatted date to ViewState
        controllerContext.Controller.ViewData.Add("FormattedDate",
                              temp.Date.ToShortDateString());
    }
}

And then use that in the view when creating the textbox i.e. :

<%= Html.TextBox("FormattedDate") %>

Hope that helps.

Comments

0

This worked for me: mvc 2

<%: Html.TextBoxFor(m => m.myDate, new { @value = Model.myDate.ToShortDateString()}) %>

Simple and sweet!

A comment of user82646, thought I'd make it more visible.

Comments

0

Try this

<%:Html.TextBoxFor(m => m.FromDate, new { @Value = (String.Format("{0:dd/MM/yyyy}", Model.FromDate)) }) %>

Comments

0

MVC4 EF5 View I was trying to preload a field with today's date then pass it to the view for approval.

ViewModel.SEnd = DateTime.Now    //preload todays date  
return View(ViewModel)           //pass to view

In the view, my first code allowed an edit:

@Html.EditedFor(item.SEnd)        //allow edit

Later I changed it to just display the date, the user cannot change it but the submit triggers the controller savechanges

 <td>
 @Html.DisplyFor(item.SEnd)       //show no edit
 </td>

When I changed to DisplayFor I needed to add this to ensure the preloaded value was passed back to the controller. I also need to add HiddenFor's for every field in the viewmodel.

    @Html.HiddenFor(model => model.SEnd)     //preserve value for passback.

Beginners stuff but it took a while to work this out.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.