Checkbox checked value lost if !ModelState.IsValid

对着背影说爱祢 提交于 2019-12-24 09:57:46

问题


My approach here may be entirely wrong, but I'm slowly learning MVC... I have a form whereby a user must select a number of (or no) modules, based on this model:

public class MyProductModule
{
    public string ModuleName { get; set; }
    public bool Checked { get; set; }
}

public class ProductRequest
{

    public ProductRequest()
    {
        Modules = LoadModules();
    }

    public static List<MyProductModule> LoadModules()
    {
        return new List<MyProductModule>()
        {
            new MyProductModule() { ModuleName = "Module One", Checked = false },
            new MyProductModule() { ModuleName = "Module Two", Checked = false },
            new MyProductModule() { ModuleName = "Module Three", Checked = false }
        };
    }

    [Required]
    [EmailAddress]
    public string Email { get; set; }

    [DisplayName("MyProduct Modules")]
    public List<MyProductModule> Modules { get; set; }
}

A check box list is rendered to display each module:

@for (int i = 0; i < Model.Modules.Count; i++)
{
    @Html.CheckBoxFor(m => m.Modules[i].Checked)
    @Html.HiddenFor(m => m.Modules[i].ModuleName)
    @Html.LabelFor(m => m.Modules[i].Checked, Model.Modules[i].ModuleName)
}

Finally, the form is processed like this:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult ProcessRequest(ProductRequest qd)
{
    if (!ModelState.IsValid)
    {
        return View("Index", qd);
    }
    else
    {
        // check email domains
        List<string> badDomains = new List<string>();
        badDomains.Add("gmail");
        badDomains.Add("yahoo");
        badDomains.Add("hotmail");
        foreach (string s in badDomains)
        {
            if (qd.Email.Contains(string.Format("@{0}.", s)))
            {
                ModelState.AddModelError(string.Empty, string.Format("Please use your work email address.", s));
            }
        }

        if (!ModelState.IsValid)
        {
            return View("Index", qd);
        }
        else
        {
            // process
        }
    }
}

Everything is working perfectly, unless for some reason my server-side validation fails, and the model is sent back (return View("Index", qd);). At that point, the checkbox list mysteriously changes from this:

[x] Module One
[ ] Module Two
[ ] Module Three

...to this:

[ ] Module One
[ ] Module Two
[ ] Module Three

All of the checkbox values are lost. If I examine the raw posted data in Firebug, I see that for some reason both true AND false are posted for the checked boxes "checked" value:


回答1:


On the server side, your variable qd contains the values you posted from view : For each MyProductModule you post only the Checked member.

So when you use return View("Index", qd); you give to the view only the value you have : Checked member.

If you want to have the ModuleName member, you have to post it alongside to the Checked member

@Html.LabelFor(model => model.Modules, htmlAttributes: new { @class = "required" })
@for (int i = 0; i < Model.Modules.Count; i++)
{
   @Html.CheckBoxFor(m => m.Modules[i].Checked)
   @Html.HiddenFor(m => m.Modules[i].ModuleName)
   @Html.LabelFor(m => m.Modules[i].Checked, Model.Modules[i].ModuleName)
}

Ok, I can't reproduce your error, but I can suggest another way to write it : using an editor template

Instead of the for loop, use @Html.EditorFor(m => m.Modules) You will have something like

@using (Html.BeginForm("ProcessRequest", "Home"))
{
    @Html.AntiForgeryToken()
    @Html.TextBoxFor(m => m.Email)
    @Html.EditorFor(m => m.Modules)
    <input type="submit" value="send" />
}

Then create a EditorTemplates folder and a new view named MyProductModule.cshtml

MyProductModule.cshtml :

@model MyNamespace.MyProductModule

@Html.CheckBoxFor(m => m.Checked)
@Html.HiddenFor(m => m.ModuleName)
@Html.LabelFor(m => m.Checked, Model.ModuleName)


来源:https://stackoverflow.com/questions/41223489/checkbox-checked-value-lost-if-modelstate-isvalid

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!