如果!ModelState.IsValid

时间:2016-12-19 13:18:56

标签: c# asp.net-mvc asp.net-mvc-5.2

我的方法可能完全错误,但我正在慢慢学习MVC ...我有一个表单,用户必须根据此模型选择一些(或没有)模块:

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; }
}

呈现复选框列表以显示每个模块:

@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)
}

最后,表单按如下方式处理:

[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
        }
    }
}

除非由于某种原因我的服务器端验证失败,并且模型被发回(return View("Index", qd);),否则一切都工作正常。那时,复选框列表神秘地改变了:

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

......对此:

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

所有复选框值都将丢失。如果我检查Firebug中的原始发布数据,我发现由于某种原因,对于选中的框发布了true和false,并且#34;已检查&#34;值:

enter image description here

1 个答案:

答案 0 :(得分:1)

在服务器端,变量qd包含您从视图中发布的值: 对于每个MyProductModule,您只发布Checked成员。

因此,当您使用return View("Index", qd);时,您只向视图提供您拥有的值:Checked成员。

如果您想拥有ModuleName成员,则必须将其发布到Checked成员

@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)
}

好的,我无法重现您的错误,但我可以建议另一种方式来编写它:使用编辑器模板

使用@Html.EditorFor(m => m.Modules)而不是for循环 你会有像

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

然后创建一个EditorTemplates文件夹和一个名为MyProductModule.cshtml

的新视图

enter image description here

MyProductModule.cshtml:

@model MyNamespace.MyProductModule

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