Сложная 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];
   ...
}

Но этот подход чем-то похож на создание собственного связующего.

Другие вопросы по тегам