Mark
Mark

Reputation: 7818

ASP.Net MVC Postback from View to Controller shows null values

I've a problem with ViewModel posting back to a controller, but the ViewModel not being mapped correctly from the View to the Controller.

TopicId and Content should contain values, however, when posted back, they do not:

VS Debug: ss

ViewModels:

  public class PostViewModel
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
    public string Author { get; set; }
    public DateTime DateOfTopic { get; set; }
}

public class ReplyViewModel
{
    public int TopicId { get; set; }
    public string Content { get; set; }

}

public class PostListAndReplyVM
{
    public List<PostViewModel> PostViewModel { get; set; }
    public ReplyViewModel ReplyViewModel { get; set; }
}

View:

@model centreforum.Models.PostListAndReplyVM

@using (Html.BeginForm()) {
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)

<fieldset>
    <legend>Post</legend>

         @Html.HiddenFor(model => model.ReplyViewModel.TopicId)

    <div class="editor-label">
        @Html.LabelFor(model => model.ReplyViewModel.Content)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.ReplyViewModel.Content)
        @Html.ValidationMessageFor(model => model.ReplyViewModel.Content)
    </div>
    <p>
        <input type="submit" value="Create" />
    </p>
</fieldset>

}

Generated HTML:

<form action="/Post/List/7/" method="post"><input name="__RequestVerificationToken" type="hidden" value="xxxxxxxxxxxxx" />    <fieldset>
    <legend>Post</legend>

         <input data-val="true" data-val-number="The field TopicId must be a number." data-val-required="The TopicId field is required." id="ReplyViewModel_TopicId" name="ReplyViewModel.TopicId" type="hidden" value="7" />

    <div class="editor-label">
        <label for="ReplyViewModel_Content">Content</label>
    </div>
    <div class="editor-field">
        <input class="text-box single-line" id="ReplyViewModel_Content" name="ReplyViewModel.Content" type="text" value="" />
        <span class="field-validation-valid" data-valmsg-for="ReplyViewModel.Content" data-valmsg-replace="true"></span>
    </div>

    <p>
        <input type="submit" value="Create" />
    </p>
</fieldset>
</form>

As you can see from the generated HTML, the TopicId definitely has a value: value="7"

Can anyone see where the problem is between the form post, and the controller, which is expecting the ReplyViewModel?

Thank you,

Mark

Upvotes: 0

Views: 8682

Answers (3)

Ant P
Ant P

Reputation: 25221

The problem is the fact that your view is typed to PostListAndReplyVM - so it creates names such as ReplyViewModel.Content - but, because your controller action expects a ReplyViewModel, these fields can't be bound (i.e. there is no such thing as ReplyViewModel.ReplyViewModel.Content).

Change your controller action:

public ActionResult List(PostListAndReplyVM reply)

Alternatively - if that's your whole view - just type it to ReplyViewModel instead (and update your HtmlHelper expressions accordingly).

Upvotes: 3

Darin Dimitrov
Darin Dimitrov

Reputation: 1038710

Your input field names are prefixed with ReplyViewModel (because of the model => model.ReplyViewModel.* lambda), so you need to indicate this information to the model binder:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult List([Bind(Prefix = "ReplyViewModel")] ReplyViewModel model)
{
    ...
}

Alternatively have your List action take the PostListAndReplyVM model:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult List(PostListAndReplyVM model)
{
    // obviously only model.ReplyViewModel will be bound here because
    // those are the only input fields in your form
    ...
}

Upvotes: 3

maxs87
maxs87

Reputation: 2284

Its null because you bound it to another model

In view

@model centreforum.Models.PostListAndReplyVM

In Action ReplyViewModel

try to bind like

public ActionResult SomeAction(PostListAndReplyVM model)

    {
    }

Upvotes: 2

Related Questions