MVC3 - значение параметра всегда нулевое - PullRequest
0 голосов
/ 03 января 2012

Я пытаюсь создать представление "расширенный поиск", используя два частичных представления и Ajax.Я определил сущность «SearchFilter», имеющую в качестве свойств все доступные критерии поиска.При отправке в частичном представлении «_Filter» (AjaxOption OnSuccess) мне нужно передать его в действие «ListResults», которое обновляет частичное представление «_Results».

Проблема в том, что я всегда получаю нулевое значениесущность как входящий параметр действия ListResults.

Код выглядит следующим образом:

AdvancedSearchView.cshtml

@model MyApp.ViewModels.SearchFormViewModel
@{
    ViewBag.Title = "Advanced search";
}
    <div id="divFilter">
        @Html.Partial("_Filter", Model)
    </div>
    <div id="divResults">
        @Html.Partial("_Results", Model.ResultsList)
    </div>

_Filter.cshtml

@model MyApp.ViewModels.SearchFormViewModel
<script type="text/javascript">
    function getForm(url, divName) {
        var obj = new Date();
        url = (url.indexOf('?', 0) != -1) ? url + '&uid=' + obj.getTime() : url + '?uid=' + obj.getTime();
        $.get(url, function (data) {
            $("#" + divName).html(data);
        });
    }
</script>

    @using (Ajax.BeginForm("Search", null, new AjaxOptions
    {
        UpdateTargetId = "divFilter",
        InsertionMode = InsertionMode.Replace,
        OnSuccess="getForm('"+Url.Action("ListResults", "Products", new { myFilter = Model.CurrentFilter}) + "','divResults')"
    }, new { id = "idSearchForm" }))
    {
        <fieldset style="width: 800px; line-height: 1.4em;">
            <legend>Configure your search filters</legend>
        ...
        </fieldset>
        <input type="submit" value="Rechercher" class="submit" style="width: 280px" />
    }

Контроллер

    public ActionResult Search()
    {
SearchFilter currentFilter = new SearchFilter();
List<Product> filteredProductsList = repository.FindProducts_Filtered(currentFilter);
          return View("AdvancedSearchView", new AdvancedSearchFormViewModel(currentFilter, filteredProductsList/* , necessary select lists */));
    }

    [HttpPost]
    public ActionResult Search(AdvancedSearchFormViewModel model)
    {
        SearchFilter currentFilter = model.CurrentFilter;
        // set the necessary select lists

        List<Product> filteredProductsList = repository.FindProducts_Filtered(currentFilter);
        return PartialView("_Filter", AdvancedSearchFormViewModel(currentFilter, filteredProductsList/* , necessary select lists */));
    }

    public ActionResult ListResults(SearchFilter myFilter)
    {
        List<Product> filteredProductsList = repository.FindProducts_Filtered(currentFilter);
        return PartialView("_Results", filteredProductsList);
    }

Модель представления

public class AdvancedSearchFormViewModel
    {
        // Properties
        public SearchFilter CurrentFilter { get; set; }
        public List<Product> ResultsList { get; set; }
        // some SelectLists

        // Constructor

        public AdvancedSearchFormViewModel()
        {}

        public AdvancedSearchFormViewModel(SearchFilter pCurrentFilter, List<Product> pResultsList, /* necessary select lists*/)
        {
            CurrentFilter = pCurrentFilter;
            ResultsList = pResultsList;
            // the SelectLists
        }
    }

У меня нет сомнений, что я что-то не так делаю, но не вижу, что это такое.

Сгенерированная разметка HTMLиз BeginForm выглядит так:

<form action="/Products/Search" data-ajax="true" data-ajax-mode="replace" data-ajax-success="getForm(&#39;/Products/ListResults?myFilter=MyApp.Models.SearchFilter&amp;uid=2622ea0e-d7dc-48fa-b65d-519978ee40b3&#39;,&#39;divResults&#39;)" data-ajax-update="#divFilter" id="idSearchForm" method="post">

1 Ответ

1 голос
/ 03 января 2012

Причина, по которой вы получаете нулевое значение для аргумента myFilter действия ListResults, заключается в том, что вы отправляете на сервер следующее:

/Products/ListResults?myFilter=MyApp.Models.SearchFilter&uid=2622ea0e-d7...

Устройство привязки по умолчанию пытается перевернуть строку "MyApp.Models.SearchFilter "в экземпляр MyApp.Models.SearchFilter, чего он не может сделать.

Я не вижу код для этого объекта модели, но вы должны попробовать отправить каждый из параметров по отдельности, чтобы связыватель модели мог создать экземпляр SearchFilter из его свойств:

OnSuccess="getForm('"+Url.Action("ListResults", "Products", new { 
    Prop1 = Model.CurrentFilter.Prop1, 
    Prop2 = Model.CurrentFilter.Prop2, 
    etc...
})...

Обновление после комментария 1

Чтобы ответить на ваш вопрос об отображении значений параметров в URL-адресе, именно так работает HTTP.Если вы не хотите показывать какие-либо параметры, отправленные на сервер в URL-адресе, вам нужно будет выполнить HTTP POST вместо HTTP GET.

Однако всякий раз, когда ваша операция идемпотентна, вы должны использовать HTTP GET.HTTP POST должен быть зарезервирован для случаев, когда отправка ввода должна каким-то образом изменять состояние приложения.На самом деле я не согласен с тем, что вы используете [HttpPost] для вашего public ActionResult Search(AdvancedSearchFormViewModel model) метода действия.Поскольку все, что он делает - возвращает данные для просмотра, это идемпотентное действие.

Тем не менее, ничто не мешает вам нарушить это правило и выполнить HTTP POST вместо GET.Лично я не вижу проблемы с параметрами URL.Вы видите их все время в Интернете.Например, см. URL-адрес этой ссылки .

HTTP не понимает сложные объекты, только текст. Чтобы отправлять данные для сложных объектов по HTTP, им нужноразбить на их текстовые части.Чтобы отправлять такие данные через HTTP GET, они должны быть в URL.

...