12
public ActionResult SomeAction(int Id){
    //Id is set to 2

    var model = //get some thing from db using Id(2);
    //Now model.Id is set to 9;

    return View(model);
}

----------View----------
@Html.HiddenFor(x => x.Id)

When I view source this hidden field is set to 2 not 9. How do I get it to map to the model instead of mapping to the URL routing info?

P.S. I'd prefer not to rename parameters because then I lose my nice looking url's unless i change the routing info. I have done that and it does work, but not what I want.

tereško
  • 58,060
  • 25
  • 98
  • 150
MondayPaper
  • 1,569
  • 1
  • 15
  • 20
  • It seems to me you are not properly setting the model value before rendering the view. That seems to be the only way to describe what you are seeing. – Jeremy Holovacs Jan 05 '12 at 20:05
  • Have you tried putting an @model in your view? – Tin Can Jan 05 '12 at 20:07
  • Yes, I have several other "HiddenFor's" on the view which are all mapping correctly to the model. Only this one is mapping incorrectly. after I changed the action's parameter name from id to x_id it worked fine. But my url went from "/account/2" to "/account?x_id=2". – MondayPaper Jan 05 '12 at 20:10
  • What is "x" on the right side of the expression? x.Id? Unless you've decalred "x" you should be using "Model.Id". – Nick Bork Jan 05 '12 at 20:17
  • @Splash-X thats a standard lambda for using the Model. x (or any letter here) IS the model. his syntax is fine on that. – Adam Tuliper Jan 05 '12 at 20:21
  • Have you placed a break point on the line where you return the view and inspected the model to ensure that Id is in fact 9? – Nick Bork Jan 05 '12 at 20:26
  • Yes, I have checked that the model is set to 9 just before I send it to the client, then I can see in the HTML as well that the hidden field is set to 2. – MondayPaper Jan 05 '12 at 20:30
  • So I also assume that you put a break point in the View on a line where you could inspect the model and the Model says the value is "2"? – Nick Bork Jan 05 '12 at 20:35
  • Oh nice, I didn't know you could put a break point in the View. If my understanding is right of what nemesv said below, it would have shown that the model was actually 9, but that the lamba was using the ModelStateCollection instead of the model. So that would have been helpful to know. – MondayPaper Jan 05 '12 at 21:39

3 Answers3

25

When an Action gets called the framework builds a ModelStateCollection based on the query-string values, post-data, routing values etc. And this ModelStateCollection will be passed to the View. All the HTML input helpers try to the get the values from the ModelStateCollection first, before trying to get the values from the actual model.

Because your input model is the int id but the output model is some new model the helpers will use the values from the ModelStateCollection (from the query string) because the propery names Id are match.

To make it work you have to manually clear the ModelStateCollection before returning the new model to the view:

public ActionResult SomeAction(int Id){
    //Id is set to 2

    ModelState.Clear();

    var model = //get some thing from db using Id(2);
    //Now model.Id is set to 9;

    return View(model);
}
nemesv
  • 138,284
  • 16
  • 416
  • 359
  • 1
    good call, however be careful clearing modelstate in case theres anything in it you need (a reason to consider diff parameter name or model name here) – Adam Tuliper Jan 05 '12 at 20:53
  • This explains it in full detail: http://blogs.msdn.com/b/simonince/archive/2010/05/05/asp-net-mvc-s-html-helpers-render-the-wrong-value.aspx – Rhys Stephens Mar 13 '15 at 01:43
4

You could try this below

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

May not be exactly what you want but essentially does the same thing.

scartag
  • 17,548
  • 3
  • 48
  • 52
0

You can use TextBoxFor and make it hidden using CSS as

@Html.TextBoxFor(x => x.Id, new { @style="visibility:hidden; width:4px;"})

It worked for me.

Harjinder Singh
  • 23
  • 1
  • 10