Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET Core using two models in single form

I am using Tuple to pass two models inside the view like code given below.

@model Tuple<AdvanceSearchModel, List<SearchUserModel>>
<form role="search" method="post" action="/Public/AdvanceSearch">
            <div class="form-group">
                <label>Name</label>
                <input name="FullNames" type="text" class="form-control" value=""/>
            </div>
            <div class="form-group">
                <label>Product</label>
                <input name="Products" type="text" class="form-control" value="" />
            </div>
            <div class="form-group">
                <label>Location:</label>
                <input name="Location" type="text" class="form-control" value="" />
            </div>
            <div class="form-group">
                <label>State</label>
                <input name="States" type="text" class="form-control" value="" />
            </div>
            <div class="form-group">
                <label>Country</label>
                <input name="Countries" type="text" class="form-control" value=""/>
            </div>
        </form>

All the name attributes inside inputs are of AdvanceSearchModel. How do I use tag helper such as asp-for when passing multiple model to the views containing one or multiple forms? Also how do I retain values of the form after submitting the form in above scenario?

like image 571
Bhavesh Jadav Avatar asked Nov 08 '22 01:11

Bhavesh Jadav


1 Answers

As you can see in the source code of InputTagHelper

You can see it creates the name attribute based on the (lambda) expression in html-tag:asp-for.

what you need

You need a form name tag like this SearchUserModel[0].Location

Where:

  • SearchUserModel is the property name on the model which is in the controller method you post to
  • [0] is the index in the list
  • Location is the property on the iten in the list the SearchUserModel instance

My suggestion

Not to do

  1. Extend the InputTagHelper and add a prefix option (which adds a prefex to the name).
  2. Use a view model Not a tuple!
  3. Create a partial view that only takes SearchUserModel + a prefix (like an int for which row in the list it is for example: usermodel[1])
  4. In your view loop over the list and call the partial.

result

@model SearchUserModel
<input asp-for="Location" my-prefix="ListItem[@Model.Id]" class="form-control" />

Better longterm option

  1. Make a HTML template on how SearchUserModel part of the form should look.
  2. Do ajax call to get the data or put the data as json in your view. (or take step 3 from what not to do)
  3. Generate the form with well structured javascript.
  4. On submit Instead of submitting the form, parse the from to json and send this as json ajax call.

Why do i say this? It is easier to debug if you get weird databindings in your controller.

That said, option 1 is perfectly fine but it might lead to problems later, as it is very static template, you wont be able to add or remove rows easily.

References for proper html name tags for lists:

  • http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx
  • How does MVC 4 List Model Binding work?
like image 82
Joel Harkes Avatar answered Nov 14 '22 22:11

Joel Harkes