asp.net Post a form with view model to controller action method

I have a Fairly Complex Form that I need to post to my MVC controller.

Here is the View model which I initially pass to the view on creation:

public class EditViewModel
{
    public Service service { get; set; }
    public bool sms { get; set; }
    public bool email { get; set; }
    public string userId { get; set; }
}

Here is my View (simplified):

@model IList<Service_Monitor_Web_Interface.Models.ViewModels.EditViewModel>
@{
  ViewBag.Title = "Configure User Notifications";
  Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>@ViewBag.Title</h2>

@using (Html.BeginForm("Edit", "Users", FormMethod.Post, new { @class = "stdform stdform2", role = "form" }))
{
@Html.AntiForgeryToken()
<hr />

<p>
    <label><u> Service:</u> </label>
    <span class="field">
        <u>Notification Methods:</u>
    </span>
</p>


for (int i = 0; i < Model.Count; i++)
{
    <p>
        <label>@Model[i].service.Name</label>
        <span class="field">
            @Html.CheckBoxFor(model => model[i].sms)
            SMS &nbsp;&nbsp;
            @Html.CheckBoxFor(model => model[i].email)
            Email &nbsp;&nbsp;
        </span>
    </p>
}
<br clear="all" /><br />

<p class="stdformbutton">
    <button class="submit radius2">Save</button>
    <input type="reset" class="reset radius2" value="Reset Form" />
</p>
}

And here is my Action method in my controller:

    //
    // POST: /Users/Edit
    [HttpPost]
    public ActionResult Edit(IList<EditViewModel> viewModel)
    {
        return View(viewModel);
    }

How Can I bind my view model when receiving it on the controller? Currently when I debug the action method receives a ViewModel which looks like so:

How can I get service and userId not to be null?

Answers


Note that in your helpers' lambdas, say in model => service.sms right part (service.sms) formally is not derived from the left part (model). That causes all name attributes of resulting inputs to be the same, and gives you request parameters that you did not expect.

The standard practice is to use for instaed of foreach in loop cases. That way name attributes for resulting html are generated correctly:

for(int i=0; i<Model.Count; i++)
{
    <p>
        <label>@Model[i].service.Name</label>
        <span class="field">                
            @Html.CheckBoxFor(model => model[i].sms)
            SMS &nbsp;&nbsp;               
            @Html.CheckBoxFor(model => model[i].email)
            Email &nbsp;&nbsp;
        </span>
    </p>
}

Note that this requires Model to be of type implementing IList rather than IEnumerable.

Update. For other values, that do not have any UI for them, you can use hidden fields, so that they are not visible for the user and are nevertheless posted to the server:

<label>@Model[i].service.Name</label>
<span class="field">                
    @Html.CheckBoxFor(model => model[i].sms)
    SMS &nbsp;&nbsp;               
    @Html.CheckBoxFor(model => model[i].email)
    Email &nbsp;&nbsp;
    @Html.HiddenFor(mode => model[i].userId)
    @Html.HiddenFor(mode => model[i].service.Name)
    ...other field of service you want to be posted...
</span>

Need Your Help

Post Commit Hook - Jenkins: Starting jobs after Jenkins downtime

svn jenkins post-commit-hook

We have implemented a Post Commit Hook which starts our jobs on Jenkins. Our inspiration is this: Trouble with SVN post-commit and Jenkins

How can I play a flv file that is hosted on a remote website?

html flash flv playback

I'm looking to play a flash video hosted on a remote website. I've tried the following (and profuse google-ing):

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.