EJN
EJN

Reputation: 17

View passes an empty model back to controller

I have a problem in ASP.NET. I made a list of checkboxes, and I want to post the selected values back to the controller. Problem is, the model I recieve in my controller is null.

My controller:

[HttpPost]
// POST: /Checklist/index
public ActionResult Index(Zoeken systemencheckboxenss)
{
    var zoekresultaat = _db.VW_Checks.AsQueryable();

    if (systemencheckboxenss.Systemen != null)
    {
        foreach (var item in systemencheckboxenss.Systemen)
        {
            if(item.isSelected == true)
            {
               zoekresultaat = zoekresultaat.Where(sy => (sy.Systeemnaam.Contains(item.Systeemnaam)));
            }
        }
    }

    var systemen = _db.SYSTEEMs;
    //Lijst van systemen en of het geslecteerd is
    var systeemnamen = new List<CheckboxSysteem>();
    //vult de lijst

    foreach (var i in systemen)
    {
        systeemnamen.Add(new CheckboxSysteem
        {
            Systeemnaam = i.SYSTEEMNAAM,
            isSelected = false,
        });
    }

    var models = new Zoeken
    {
        VwChecks = zoekresultaat.ToList(),
        Systemen = systeemnamen,
    }; 

    return View(models);
}

And here is my View:

@model UsabilityChecklistApp.ViewModels.Zoeken

@{
    ViewBag.Title = "Index";
}

<h2>Checks</h2>

@using (Html.BeginForm("Index", "Checklist", Model, FormMethod.Post))
{
    <table class="table">
        @foreach (var item in Model.Systemen)
        {
            <tr>
                <td>
                    @Html.HiddenFor(modelItem => item.Systeemnaam)
                    @Html.HiddenFor(modelItem => item.isSelected)
                    @Html.DisplayFor(modelItem => item.Systeemnaam)
                </td>
                <td>
                    @Html.CheckBoxFor(modelItem => item.isSelected)
                </td>

            </tr>
        }
    </table>
    <input type="submit" value="Zoek" />
}

And ofcourse my ViewModel:

using System.Web;
using UsabilityChecklistApp.Models;

namespace UsabilityChecklistApp.ViewModels
{
    public class Zoeken
    {
        public List<VW_Checks> VwChecks { get; set; }
        public List<CheckboxSysteem> Systemen { get; set; }
    }

    public class CheckboxSysteem
    {
        public string Systeemnaam { get; set; }
        public bool isSelected { get; set; }
    }
}

If I did not provide information to solve the problem, please ask for it.

EDIT: I must use checkboxes, no other options possible

Upvotes: 0

Views: 4163

Answers (3)

DoctorMick
DoctorMick

Reputation: 6793

Parameters are routed using their name by default so it is trying to map your model to a parameter named Model. When you're submitting a form things are usually handled for you though so you don't need to worry about the parameter name as the Model Binder will take care of the mapping.

All you need to do is remove the Model parameter from the form so the model binder can take care of it all for you

@using (Html.BeginForm("Index", "Checklist", FormMethod.Post))}

To get the list to map properly you'll need to changed your cshtml like so:

<table class="table">
    @for(int i = 0; i < Model.Systemen.Count; i++)
    {
        <tr>
            <td>
                @Html.HiddenFor(modelItem => modelItem.Systemen[i].Systeemnaam)
                @Html.DisplayFor(modelItem => modelItem.Systemen[i].Systeemnaam)
            </td>
            <td>
                @Html.CheckBoxFor(modelItem => modelItem.Systemen[i].isSelected)
            </td>

        </tr>
    }
</table>

The HTML helpers use expressions to generate the correct markup, specifically the names which need to have the index in order to map correctly. If you use a foreach the expression doesn't contain an index so the name generated is incorrect and can't be mapped back on to the list. There is a superb answer to a similar question which gives a much better description of this than I ever could.

I've give all of this a quick test and it is working once the Model parameter is removed from BeginForm.

Upvotes: 1

Saket Kumar
Saket Kumar

Reputation: 4835

I reused your code, and did the changes; it works perfectly. Try using this code:

Model:

 public class Zoeken
    {
        public Zoeken() { Systemen = new List<CheckboxSysteem>(); }
        public List<VW_Checks> VwChecks { get; set; }
        public List<CheckboxSysteem> Systemen { get; set; }
    }

    public class CheckboxSysteem
    {
        public string Systeemnaam { get; set; }
        public bool isSelected { get; set; }
    }

Controller:

    // GET: 
    public ActionResult Index()
    {
        var model = new Zoeken();
        CheckboxSysteem obj1 = new CheckboxSysteem();
        CheckboxSysteem obj2 = new CheckboxSysteem();
        CheckboxSysteem obj3 = new CheckboxSysteem();

        obj1.Systeemnaam = "Check1";
        obj1.isSelected = true;
        obj2.Systeemnaam = "Check3";
        obj2.isSelected = false;
        obj3.Systeemnaam = "Check3";
        obj3.isSelected = true;

        model.Systemen.Add(obj1);
        model.Systemen.Add(obj2);
        model.Systemen.Add(obj3);

        return View(model);
    }

    [HttpPost]
    public ActionResult Index(Zoeken model)
    {         
       return View(model);
    }

View:

@model MvcApplication2.Models.Zoeken
@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <div>
        @using (Html.BeginForm())
        {
            <table class="table">
                @for (int i = 0; i< Model.Systemen.Count; i++)
                {
                    <tr>
                        <td>
                            @Html.HiddenFor(m => m.Systemen[i].Systeemnaam)
                            @Html.HiddenFor(m => m.Systemen[i].isSelected)
                            @Html.DisplayFor(m => m.Systemen[i].Systeemnaam)
                        </td>
                        <td>
                            @Html.CheckBoxFor(m => m.Systemen[i].isSelected)
                        </td>

                    </tr>
                }
            </table>
            <input type="submit" value="Zoek" />
        }

    </div>
</body>
</html>

Comment if it still doesn't work.

Upvotes: 0

Ajay
Ajay

Reputation: 6590

I had same issue. I tried radio buttons instead of checkbox. Go through links

MVC3 @Html.RadioButtonfor Pass data from view to controller

View to Controller in mvc3

MVC3 @html.radiobuttonfor

How to pass List in Redirecttoaction

Might be your problem will solve.

Upvotes: 0

Related Questions