ASP.NET MVC: Multiple Models in a View

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Frinavale
    Recognized Expert Expert
    • Oct 2006
    • 9749

    ASP.NET MVC: Multiple Models in a View

    I'm playing with an ASP.NET MVC application and I've run into a bit of a problem. I am pretty new to ASP.NET MVC and just barely understand the basics to get things to work at this point.

    I have a PersonModel, a PersonControlle r, and a bunch of views that let a user add a new person, edit a person and search for people.

    I am not using a DataBase in the back end. Everything I'm doing depends on an external DLL that returns "person" structures (that I turn into PersonModels).

    In order to search for people, I have to provide a person-structure that acts as search criteria to a method in the external DLL. The method returns a collection of person-structures that match the search criteria. If I want to retrieve all of the people in the system I supply an empty person-structure to the method.

    So, I have the "retrieve all people" function working.....but I'd like to provide an advanced search.

    My Search View is bound to a class that contains 2 properties:

    Code:
    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
    Now the Search View binds to this PersonSearchMod el and I have 2 sections...a section where the user can provide search criteria and a section that displays the search results.

    I am having a problem binding the PersonSearchMod el.SearchCriter ia to the controls used to display/gather the Person search criteria.

    I cannot retrieve the search criteria.

    This what I have in my view for the search criteria:
    Code:
     <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-->
    The PersonModel passed into the Search method is a new/empty PersonModel Object. So all of the people in the system are returned and displayed but that's not what is supposed to happen. The search is supposed to return Persons that match the search criteria. But it's always empty.

    What am I doing wrong here?

    -Frinny
  • Frinavale
    Recognized Expert Expert
    • Oct 2006
    • 9749

    #2
    After much testing and debugging I discovered something interesting: I can retrieve the information entered by the user from the FormCollection passed into the Search Function. Originally my search function took 2 parameters. The first parameter was the PersonModel that was supposed bound to the PersonSearchMod el.SearchCriter ia, the second parameter was the FormCollection for the view.

    I am able to create the PersonModel used for the PersonSearchMod el.SearchCriter ia based on the FormCollection passed into the Search function. I removed the first parameter (the PersonModel) since it was always a new/empty object.

    This is my current Search method:
    Code:
    <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 line uses the searchModel.searchCriteria to search for People.
    End Function
    My View (if your curious) looks like:

    Code:
     <% 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%>
    This solution works but I am really not happy with it.
    This seems ridiculous to me!

    Why do I have to recreate the PersonModel used as the search criteria?

    Why can't I pass the PersonModel (the search criteria) into the Search function?

    -Frinny

    Comment

    • Frinavale
      Recognized Expert Expert
      • Oct 2006
      • 9749

      #3
      I doubt anyone's interested in this thread but I'm going to keep updating it regardless.

      I finally found a better answer to my problem. I add the first parameter back into the Saerch method. Recall that originally the first parameter was the PersonModel that I was using as the search criteria, now I'm passing a SearchPersonsMo del instead.

      What I discovered is that I have to use the name of this parameter in the names for the controls that I'm using in the View to display/gather the search criteria.

      It's hard to explain so here's an example of what I'm talking about.

      Here is my current Search method:
      Code:
      <AcceptVerbs(HttpVerbs.Post)> _
      Function Search(ByVal searchModel As SearchPersonsModel, ByVal collection As FormCollection) As ActionResult      
        '...Code that uses the searchModel.searchCriteria to search for People...
        'Displaying the results
        View(searchModel)
      End Function
      Here is my Search View:
      Code:
       <% Using Html.BeginForm()%>
       <%With Model.SearchCriteria%>
        <fieldset>
          <legend>Search Criteria</legend>
            <div style="float: left">
              <p>
                <label for="FirstName">FirstName:</label>
                <%=Html.TextBox("searchModel.SearchCriteria.FirstName", Html.Encode(Model.SearchCriteria.FirstName))%>
                 <%=Html.ValidationMessage("Model.SearchCriteria.FirstName", "*")%>
              </p>
              <p>
                  <label for="LastName">LastName:</label>
                  <%=Html.TextBox("searchModel.SearchCriteria.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%>
      Note that the TextBoxes are named "searchModel.Se archCriteria.Fi rstName" and "searchModel.Se archCriteria.La stName".

      "searchMode l" is the name of the first parameter in the Search method. These have to match.

      Now when the user clicks the "Search" submit button, ASP.NET MVC creates and populates the SearchPersonsMo del that is passed it as the "searchMode l" parameter in my Search method. It creates and populates the Object using reflection. This all has something to do with Binders.

      I am currently researching Binder Objects because even though I'm happy that I don't have to use reflection to populate my model based on the form collection, I'm still not 100% happy with the "magic" that is happening behind the scenes here.

      -Frinny

      Comment

      • sanjib65
        New Member
        • Nov 2009
        • 102

        #4
        Mvc

        I'm following your thread with interest and want to learn MVC. As it is completely new concept in ASP.NET I'll be grateful if you kindly let me know where can I get to know the basics? Thanks in advance :)

        Comment

        • Frinavale
          Recognized Expert Expert
          • Oct 2006
          • 9749

          #5
          I think the best place to start would be Microsoft's ASP.NET MVC website.

          -Frinny

          Comment

          • sanjib65
            New Member
            • Nov 2009
            • 102

            #6
            MVC Learning

            I checked and bookmarked. Yes, that's the good place to start with MVC. Many thanks.

            Comment

            Working...