下拉列表值未在创建MVC 5

时间:2017-06-20 18:02:31

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

如果这是一个愚蠢的问题,我道歉,但我很难过。这是我尝试的第一个MVC应用程序,来自Web表单。我有以下型号:

public class IndividualItem
{
    [Required][Key]
    public string SerialNumber { get; set; }
    public virtual NSN NSNnumber { get; set; }
    public string Location { get; set; }
    public string User { get; set; }
}

public class NSN
{
    [Required][DisplayName("NSN")][StringLength(13)][Key]
    public string NSNnumber { get; set; }
    [Required]
    [StringLength(100)]
    [DisplayName("NSN Description")]
    public string Description { get; set; }
    public virtual ICollection<IndividualItem> Items { get; set; }
}

这是视图模型

public class IndividualItemNSNselectList
{
    public SelectList NSNlist { get; set; }
    public IndividualItem IndividualItem { get; set; }
}

控制器

public ActionResult Create()
    {
        var view = new IndividualItemNSNselectList();
        view.NSNlist = new SelectList(db.NSNs.ToList(),"NSNnumber","Description");
        return View(view);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create([Bind(Include = "SerialNumber,Location,User")] IndividualItem individualItem)
    {
        if (ModelState.IsValid)
        {
            db.IndividualItem.Add(individualItem);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(individualItem);
    }

并在视图中下拉

<div class="form-group">
            @Html.LabelFor(model => model.IndividualItem.NSNnumber, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.DropDownListFor(model => model.IndividualItem.NSNnumber,Model.NSNlist, " ")
                @Html.ValidationMessageFor(model => model.IndividualItem.NSNnumber, "", new { @class = "text-danger" })
            </div>
        </div>

当我尝试为IndividualItem创建创建视图时,一切正常,包括下拉列表的填充。但是,当我发布NSN对象时没有输入数据库。

我做了很多研究,引导我到这一点,但我无法弄清楚出了什么问题。感谢您的帮助,请告诉我您是否需要我澄清任何事情。

2 个答案:

答案 0 :(得分:1)

您的代码中存在多个错误,以及一些不良做法。

首先,您不能将<select>绑定到属于复杂对象的属性(它只回发一个简单的值 - 所选选项的值)。假设您想要绑定到NSNnumber的{​​{1}},那么视图代码必须是

NSN
正如Saket所说。

其次,视图中的模型为@Html.DropDownListFor(m => m.IndividualItem.NSNnumber.NSNnumber, Model.NSNlist, "") ,这意味着POST方法参数中的模型也必须为IndividualItemNSNselectList。你的POST方法签名应该是

IndividualItemNSNselectList

并且你在POST方法中获得任何内容的唯一原因是因为你将参数命名为与可能导致其他问题的属性相同,包括当你返回视图因为public ActionResult Create IndividualItemNSNselectList model) 无效时你的意愿获取异常(请参阅The model item passed into the dictionary is of type .. but this dictionary requires a model item of type以获取更多详细信息),因为您将ModelState的实例传回期望IndividualItem的视图。

通过正确使用视图模型可以轻松解决所有这些问题。视图模型不应包含作为数据模型的属性,只应包含要在视图中显示/编辑的数据模型的属性。此外,在使用视图模型时,您永远不需要IndividualItemNSNselectList属性,因为您已经防止过度发布攻击。请参阅What is ViewModel in MVC?

您的[Bind]属性建议您只编辑4个属性,因此您的视图模型应该是(根据需要添加显示和验证属性)

[Bind]

并且视图变为

public class IndividualItemVM
{
    public string SerialNumber { get; set; }
    public string NSNnumber { get; set; }
    public string Location { get; set; }
    public string User { get; set; }
    public IEnumerable<SelectListItem> NSNlist { get; set; }
}

POST方法签名现在变为

@Html.DropDownListFor(m => m.NSNnumber, Model.NSNlist, "", new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.NSNnumber, "", new { @class = "text-danger" })

并在该方法中,您创建数据模型的新实例,并从视图模型中映射其属性并保存。

此外,您还必须在返回视图之前重新填充public ActionResult Create IndividualItemVM model) ,否则您的当前代码将发生另一个异常,如The ViewData item that has the key 'XXX' is of type 'System.Int32' but must be of type 'IEnumerable'中所述。作为旁注,在查询中使用SelectList生成.ToList()是不必要的。

答案 1 :(得分:0)

您的代码需要进行两项修改:

更改1: 下拉列表应绑定到属性而不是类

将您的下拉列表更新为:

@Html.DropDownListFor(model => model.IndividualItem.NSNnumber.NSNnumber, Model.NSNlist, " ")

更改2:

action方法中的绑定属性缺少要绑定的必需属性。更新您的帖子操作方法,如下所示:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "SerialNumber,Location,User,NSNnumber")] IndividualItem individualItem)
{
}

或者如果您打算排除属性,请修改如下:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Exclude= "SerialNumber,Location,User")] IndividualItem individualItem)
{
}

希望这适合你。我自己验证了。