2009-11-30 3 views
0

Я играю с приложением ASP.NET MVC, и у меня возникла проблема. Я довольно новичок в ASP.NET MVC и едва понимаю основы, чтобы заставить вещи работать на этом этапе.ASP.NET MVC: привязка к нескольким моделям

У меня есть PersonModel, PersonController и куча представлений, которые позволяют пользователю добавлять нового человека, редактировать человека и искать людей.

Я не использую базу данных на заднем конце. Все, что я делаю, зависит от внешней DLL, которая возвращает структуры «person» (что я превращаю в PersonModels).

Для того, чтобы искать людей, я должен предоставить персональную структуру, которая действует как критерии поиска для метода во внешней DLL. Метод возвращает коллекцию человеческих структур, которые соответствуют критериям поиска. Если я хочу получить всех людей в системе, я поставлю пустую человеческую структуру для метода.

Итак, у меня есть функция «получить все люди», но я хотел бы предоставить расширенный поиск.

Мой поиск Просмотр привязывается к классу, который содержит 2 свойства:

Public Class PersonSearchModel 
    Private _searchCriteria As PersonModel 
    Private _searchResults As List(Of PersonModel) 
    Public Property SearchCriteria As PersonModel 
    Get 
     return _searchCriteria 
    End Get 
    Set(ByVal value As PersonModel) 
     _searchCriteria = value 
    End Set 
    End Property 
    Public Property SearchResults As List(Of PersonModel) 
    Get 
     return _searchResults 
    End Get 
    Set(ByVal value As List(Of PersonModel)) 
     _searchResults = value 
    End Set 
    End Property 
End Class 

Теперь поиск Просмотр привязывается к этому PersonSearchModel и у меня есть 2 секции ... раздел, в котором пользователь может предоставить критерии поиска и раздел, в котором отображаются результаты поиска.

У меня возникла проблема с привязкой PersonSearchModel.SearchCriteria к элементам управления, используемым для отображения/сбора критериев поиска Person.

Я не могу найти критерии поиска.

Это то, что у меня есть на мой взгляд, для критериев поиска:

<fieldset> 
     <legend>Search Criteria</legend> 
     <% 
      With Model.SearchCriteria 
     %> 
     <div style="float:left"> 
     <p> 
      <label for="FirstName"> 
       FirstName:</label> 
      <%=Html.TextBox("FirstName", Html.Encode(.FirstName))%> 
      <%= Html.ValidationMessage("FirstName", "*") %> 
     </p> 
     <p> 
      <label for="LastName"> 
       LastName:</label> 
      <%=Html.TextBox("LastName", Html.Encode(.LastName))%> 
      <%= Html.ValidationMessage("LastName", "*") %> 
     </p> 
     <!-- More controls --> 
     </div> 
     <% End With%> 
    </fieldset> 
    <%=Html.ActionLink("Search", "Search",Model.SearchCriteria)%> 
<!-- The Search Results Section--> 

PersonModel передается в метод поиска является новой/пустой PersonModel объекта. Он не содержит данные, введенные пользователем.

Что я здесь делаю неправильно?

********** Редактировать ********** Я попытался изменить вид для привязки по-разному. Я удалил VB «С»:

<fieldset> 
     <legend>Search Criteria</legend> 
     <div style="float:left"> 
     <p> 
      <label for="FirstName"> 
       FirstName:</label> 
      <%=Html.TextBox("FirstName", Html.Encode(.FirstName))%> 
      <%= Html.ValidationMessage("FirstName", "*") %> 
     </p> 
     <p> 
      <label for="LastName"> 
       LastName:</label> 
      <%=Html.TextBox("LastName", Html.Encode(.LastName))%> 
      <%= Html.ValidationMessage("LastName", "*") %> 
     </p> 
     <!-- More controls --> 
     </div> 
    </fieldset> 
    <%=Html.ActionLink("Search", "Search",Model.SearchCriteria)%> 
<!-- The Search Results Section--> 

Но это не помогло.

Я также попытался:

