0

I am using MVC 3 final RTM.

Given

This route:

context.MapRoute(
    "Blog_Posts",
    "Blog/Posts/{id}/{slug}",
    new { controller = "Posts", action = "Index", slug = UrlParameter.Optional }
);

And on a post's page, e.g. /blog/posts/2/some-slug I bind a partial view with a Comment model:

@Html.Partial("_CommentEditor", new Comment())

And Comment has a public int Id {get; set;}.

And in the partial view, I have this:

@Html.HiddenFor(comment => comment.Id)

Why does it display this?

<input type="hidden" value="2" name="Id" id="Id" data-val-required="The Id field is required." data-val-number="The field Id must be a number." data-val="true">

And why when I change Id on Comment to CommentId does it correctly have a value of 0?

Me thinks the default model binder is binding to the {id} of the route.

kamranicus
  • 4,207
  • 2
  • 39
  • 57

4 Answers4

2

That's happens because when you are using HTML helpers such as HiddenFor they first look at route data and model state and after that in the model. So they find in your route data a parameter id=2 and use this value instead of the id=0 in the model you are passing.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • Thanks, this would explain the issue. I switched to using `CommentId` instead. I've also seen issues with using `SomeAction(SomeRequestClass request)` as a variable parameter into an Action where it *attempts* to populates it as a `HttpContext.Current.Request` object, is that the same thing? I have not seen it myself, just was mentioned by a co-worker having issues. – kamranicus Mar 19 '11 at 15:57
  • **Just a suggestion:** Since I always use `Id` as property name in my entity classes I rather renamed route variable to `identifier`. Seems easier. Naming convention of `Comment.CommentId` seems unnecessary and plain stupid. It's like as if I'd ask you about your name: **Darin, what's your name?** – Robert Koritnik Mar 19 '11 at 17:39
  • Funny you mention that Robert, I just started a project at work and when I tried using `id` in my action method parameters I kept getting errors. I found out my team switched it to `identifier` so they were smarter than me :) Luckily I am using SubSonic so it's easy to change it back to `Id`. – kamranicus Mar 23 '11 at 12:15
1

It is a bug or it might not because of below implemented logic;

In Asp.NET MVC, a View engine uses ViewData (it is variable and its type is "ViewDataDictionary"). And this ViewData has 2 properties "ModelState" that holds routing values, and "Model" that holds our actual model object.

  1. A View engine looks into "ModelState" object retrieving value of a property.
  2. If found in step 1 then return value.
  3. Else looks into "Model" object to retrieve value for a property.

In above case, route has property "id" and its value are saved in "ModelState" so it return value from "ModelState" instead of binded model.

For above scenario, any input control renders with unexpected value.

Resolution is:

<div class="postData" value='@Model.Id'/>

//use below jquery function to retrieve data
var postedData = $('.postData');
vrluckyin
  • 1,026
  • 8
  • 15
0

If you're using linq to sql, fields marked as provided by database cannot be set manually.

Nick Larsen
  • 18,631
  • 6
  • 67
  • 96
0

Try:

Try @Html.Partial("_CommentEditor", new Comment{Id = 0}) 
Paul
  • 12,392
  • 4
  • 48
  • 58
  • The other thing I would try is using a Command/ViewModel. You can read more about it here:http://geekswithblogs.net/michelotti/archive/2009/10/25/asp.net-mvc-view-model-patterns.aspx I generally never user my actual Entities in my views. To cut down the left to right you can use Automapper: http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/01/22/automapper-the-object-object-mapper.aspx – Paul Mar 19 '11 at 17:05
  • Thanks Paul; I did end up using a ViewModel eventually for other reasons to make my life easier. I should use AutoMapper now that you mention it. – kamranicus Mar 23 '11 at 12:13