Search code examples
asp.netasp.net-mvc-5mvc-editor-templates

Missing data when submit with DateTime and editor template in MVC5


I'm new in MVC. I use editor template for create 3 textbox for day, month, year for datetime type. Main View:

    @model mvc3date.Models.SomeDate

...

<html>
...
<body>
    @using (Html.BeginForm()) 
    { ...
            <div class="form-group">
                @Html.LabelFor(model => model.oneday, new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.oneday)
                    @Html.ValidationMessageFor(model => model.oneday)@**@
                </div>
            </div>
...}

    <div>
        @Html.ActionLink("Back to List", "Index")
    </div>
</body>
</html>

Editor Template:

@model DateTime?
...
    <td>@Html.TextBox("", (Model.HasValue ? Model.Value.ToString("dd") : string.Empty)) </td>
    <td class="separator">/</td>
    <td>@Html.TextBox("", (Model.HasValue ? Model.Value.ToString("MM") : string.Empty))</td>
    <td class="separator">/</td>
    <td>@Html.TextBox("", (Model.HasValue ? Model.Value.ToString("yyyy") : string.Empty))</td>

My problem not done when I try to change editor template to:

    <td>@Html.TextBox("Day", (Model.HasValue ? Model.Value.ToString("dd") : string.Empty)) </td>
    <td class="separator">/</td>
    <td>@Html.TextBox("Month", (Model.HasValue ? Model.Value.ToString("MM") : string.Empty))</td>
    <td class="separator">/</td>
    <td>@Html.TextBox("Year", (Model.HasValue ? Model.Value.ToString("yyyy") : string.Empty))</td>

With new editor template, validation for model.oneday return true and can be submit this form. But when submit, the value of oneday is null! How to fix this problem?


Solution

  • Your first EditorTemplate is creating 3 textboxes with the name oneday When you submit the form, the DefaultModelBinder tries to set the value of oneday to the first value it sees (a 1 or 2 digit number) which of course fails (try setting DateTime oneday = 7; yourself). Even if by magic it did succeed, the other 2 values would be ignored anyway.

    In the second EditorTemplate your controls have name="Day",name="Month" and name="Year". If you inspect Response.Form you will see these name/value pairs but since you model does not have any properties named Day, Month or Year then nothing is bound (they are just ignored).

    In unclear why you would want to do this, especially as you cant use client side validation, but you either need

    1. A view model with 3 properties, for Day, Month and Year so that you can strongly bind to the properties using html helpers. In the POST method you can then construct the date based on the 3 properties.
    2. Manually add the (unbound) html as you are doing in the second template, and write your own custom ModelBinder that reads the form data values and builds the date. An example is shown in this article.