ASP.NET MVC: привязка к нескольким моделям - PullRequest
0 голосов
/ 30 ноября 2009

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

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

Я не использую базу данных в серверной части. Все, что я делаю, зависит от внешней DLL, которая возвращает структуры "человек" (которые я превращаю в 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

Теперь представление поиска привязывается к этой модели PersonSearch, и у меня есть 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, переданный в метод Search, является новым / пустым объектом 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

Ответы [ 4 ]

0 голосов
/ 08 декабря 2009

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

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

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

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

0 голосов
/ 08 декабря 2009

После долгих испытаний и отладки я обнаружил кое-что интересное: я могу извлечь информацию, введенную пользователем, из 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

Мой взгляд (если вам интересно) выглядит так:

 <% 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 голосов
/ 08 декабря 2009

Использование отражения - это почти то, для чего предназначены привязки модели 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 голосов
/ 01 декабря 2009

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...