0

Just need to know if this is possible to do or what exactly is standard practice in MVC as this is my first large scale MVC application.

So I've got a form I want the user to be able to edit and on that form page to pull up all the necessary data I need I'm bringing in a viewmodel,

public class Tier2IssueFormViewModel
{
    public Tier2IssueDTO Tier2Issue { get; set; }
    public IEnumerable<SelectListItem> VersionList { get; set; }
    public IEnumerable<SelectListItem> BugList { get; set; }
    public IEnumerable<SelectListItem> IssueStatusList { get; set; }
}

Then once I've finished collecting the form data from the user using things like,

@Html.TextBoxFor(m => m.Tier2Issue.Tier2Notes, new { @class = "form-control"})
@Html.DropDownListFor(m => m.Tier2Issue.FishbowlVersion, Model.VersionList, "Select Application Version")
@Html.HiddenFor(m => m.Tier2Issue.ID)

I want to post back to this action with the following signature for my model to bind to,

[HttpPost]
[Route("Issues/{id}/Edit")]
public ActionResult EditIssue(Tier2IssueDTO model)
{
    ...
    // Update DB with the DTO model
    ...
}

But so far nothing really gets bound to this object. I thought the model binder might be smart enough to pair the two but I'm guessing this logic is incorrect. So I'm currently doing a workaround by using this,

[HttpPost]
[Route("Issues/{id}/Edit")]
public ActionResult EditIssue(Tier2IssueFormViewModel model)
{
    ...
    // Get Tier2IssueDTO values from viewmodel
    // Update DB with the DTO model
    ...
}

I mean it works, but it seems odd to me that you would model bind to a view model. Is this standard practice or is there a way to bind to an object contained within the viewmodel directly?

tokyo0709
  • 1,897
  • 4
  • 28
  • 49
  • The model in the view is `Tier2IssueFormViewModel` and your `HtmlHelper` methods are generating form controls based on that model, not `Tier2IssueDTO` (look at the `name` attributes your generating) so it cannot bind to `Tier2IssueDTO`. Although your could use the `Prefix` property of `BindAttribute`, your not doing this correctly anyway. A view model should not contain data models, especially when editing data. –  Oct 03 '16 at 23:55
  • @StephenMuecke If you shouldn't have data models in the view model how do I display the data for an object that is to be edited? I mean the object already has values and that is how I'm getting those values to display and subsequently change. What is the alternative? – tokyo0709 Oct 04 '16 at 00:07
  • You view model should contain properties of the data model that you want to edit (not the data model itself) plus your SelectLists etc - [What is ViewModel in MVC?](http://stackoverflow.com/questions/11064316/what-is-viewmodel-in-mvc) –  Oct 04 '16 at 00:09
  • @StephenMuecke After reading the top answer there I can see where you are going with that. The one thing I'm still wondering though is why is passing the data model taboo? I guess it comes up because in my situation we are getting data from our api and then sending it straight over to the View. I'm sure there is some extra data but I can't imagine it costs us that much performance. – tokyo0709 Oct 04 '16 at 00:32
  • @tokyo0709 `public ActionResult EditIssue(Tier2IssueDTO tier2Issue)` would bind properly I believe. – dom Oct 04 '16 at 00:50

2 Answers2

1

This will not work because the input text box names are differnt from the model inside your action, ex: the text box will have a name Tier2Issue.Tier2Notes while the model parameter in your action is expecting a property name Tier2Notes only without the Tier2Issue prefix.

You can overcome this issue by either making the model the same as the action parameter or give an explicit name and value to the text box, ex:

@Html.TextBox("Tier2Notes",Model.Tier2Issue.Tier2Notes, new { @class = "form-control"})

This should make it work

Haitham Shaddad
  • 4,336
  • 2
  • 14
  • 19
0

You have the right of it. It often seems pretty repetitive to have a viewmodel, dto and entity that all seem to have the same properties, but they all do different jobs an usually end up diverging a bit. A dto could act as a viewmodel, but it's a square peg in a round hole. If you're not using automapper to map these objects to one an other (this may be opinion baesed but it's broadly shared) - then use automapper to save you mindless keystrokes.

Chad McGrath
  • 1,561
  • 1
  • 11
  • 17