<fieldset> 
     <legend>Search Criteria</legend> 
     <div style="float:left"> 
     <p> 
      <label for="FirstName"> 
       FirstName:</label> 
      <%=Html.TextBox("Model.SearchCriteria.FirstName", Html.Encode(Model.SearchCriteria.FirstName))%> 
      <%= Html.ValidationMessage("FirstName", "*") %> 
     </p> 
     <p> 
      <label for="LastName"> 
       LastName:</label> 
      <%=Html.TextBox("Model.SearchCriteria.LastName", Html.Encode(Model.SearchCriteria.LastName))%> 
      <%= Html.ValidationMessage("LastName", "*") %> 
     </p> 
     <!-- More controls --> 
     </div> 
    </fieldset> 
    <%=Html.ActionLink("Search", "Search",Model.SearchCriteria)%> 
<!-- The Search Results Section--> 

И:

<fieldset> 
     <legend>Search Criteria</legend> 
     <div style="float:left"> 
     <p> 
      <label for="FirstName"> 
       FirstName:</label> 
      <%=Html.TextBox("SearchCriteria.FirstName")%> 
      <%= Html.ValidationMessage("FirstName", "*") %> 
     </p> 
     <p> 
      <label for="LastName"> 
       LastName:</label> 
      <%=Html.TextBox(".SearchCriteria.LastName")%> 
      <%= Html.ValidationMessage("LastName", "*") %> 
     </p> 
     <!-- More controls --> 
     </div> 
    </fieldset> 
    <%=Html.ActionLink("Search", "Search",Model.SearchCriteria)%> 
<!-- The Search Results Section--> 

Однако, я все еще получаю пустую/новую PersonModel передается в метод поиска в контроллере. Я также проверил PersonSearchModel.SearchCriteria, чтобы узнать, может ли это содержать введенные значения, но у этого также есть новый/пустой PersonModel.

-Frinny

ответ

0

С помощью отражения в значительной степени то, что модель вяжущих MVC настроено делать, я думаю, что вы не именование поля правильно, чтобы, когда они отправили обратно в действие они не карты до ваших параметров. Попробуйте сделать что-то вроде:

Function Search(ByVal personSearchModel As PersonSearchModel, ByVal collection As FormCollection) As ActionResult 

Тогда ваши поля (HTML) должны называться так:

<%= Html.TextBox("personSearchModel.SearchCriteria.FirstName", Html.Encode(Model.SearchCriteria.FirstName)) %> 
+0

Не уверен, что вы здесь делаете. Я немного смущен вашим выбором имени переменной ... имя переменной соответствует типу. Поэтому я не уверен, что вы пытаетесь сказать мне совместить имя переменной с именем поля или если вы говорите мне, чтобы я соответствовал типу объекта. Я попробую в обоих направлениях и посмотрю, что произойдет. Спасибо за ваш ответ. – Frinavale

+0

Большое спасибо. Оказывается, это имя переменной должно совпадать. Я, вероятно, должен выбрать книгу по этой теме, вместо того, чтобы сначала пробовать руки. Еще раз спасибо! – Frinavale

+0

Я смотрю на свои другие виды (редактирование и создание), и я не указываю имя переменной в именах полей для этих представлений ... но я все еще получаю объект полностью заполненного человека, переданный в качестве параметра к методам «создать» или «отредактировать». Почему это так? – Frinavale

0

Я думаю, что вам не хватает необходимых префиксов на призывы к Html.TextBox и Html.ValidationMessage.Я рекомендую не, используя ключевое слово VB «С», так как оно скрывает полное имя участника. Как HTML-помощники, так и привязка к модели (которая используется для передачи параметров в методы действия), требуется полное имя свойства или поля для извлечения значения.

Попробуйте вместо этого:

<%= Html.TextBox("SearchCriteria.FirstName", SearchCriteria.FirstName) %> 
<%= Html.ValidationMessage("SearchCriteria.FirstName", "*") %> 

Кроме того, нет необходимости вызывать Html.Encode() для значения передаются в TextBox - он получает автоматически кодируется в любом случае.

+0

