2012-01-03 2 views
0

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

Проблема в том, что я всегда получаю нулевой объект как входящий параметр действия 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"> 
+0

Что такое сгенерированная HTML-разметка вашего 'Ajax.BeginForm()'? – eth0

+0

@ eth0: Я отредактировал свое оригинальное сообщение и добавил разметку HTML. – Furnica

ответ

1

Причина вы получаете нулевое значение для MyFilter аргумента ListResults действия происходит потому, что это то, что вы отправляете на сервер:

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

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

Я не могу увидеть код для данной модели объекта, но вы должны попытаться отправить каждый из параметров по отдельности, так что ModelBinder способен построить экземпляр 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. Вы видите их все время в Интернете. Например, see the URL for this link.

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

+0

Благодарим вас за советы, я боялся, что мне нужно это сделать :-(Объект SearchFilter имеет 10 свойств ... В любом случае, если у меня нет выбора, это то, что я буду делать. ** Интересно, есть ли способ не показывать все параметры вызываемого действия в адресной строке? ** Потому что это будет что-то вроде этого: '/ Products/ListResults? Category =" Ladies'shoes "& Color =" pink "& MinPrice = 10 & MaxPrice = 100 'и т. д. со всеми 10 фильтрами, которые будут применяться. – Furnica

+0

Ваш ответ очень подробный и помог мне понять и решить мою проблему. Большое вам спасибо. – Furnica

Смежные вопросы