tags:

views:

6606

answers:

9

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())?

+1  A: 

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())%>
slude
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) .
Corin
A: 

Since I can't comment apparently I'll respond here:

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.

slude
+3  A: 

Why don't you use

<% =Html.TextBox("due", Model.due.ToShortDateString()) %>
Casper
Corin wants to input date and not just show date. The issue is related to binding date in the required format.
goths
A: 

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)) %>
Craig M
+1  A: 

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

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

First, add this extension for getting property path:

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 extensions for HtmlHalper:

 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" }) %>

http://stackoverflow.com/questions/2227742/asp-net-mvc2-and-datetime-format/2238204#2238204

Сергій
A: 

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.

Cephas
+15  A: 

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

http://geekswithblogs.net/michelotti/archive/2010/02/05/mvc-2-editor-template-with-datetime.aspx

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.

Nick Chadwick
This worked perfectly for me, thank you.
Xenph Yan
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
@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.
Nick Chadwick
A: 

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

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

Quoo