How can I make sure that model binding will work as expected?

I am programming in C # ASP.NET MVC4 (Razor engine). I need to create a partial view and reuse it in several places. The problem is that the view is a form, and in some cases I will need to use it with the ViewModel. My question is how model binding will work because in ViewModel this is a property of a property. Example:

public class PersonModel { public string FirstName { get; set; } public string LastName { get; set; } } public class OfficeViewModel { public PersonModel Person { get; set; } // other properties } 

A partial view for PersonModel will be:

 @model SomeNameSpace.PersonModel @Html.TextBoxFor(m => m.FirstName) @Html.TextBoxFor(m => m.LastName) 

When this view is displayed, it will look like this:

 <input type="textbox" id="FirstName" name="FirstName" /> <input type="textbox" id="LastName" name="LastName" /> 

Now I want to use the same view with my OfficeViewModel. In this case, I would do this in my Office view:

 @{ Html.RenderPartial("Person", Model.Person); } 

When this partial view is displayed, it will be displayed as shown above. If I had NOT reused this view, my Office view would look like this:

 @model SomeNameSpace.OfficeViewModel @Html.TextBoxFor(m => m.Person.FirstName) @Html.TextBoxFor(m => m.Person.LastName) 

This will display as:

 <input type="textbox" id="Person_FirstName" name="Person.FirstName" /> <input type="textbox" id="Person_LastName" name="Person.LastName" /> 

Note that the name attribute has the Person prefix property. So, if I use the RenderPartial parameter and pass to Model.Person, will the connecting device know where to bind FirstName and LastName in OfficeViewModel?

If the model’s middleware is smart enough to check the properties of the properties, what happens when I have ManagerModel and EmployeeModel in OfficeViewModel, and both of them have properties named FirstName and LastName?

I hope I was simple and thankful in advance.

+4
source share
3 answers

@ Herald is right. The default value of RenderPartial will not help. Although you can write a user helper that takes care of this problem:

 public static MvcHtmlString PartialFor<TModel, TProperty>(this HtmlHelper<TModel> helper, System.Linq.Expressions.Expression<Func<TModel, TProperty>> expression, string partialViewName) { string name = ExpressionHelper.GetExpressionText(expression); object model = ModelMetadata.FromLambdaExpression(expression, helper.ViewData).Model; var viewData = new ViewDataDictionary(helper.ViewData) { TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = name } }; return helper.Partial(partialViewName, model, viewData); } 

Use it in a view:

 @Html.PartialFor(x => x.Person, "Person") 
+2
source

Unfortunately, Html.RenderPartial does not transfer the information necessary for the correct field names to appear in this situation.

If you want to reuse a partial view this way, look at using Editor Templates with Html.EditorFor instead. Like others * For helpers, EditorFor accepts a lambda expression that allows you to transfer the name of the property passed to the template.

+4
source

Found the answer here: fooobar.com/questions/24677 / ...

Basically, I need to install ViewData.TemplateInfo.HtmlFieldPrefix .

So, I added the PersonModel property and named it HtmlFieldPrefix . Example:

 public class PersonModel { public string HtmlFieldPrefix { get; set; } public string FirstName { get; set; } public string LastName { get; set; } } 

Then in my partial view I do this:

 @model SomeNameSpace.PersonModel @{ ViewData.TemplateInfo.HtmlFieldPrefix = Model.HtmlFieldPrefix; } @Html.TextBoxFor(m => m.FirstName) @Html.TextBoxFor(m => m.LastName) 

In my controller action, I can do this:

 model.HtmlFieldPrefix = "Person"; return View("_Person", model); 

Now my visualization will look like this:

 <input type="textbox" id="Person_FirstName" name="Person.FirstName" /> <input type="textbox" id="Person_LastName" name="Person.LastName" /> 

If you leave the .HtmlFieldPrefix model to zero, the view will display as:

 <input type="textbox" id="FirstName" name="FirstName" /> <input type="textbox" id="LastName" name="LastName" /> 

So this fixes my problem and allows me to use a partial view using ViewModels.

0
source

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


All Articles