0

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

Vladislav Qulin
  • 1,872
  • 1
  • 17
  • 20

2 Answers2

1

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",
        }
    )
}
Community
  • 1
  • 1
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
0

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.

karaxuna
  • 26,752
  • 13
  • 82
  • 117
  • >> Also it would be better to use hidden fields then passing values through routevalues. - why? – Vladislav Qulin Aug 24 '12 at 06:49
  • m => m.ClientListViewModel.Filters.EndDateRange you have ClientListViewModel and Filters. It would be better -> ClientListViewModel.FilterModel – karaxuna Aug 24 '12 at 06:53
  • Well that sounds legit. And what about hidden fields and routevalues? – Vladislav Qulin Aug 24 '12 at 06:57
  • You will be able to manipulate with hidden fields easily. It's only my concern about hidden fields vs routevalues – karaxuna Aug 24 '12 at 06:59
  • This form only have responsibility to operate with date ranges. So routevalues in this case are some sort of incapsulation principle) – Vladislav Qulin Aug 24 '12 at 07:02
  • @VladislavQulin can you show me how Request.Form is filled (or formcollection names)? Binding depends on that names. Then i will surely help you – karaxuna Aug 24 '12 at 07:20