Я удалил VB.NET и попробовал код, который вы рекомендовали. Я также пробовал <% = Html.TextBox («Model.SearchCriteria.FirstName», Model.SearchCriteria.FirstName)%> Но это не помогло. Я все еще ничего не меняю: я все еще получаю новый/пустой PersonModel в методе поиска. – Frinavale

+0

Вы должны просто использовать Html.TextBox («SearchCriteria.FirstName») (не префикс строки с помощью «Model.», И вам также не нужно передавать явное значение - помощник TextBox будет автоматически извлекаться Это. – Eilon

+0

Контроллер по-прежнему получает пустой/новый PersonMode. Пожалуйста, ознакомьтесь с оригинальным вопросом, потому что я обновил его, чтобы включить то, что еще я пробовал. – Frinavale

0

После долгих испытаний и отладки я обнаружил что-то интересное: я могу получить информацию, введенную пользователем, из FormCollection, переданного в функцию поиска. Первоначально моя функция поиска взяла 2 параметра. Первым параметром был PersonModel, который предположительно привязан к PersonSearchModel.SearchCriteria, вторым параметром был FormCollection для представления.

Я могу создать PersonModel, используемый для PersonSearchModel.SearchCriteria на основе FormCollection, переданного в функцию поиска. Я удалил первый параметр (PersonModel), поскольку он всегда был новым/пустым.

Это мой текущий метод поиска:

<AcceptVerbs(HttpVerbs.Post)> _ 
Function Search(ByVal collection As FormCollection) As ActionResult 
     Dim searchModel As New SearchPersonsModel 

     Dim personProperties() As PropertyInfo = GetType(PersonModel).GetProperties 
     For Each pi As PropertyInfo In personProperties 
      Dim piName As String = pi.Name 
      Dim info As String = Array.Find(collection.AllKeys, Function(x) x.Compare(piName, x, true) = 0) 
      If String.IsNullOrEmpty(info) = False Then 
       pi.SetValue(searchModel.SearchCriteria, collection.Item(info), Nothing) 
      End If 
     Next 
'The following code uses the searchModel.searchCriteria to search for People. 
End Function 

My View (если любопытно) выглядит следующим образом:

<% Using Html.BeginForm()%> 
<%With Model.SearchCriteria%> 
    <fieldset> 
    <legend>Search Criteria</legend> 
     <div style="float: left"> 
     <p> 
      <label for="FirstName">FirstName:</label> 
      <%=Html.TextBox("FirstName", Html.Encode(Model.SearchCriteria.FirstName))%> 
      <%=Html.ValidationMessage("Model.SearchCriteria.FirstName", "*")%> 
     </p> 
     <p> 
      <label for="LastName">LastName:</label> 
      <%=Html.TextBox("LastName", Html.Encode(Model.SearchCriteria.LastName))%> 
      <%=Html.ValidationMessage("Model.SearchCriteria.LastName", "*")%> 
     </p> 
     <!---..... more controls .... --> 
    </div> 
    </fieldset> 
    <%End With%> 
    <input type="submit" value="Search" /> 

<!-- Search Results Controls --> 

    <%End Using%> 

Это решение работает, но я действительно не доволен. Почему я должен воссоздать PersonModel, используемый в качестве критериев поиска? Почему я не могу передать этот объект в качестве параметра в метод поиска?

-Frinny

0

Походит UpdateModel() может быть вашим другом здесь. MVC не передает объекты в стиле веб-форм.

Даже если ваша модель состоит из двух объектов, вполне возможно использовать UpdateModel для извлечения значений для одного из них. Вам просто нужно указать этот объект как параметр. Например:

Thing t = new Thing(); 
UpdateModel(t); 

Возможно, вам придется искать имена параметров, чтобы позволить MVC правильно угадывать. Кроме того, вам могут потребоваться свойства белых списков по соображениям безопасности и/или избежать слишком сильной проверки модели.

+0

Я пробовал это, но он все еще не работает. Я искал метод UpdateModel, и похоже, что он должен работать ... но по какой-то причине он все равно передает новый/пустой объект. – Frinavale

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