ASP.NET MVC 3 Model Identifier Using Route Identifier Value

Scenario
Route: / template / customize / 10 Where: 10 = template identifier ()

In the controller, the model is created based on the template, so the View model is actually a Customization () object, which actually has the identifier 0, because it is new.

In the view, I render @ Html.HiddenFor (m => m.Id), and the resulting value for this hidden input is 10 , although it should be 0 because m is of type Customization. I came across this before with MVC 2 and worked around it without using helper methods.

Questions

  • Is there an annotation or something else that can add the Html Helper method to really make the right value?

  • Is this a mistake (it seems MVC rendering m.Id as a route value no matter what actual model is installed in the controller)?

Additional code for clarification

View

@model Project.Core.Domain.Customization @using( Html.BeginForm( "save", "customization" ) ) { @Html.HiddenFor( m => m.Id ) @Html.HiddenFor( m => m.Template.Id ) <button type="submit" id="save" name="save">Save</button> } 

controller

  public ActionResult Customize( int id ) { var template = Persistence.Data.RetrieveObject<Template>( id ); var model = new Customization(); ViewBag.Template = template; return ( View( model ) ); } 

Decision

Action signature changed:

 public ActionResult Customize( int TemplateId ){ ... } 

Changed the link to the action as such:

 @Html.ActionLink( "customize", "customize", new { TemplateId = template.Id } ) 

I get a url that looks like

 /template/customize?TemplateId=10 

It's uglier, but I get my view to be clear with the model. So this is a victory for me.

+4
source share
3 answers

I think this is because when you use something like @Html.HiddenFor( m => m.Id ) , the html helpers look in different places to fill in the input value, and the values ​​in the route are one of these places

This way you can either change your route to look like template/customize/{TemplateId} , and then your action method reflects this, for example. public ActionResult Customize(int templateId) .

OR you could change your view model (or create a custom view model) that has the CustomizationId property, not just the Id .

And no, this is not a mistake ... it is rather a function that can have unforeseen consequences. But once you realize this, it works like a pleasure.

+2
source

In this case, you can always not use the HTML helper and use plain HTML instead:

<input name="Id" id="Id" type="hidden" value="@Model.Id"/>

+5
source

To prevent route values ​​from exceeding the corresponding model properties, call ModelState.Clear() on your controller action. Be careful to call this method after using / reading the state of the model.

 public ActionResult Customize( int id ) { var template = Persistence.Data.RetrieveObject<Template>( id ); var model = new Customization(); ViewBag.Template = template; this.ViewData.ModelState.Clear(); // add that after you consume the ModelState return ( View( model ) ); } 

For my part, hidden input gets the model value instead of the route value.

0
source

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


All Articles