Сложная ViewModel ASP.MVC 1.0 не заполняется на Action
Я за 3 дня изучаю MVC для нового проекта, и мне удалось натолкнуться на множество проблем, с которыми я столкнулся, - в основном, в такой простой вещи, как перемещение данных в представление и обратно в контроллер в типобезопасный (и управляемый) способ. Это последний.
Я видел это раньше, но ничего не советовал, кажется, работает. У меня сложная модель представления:
public class IndexViewModel : ApplicationViewModel
{
public SearchFragment Search { get; private set; }
public IndexViewModel()
{
this.Search = new SearchFragment();
}
}
public class SearchFragment
{
public string ItemId { get; set; }
public string Identifier { get; set; }
}
Это соответствует (главная страница индекса):
%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IndexViewModel>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<% Html.BeginForm("Search", AvailableControllers.Search, FormMethod.Post); %>
<div id="search">
<% Html.RenderPartial("SearchControl", Model.Search); %>
</div>
<% Html.EndForm(); %>
</asp:Content>
и UserControl:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<SearchFragment>" %>
<p>
<label for="itemId">
<%= Html.Resource("ItemId") %></label>
<%= Html.TextBox("itemId", Model.ItemId)%>
</p>
<p>
<label for="title">
<%= Html.Resource("Title") %></label>
<%= Html.TextBox("identifier", Model.Identifier)%>
</p>
<p>
<input type="submit" value="<%= Html.Resource("Search") %>" name="search" />
</p>
Это возвращается к следующему методу:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Search(IndexViewModel viewModel)
{
....
}
Моя проблема заключается в том, что когда модель представления повторно гидратируется из View в ViewModel, элементы SearchFragment становятся нулевыми. Я подозреваю, что это связано с тем, что механизм связывания модели по умолчанию не реализует элементы HTML ItemId и Identifier, визуализированные как встроенные в карте View в классе SearchFragment. Когда у меня есть два дополнительных свойства (ItemId и Identifier) в IndexViewModel, значения связаны правильно.
К сожалению, насколько я могу судить, я должен использовать SearchFragment, так как он мне нужен для строгого ввода Search UserControl... так как элемент управления можно использовать везде, где он может работать в любом родительском представлении.
Я действительно не хочу заставлять это использовать "волшебные последовательности". Слишком много всего происходит уже в ИМО.
Я попытался добавить префикс HTML к "Поиск". в надежде, что механизм связывания распознает "Search.ItemId" и будет соответствовать свойству IndexViewModel "Search" и ItemId внутри него, но это не работает.
Я боюсь, что мне придется написать свой собственный ModelBinder, чтобы сделать это, но, конечно, это должно быть что-то, что вы можете сделать из коробки??
В противном случае, есть ли другие предложения (или ссылка на кого-то, кто уже сделал это?)
Здесь надеемся....
Пока спасибо. Совершенно очевидно, что это довольно основное требование отсутствует в MVC:p
3 ответа
Я думаю, что ваша проблема может быть здесь:
public IndexViewModel()
{
this.Search = new SearchFragment();
}
Вы пытались оставить свой объект поиска пустым? Я знаю, что защищенный метод CreateModel в DefaultModelBinder не сработает, если значение уже нулевое, но я не уверен насчет установки свойств. Дайте ему шанс, если вы еще не попробовали это...
РЕДАКТИРОВАТЬ:
Я просто заметил:
<%= Html.TextBox("identifier", Model.Identifier)%
Должно быть:
<%= Html.TextBox("Search.Identifier", Model.Identifier)%
Мои первые мысли о том, что свойства SearchFragment не совпадают с регистром полей формы.
Я могу ошибаться, но это может стоить проверить.
Редактировать:
При дальнейшем изучении вы также можете рассмотреть тот факт, что форма использует SearchFragment, а View использует IndexViewModel - почему бы просто не использовать SearchFragment в качестве ViewModel?
Может быть, вы должны попробовать изменить свой метод действия на что-то вроде этого и сделать привязки вручную:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Search(FormCollection formCollection)
{
var viewModel = new IndexViewModel();
viewModel.Search.ItemId = formCollection[0];
viewModel.Search.Identifier = formCollection[1];
...
}
Но этот подход чем-то похож на создание собственного связующего.