简体   繁体   中英

ASP.Net MVC checkbox values from view to custom controller method

I have a view with a table that displays my model items. I've extracted the relevant portions of my view:

@model System.Collections.Generic.IEnumerable<Provision>

@using (Html.BeginForm("SaveAndSend", "Provision", FormMethod.Post))
{
    if (Model != null && Model.Any())
    {
        <table class="table table-striped table-hover table-bordered table-condensed">
            <tr>
                ...
                // other column headers
                ...
                <th>
                    @Html.DisplayNameFor(model => model.IncludeProvision)
                </th>
                ...
                // other column headers
                ...
            </tr>
            @foreach (var item in Model)
            {
                <tr>
                    ...
                    // other columns
                    ...
                    <td>
                        @Html.CheckBoxFor(modelItem => item.IncludeProvision)
                    </td>
                    ...
                    // other columns
                    ...
                </tr>
            }
        </table>
        <button id="save" class="btn btn-success" type="submit">Save + Send</button>
    }
    ...
}

This works fine and the checkbox values are displayed correctly in the view depending on the boolean value of the IncludeProvision field for the given model item.

As per Andrew Orlov's answer, I've modified the view and controller and the SaveAndSend() controller method is now:

[HttpPost]
public ActionResult SaveAndSend(List<Provision> provisions)
{
    if (ModelState.IsValid)
    {
        // perform all the save and send functions
        _provisionHelper.SaveAndSend(provisions);
    }
    return RedirectToAction("Index");
}

However, at this point the passed in model object is null.

Including the Provision model object for completeness:

namespace
{
    public partial class Provision
    {
        ...
        // other fields
        ...
        public bool IncludeProvision { get; set; }
    }
}

My question is, what is the best way to grab the checked/unchecked value from each checkbox and update the session IncludeProvision field for each model item when the 'SaveAndSend' button is clicked?

As @mattytommo said in comments, you should post your model to controller. It can be done with putting your checkbox inside a form. After clicking on button "Save and exit" all data from inputs inside this form will be serialized and sent to your controller where you can perform manipulations with session variables and so on. After that you can redirect wherever you like.

Model

public class YourModel
{
    ...
    public bool IncludeProvision { get; set; }
    ...
}

View

@model YourModel

...
@using (Html.BeginForm("SaveAndSend", "Test", FormMethod.Post))
{
    ...
    @Html.CheckBoxFor(model => model.IncludeProvision)
    ...
    <button type="submit">Save and send</button>
}
...

Controller

public class TestController : Controller
{
    ...
    [HttpPost]
    public ActionResult SaveAndSend(YourModel model)
    {
         if (ModelState.IsValid)
         {
             // Some magic with your data
             return RedirectToAction(...);
         }

         return View(model); // As an example
    }
    ...
}

You cannot use a foreach loop to generate form controls for properties in a collection. It creates duplicate name attributes (in your case name="item.IncludeProvision" ) which have no relationship to your model and duplicate id attributes which is invalid html. Use either a for loop (you models needs to be IList<Provision>

for(int i = 0; i < Model.Count; i++)
{
  <tr>
    <td>....</td>
    <td>@Html.CheckBoxFor(m => m[i].IncludeProvision)<td>
  </tr>
}

or create an EditorTemplate for typeof Provision . In /Views/Shared/EditorTemplates/Provision.cshtml (note the name of the template must match the name of the type)

@model Provision
<tr>
  <td>....</td>
  <td>@Html.CheckBoxFor(m => m.IncludeProvision)<td>
</tr>

and in the main view (the model can be IEnumerable<Provision> )

<table>
  @Html.EditorFor(m => m)
</table>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM