ASP.NET MVC5 无效的模型状态:如何将外键传递到下拉列表并将其传递回 HTTPPost

本文关键字:NET MVC5 下拉列表 HTTPPost 状态 模型 ASP 无效 | 更新日期: 2023-09-27 18:37:26

我有一个项目模型,如下所示:

public class Project
{
    public int Id { get; set; }
    ....
    [Required]
    public virtual ApplicationUser Client { get; set; }
    [Key]
    [ForeignKey("Client")]
    public string ClientID;

    [Required]
    public virtual ApplicationUser ProjectManager { get; set; }
    [Key]
    [ForeignKey("ProjectManager")]
    public string ProjectManagerID;
    ....

}

在尝试将具有指定角色的用户传递到创建操作中,如下所示,使用 ViewBag:

// GET: /Project/Create
public ActionResult Create()
{
    populateRoles();
    SelectList PMs = new SelectList(projectManagers, "Id", "Name");
    ViewBag.ProjectManagerID = PMs;
    SelectList Clients = new SelectList(clients, "Id", "Name");
    ViewBag.ClientID = Clients;
    return View();
}

这是下拉菜单的剃刀视图部分:

<div class="form-group">
    @Html.Label("Project Manager", new { @class = "col-md-2 control-label" })
    <div class="col-md-10">
        @Html.DropDownList("ProjectManagerID", ViewBag.ProjectManagerID as SelectList, new { @class = "col-md-10 control-label" })
    </div>
</div>
<div class="form-group">
    @Html.Label("Client", new { @class = "col-md-2 control-label" })
    <div class="col-md-10">
        @Html.DropDownList("ClientID", ViewBag.ClientID as SelectList, new { @class = "col-md-10 control-label" })
    </div>
</div>

到目前为止没有问题,但是在表单发布中,我的模型将没有有效状态:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "Id,Name,Progress,CreateDate")] Project project)
{
    /*---------------------populate select lists ------*/
    populateRoles();
    SelectList PMs = new SelectList(projectManagers, "Id", "Name");
    ViewBag.ProjectManagerID = PMs;
    SelectList Clients = new SelectList(clients, "Id", "Name");
    ViewBag.ClientID = Clients;
    /*-----------try to fix invalid modelstate ---------*/
    string projectManagerID = Request["PMs"];
    string clientID = Request["Clients"];
    project.ProjectManagerID = projectManagerID;
    project.ClientID = clientID;
    if (ModelState.IsValid) // <-Invalid modelstate because required foreign key properties
    {
        dbContext.Projects.Add(project);
        dbContext.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(project);
}

问题:如何在此处传递所需的外键属性?

ASP.NET MVC5 无效的模型状态:如何将外键传递到下拉列表并将其传递回 HTTPPost

我不相信你在控制器中以正确的方式使用框架。使用请求项将抛弃 ASP.NET MVC 框架试图为您执行的所有操作。它实际上应该按照以下思路阅读:

    [HttpPost]
    public ActionResult Create(string submitButton)
    {
        var model = new MyClass();  // go and get the record you want to edit
        if (submitButton == "Save")
        {
            TryUpdateModel(model);
            if (!ModelState.IsValid) // if the modelstate isn't valid, setup the dropdowns for the return trip to the form
            {
                ViewData["OrganizationId"] = model.OrganizationId;
                ViewBag.RecordTypes = GetRecordTypes(model.OrganizationId);
                return View(model);
            }
            context.AddToMyType(model);
            context.SaveChanges(); // save changes if there are no errors
        }
        return RedirectToAction("Index", new { id = model.OrganizationId });
    }

现实情况是,您应该允许 MVC 处理几乎所有 ASP.NET 绑定。只有在非常特殊的情况下,您才应该覆盖它。

另外,正如 Shyju 在评论中所说,最佳实践表明您还应该为此使用专用视图模型,而不是域模型。

P.S. 撇开讲课(抱歉),您的代码不可操作的具体原因是在您调用 SaveChanges() 时未设置 ProjectManager 属性。您只设置了项目经理ID,这不会自动为您设置项目经理属性,如果您没有按照MVC中的预期使用绑定,则必须自己执行此操作。

祝你的应用好运!