数据绑定MVC3

I have no idea what am i doing wrong. Well i have this form, it's part of complex view.

    @{
    var filtersAjaxOptions = new AjaxOptions
        {
            HttpMethod = "POST",
            InsertionMode = InsertionMode.Replace,
            UpdateTargetId = "clientList-body",
            OnBegin = "clientList.filterRequestStart()",
            OnComplete = "clientList.filterRequestComplete()",
            OnSuccess = "clientList.filterRequestSuccess()"
        };
    }
    <span class="clientFilters-filterValue inlineBlock">
        @using (Ajax.BeginForm(
            "Index",
            "ClientList",
            new {
                ProductId = Model.ClientListViewModel.Filters.ProductId,
                ClientFilter = Model.ClientListViewModel.Filters.ClientFilter,
                BillFilter = Model.ClientListViewModel.Filters.BillFilter,
                DateSortType = Model.ClientListViewModel.Filters.DateSortType,
                SortDirection = Model.ClientListViewModel.Filters.SortDirection
            },
            filtersAjaxOptions,
            new
            {
                id = "clientListDateFilter-form"
            }
        ))
        {
            @Html.TextBoxFor(
                m => m.ClientListViewModel.Filters.BeginDateRange,
                new
                {
                    @class = "dp-input textInput inlineBlock",
                    id = "dp-billDateFilterStart",
                }
            )
            @Html.TextBoxFor(
                m => m.ClientListViewModel.Filters.EndDateRange,
                new
                {
                    @class = "dp-input textInput inlineBlock",
                    id = "dp-billDateFilterEnd",
                }
            )
        }
    </span>

Here's the filters model

    public class FilterModel
    {
        public FilterModel()
        {
            ClientFilter = ClientsEnum.All;
            BillFilter = ClientBillsEnum.All;
        }

        public string ProductId { get; set; }
        public ClientsEnum ClientFilter { get; set; }
        public ClientBillsEnum BillFilter { get; set; }
        public DateTime? BeginDateRange { get; set; }
        public DateTime? EndDateRange { get; set; }
        public DateSortType? DateSortType { get; set; }
        public SortDirection? SortDirection { get; set; }
    }

This part is ClientListController method Index:

    public ActionResult Index(FilterModel filters)
    {
        var clientListViewModel = GetClientListViewModel(filters, 1, 1, PageSize);
        if (ControllerContext.HttpContext.Request.IsAjaxRequest())
            return PartialView("Partial/ClientListBody", clientListViewModel);
        return View(clientListViewModel);
    }

Whenever i submit the form above, it turns to me that fields "BeginDateRange" and "EndDateRange" are null and other fields are set properly. Although, when i insert Request.Form in Watch, i can see the whole data.

UPDATE 1 So i set the <globalisation> in Web.config as this:

    <globalisation responseHeaderEncoding="utf-8" culture="en-US">

and yet it doesn't work. Very same result as before.

UPDATE 2 Also when i tried to put all the routevalues data into @Html.HiddenFor, controller saw only nulls. And again, Request.Form is filled prprly.

So the question is: how can i bind form data to incoming model? TY

Try this:

public ActionResult Index(FilterModel filters, FormCollection collection)
{
    UpdateModel(filters, "ClientListViewModel");
    var clientListViewModel = GetClientListViewModel(filters, 1, 1, PageSize);
    if (ControllerContext.HttpContext.Request.IsAjaxRequest())
        return PartialView("Partial/ClientListBody", clientListViewModel);
    return View(clientListViewModel);
}

And in view:

@Html.TextBoxFor(
            m => m.ClientListViewModel.FilterModel.EndDateRange,
            new
            {
                @class = "dp-input textInput inlineBlock",
                id = "dp-billDateFilterEnd",
            }
        )

You have strange naming. Also it would be better to use hidden fields then passing values through routevalues.

The default model binder uses the current culture datetime format when binding datetimes. This means that you have to enter the date into the proper format in your textboxes. On the other hand if you need a fixed format you could use a fixed culture in your web.config (<globalization> element) or write a custom model binder: https://stackoverflow.com/a/7836093/29407


UPDATE:

You need to specify the correct binding prefix because your input fields are named like ClientListViewModel.Filters.BeginDateRange but your controller action takes a FilterModel as parameter instead of the root view model:

public ActionResult Index([Bind(Prefix = "ClientListViewModel.Filters")] FilterModel filters)
{
    ...
}

But now this will break the other values, so you need to adjust your view as well:

@using (Ajax.BeginForm(
    "Index",
    "ClientList",
    null,
    filtersAjaxOptions,
    new
    {
        id = "clientListDateFilter-form"
    }
 ))
{
    @Html.HiddenFor(x => x.ClientListViewModel.Filters.ProductId)
    @Html.HiddenFor(x => x.ClientListViewModel.Filters.ClientFilter)
    @Html.HiddenFor(x => x.ClientListViewModel.Filters.BillFilter)
    @Html.HiddenFor(x => x.ClientListViewModel.Filters.DateSortType)
    @Html.HiddenFor(x => x.ClientListViewModel.Filters.SortDirection)

    @Html.TextBoxFor(
        m => m.ClientListViewModel.Filters.BeginDateRange,
        new
        {
            @class = "dp-input textInput inlineBlock",
            id = "dp-billDateFilterStart",
        }
    )
    @Html.TextBoxFor(
        m => m.ClientListViewModel.Filters.EndDateRange,
        new
        {
            @class = "dp-input textInput inlineBlock",
            id = "dp-billDateFilterEnd",
        }
    )
}

or if you want to send them as part of the form url instead if using hidden fields:

@using (Ajax.BeginForm(
    "Index",
    "ClientList",
    new RouteValueDictionary 
    { 
        { "ClientListViewModel.Filters.ProductId", Model.ClientListViewModel.Filters.ProductId },
        { "ClientListViewModel.Filters.ClientFilter", Model.ClientListViewModel.Filters.ClientFilter },
        { "ClientListViewModel.Filters.BillFilter", Model.ClientListViewModel.Filters.BillFilter },
        { "ClientListViewModel.Filters.DateSortType", Model.ClientListViewModel.Filters.DateSortType },
        { "ClientListViewModel.Filters.SortDirection", Model.ClientListViewModel.Filters.SortDirection },
    },
    filtersAjaxOptions,
    new RouteValueDictionary
    {
        { "id", "clientListDateFilter-form" }
    }
 ))
{
    @Html.TextBoxFor(
        m => m.ClientListViewModel.Filters.BeginDateRange,
        new
        {
            @class = "dp-input textInput inlineBlock",
            id = "dp-billDateFilterStart",
        }
    )
    @Html.TextBoxFor(
        m => m.ClientListViewModel.Filters.EndDateRange,
        new
        {
            @class = "dp-input textInput inlineBlock",
            id = "dp-billDateFilterEnd",
        }
    )
}