Dismissile Dismissile - 2 months ago 12
C# Question

ASP.net MVC - Separate ViewModel for POST Action

In my MVC application I have a View Model that looks similar to this:

public class ComplexViewModel
{
public ComplexDetailsViewModel Details1 { get; set; }
public ComplexDetailsViewModel Details2 { get; set; }
}

public class ComplexDetailsViewModel
{
public int Id { get; set; }
public string DisplayValue1 { get; set; }
public string DisplayValue2 { get; set; }
// ...
}


I was originally doing the following in my view:

@Html.HiddenFor(model => model.Details1.Id)
@Html.HiddenFor(model => model.Details2.Id)

@Html.DisplayFor(model => model.Details1.DisplayValue1)
...


I would POST the full model to the controller:

public ActionResult Post(ComplexViewModel model)


I don't actually need anything from ComplexViewModel except for the Id values, so I decided to create another view model used specifically for POSTing the data:

public class PostViewModel
{
public int Details1Id { get; set; }
public int Details2Id { get; set; }
}

public ActionResult Post(PostViewModel model)


The problem is that now my
@HiddenFor(model => model.Details1.Id)
does not map to my POST model so nothing actually gets POSTed.

Is there a way to have the separate structure for my POST model and my GET model while still using the
HiddenFor
helper?

Answer

Just write the HTML for the hidden inputs by hand instead of using the Html Helpers.

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

Update

I had issues doing something similar. I ended up flattening out the form related properties on my views. Automapper makes it really easy to map from other objects to your view and can flatten out hierarchies. Doing this, your new view might end up looking similar to this.

public class ComplexViewModel        
{        
    public long Details1Id { get; set; }        
    public string Details1Name { get; set; }
    public long Details2Id { get; set; }    
    public string Details2Name { get; set; }    
}