Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET MVC 3 Model Id using Route Id value

Scenario
Route: /template/customize/10 Where: 10 = ID of Template()

In the controller the model is created based on the template so that the View's model is actually a Customization() object which actually has an Id of 0 because it's new.

In the view I render @Html.HiddenFor( m => m.Id ) and the resulting value of that hidden input is 10, though it should be 0 because m is of type Customization. I've run into this before with MVC 2 and worked around it by not using helper methods.

Questions

  1. Is there annotation or something I can add to the Html Helper method to actually render the correct value?

  2. Is this a bug (MVC seems to be rendering m.Id as the route value regardless of what the actual model is set to 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 ) );
    }

Solution

Changed signature of Action to:

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

Changed link to action as such:

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

I end up with a url that looks like

/template/customize?TemplateId=10

It's uglier, but I get to keep my view clean with model.Id so this is a win for me.

like image 226
Shawn Hall Avatar asked Mar 15 '11 17:03

Shawn Hall


2 Answers

You can always choose not to use the HTML Helper in this case and use plain HTML instead:

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

like image 188
domenu Avatar answered Nov 12 '22 09:11

domenu


I think this is because when you use something like @Html.HiddenFor( m => m.Id ) the html helpers look in various places to populate the input's value, and the values in the route is one of those places.

So you could either change your route so that it's something like template/customize/{TemplateId} and then have your action method reflect this, e.g. public ActionResult Customize(int templateId).

OR you could change your viewmodel (or create a custom view model) that has a CustomizationId property rather than just Id.

And no, it's not a bug... it's more of a feature that can have unforeseen consequences. But once you're aware of it, it works like a treat.

like image 3
Charlino Avatar answered Nov 12 '22 08:11

Charlino