简体   繁体   English

ASP.NET MVC5无效的ModelState:如何将外键传递给下拉列表,并将其传递回HTTPPost?

[英]ASP.NET MVC5 Invalid ModelState: How to pass foreign key to drop-down and pass it back on HTTPPost?

I've a Project model like below: 我有一个如下的项目模型:

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;

    ....


}

In tried to pass users with specified role inside create action like below,using ViewBag: 在尝试通过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();
}

And here is the part of Razor View for drop-downs: 这是Razor 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>

There is no problem up to here, but on form post my model will not have valid state: 到这里为止没有问题,但是在表单发布后,我的模型将没有有效状态:

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

The Question: How to pass required foreign key properties here? 问题:如何在此处传递所需的外键属性?

I don't believe you are using the framework in the correct fashion in your controller. 我不相信您在控制器中以正确的方式使用框架。 Using Request items is leaving behind all of the things that the ASP.NET MVC framework is trying to do for you. 使用“请求”项将遗留下ASP.NET MVC框架要为您完成的所有工作。 It should really read along the following lines: 它实际上应该遵循以下几行:

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

The reality is that you should be allowing ASP.NET MVC to handle almost all of your binding. 实际上,您应该允许ASP.NET MVC处理几乎所有的绑定。 It's only in very particular circumstances that you should override it. 仅在非常特殊的情况下才应覆盖它。

As an additional point, as Shyju also says in the comments, best practice dictates that you should also use a dedicated view model for this rather than your domain model. 另外,正如Shyju在评论中所说,最佳实践要求您还应该为此使用专用的视图模型,而不是域模型。

PS Lecturing aside (sorry), the specific reason why your code is non-operational is that the ProjectManager property is not set at the time you are calling SaveChanges(). 顺便说一句(抱歉),您的代码无法运行的特定原因是,在调用SaveChanges()时未设置ProjectManager属性。 You have only set ProjectManagerID, this will not automagically set the ProjectManager property for you, you have to do that yourself if you don't use the bindings as intended in MVC. 您只设置了ProjectManagerID,这不会自动为您设置ProjectManager属性,如果您没有按MVC的意图使用绑定,则必须自己进行设置。

Good luck with your app! 祝您的应用程序好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM