Using the same partial view Multiple times on the same parent view

I am using an MVC3 razor. I have a scenario where I need to partially view several points several times on the same parent view. The problem I am facing is that when I view the parent view, it generates the same names and identifiers of the input controls in these partial views. Since my partial views are tied to different models, when the view is sent to Save, it will work. Any idea how I can make identifiers / names of controls unique, maybe some of them are prefixed?

Expectation

Nabel

+6
source share
2 answers

Personally, I prefer to use editor templates as they take care of this. For example, you might have the following presentation model:

public class MyViewModel { public ChildViewModel Child1 { get; set; } public ChildViewModel Child2 { get; set; } } public class ChildViewModel { public string Foo { get; set; } } 

and the following controller:

 public class HomeController : Controller { public ActionResult Index() { var model = new MyViewModel { Child1 = new ChildViewModel(), Child2 = new ChildViewModel(), }; return View(model); } [HttpPost] public ActionResult Index(MyViewModel model) { return View(model); } } 

and inside the Index.cshtml :

 @model MyViewModel @using (Html.BeginForm()) { <h3>Child1</h3> @Html.EditorFor(x => x.Child1) <h3>Child2</h3> @Html.EditorFor(x => x.Child2) <input type="submit" value="OK" /> } 

and the last part is the editor template ( ~/Views/Home/EditorTemplates/ChildViewModel.cshtml ):

 @model ChildViewModel @Html.LabelFor(x => x.Foo) @Html.EditorFor(x => x.Foo) 

Using EditorFor , you can include a template for various properties of your main view model and correct names / identifiers. In addition to this, you will get the correct populated model of your view in the POST action.

+5
source

There is an alternative:

  • Add Prefix to PartialView
  • Snap model by removing prefix

For 1, set the prefix in your view:

 ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = "prefix"; 

For 2, you can restore data using UpdateModel , for example:

 UpdateModel(producto, "prefix"); 

This is not very desirable, because your action does not receive data as a parameter, but later updates the model. This has several inconveniences: 1) it is not clear what your action needs, looking at its signature. 2) It is not easy to provide input for action for unit testing. 3) the action is vulnerable to overflow parameters (parameters provided by the user that should not be there and mapped to the model).

However, there is an alternative for 2: register a custom mediator that allows you to remove the prefix. And the custom binder model needs to know about it.

A good solution to this is SO Q & A: How do I handle the MVC model binding prefix with the same shape repeated for each row in the collection? But it has a small drawback: if you add a hidden field named "__prefix" in the partial view, and you render it several times as a partial view, this identifier will be repeated for several different elements on the page, which is unacceptable, and can cause some problems . And one of the most important reasons for providing a prefix is ​​the same as editing, as partial views for multiple instances of an object. That is, this will happen on a page like gmail, where you can edit several emails at once.

There are several possible solutions to this problem.

One of them provides a prefix in the form of a query string or a routedata value, and not as a form field that avoids identifier conflicts and can be found using a binder. (He can always have the same name).

Another solution is to use a hidden field with a fixed template, but for each rendered view it is different. The prefix could follow this pattern for uniqueness: "PP $ ActionControllerId", like "PP $ EditProduct23", which is unique for each rendered view and can be easily found between query parameters that start with "PP $".

And the final solution would be to create a prefix only in the view and not provide it in any query parameter. The model’s connecting device should look for a prefix that checks the names of the request parameters until it finds one whose prefix matches the pattern.

Of course, the custom ModelBinder must be adapted to work on the selected agreement.

+2
source

Source: https://habr.com/ru/post/891441/


All Articles