强类型视图中多模型表单提交的模型绑定

woo*_*ash 10 c# asp.net-mvc html-helper model-binding

我在提交多个模型的表单上遇到问题.我有一份投诉表格,其中包括投诉信息以及一对多投诉人.我正在尝试提交表单,但我在绑定上遇到错误.ModelState.IsValid始终返回false.

如果我调试并查看ModelState错误,我得到一个说法:"EntityCollection已经被初始化.应该只调用InitializeRelatedCollection方法在对象图的反序列化期间初始化一个新的EntityCollection".

此外,在调试时,我可以看到投诉模型确实填写了表单提交中的投诉人,因此似乎该部分正在运行.

我不确定使用默认的ModelBinder我是不是可以做什么,或者我是不是以正确的方式去做.我似乎无法找到任何具体的例子或文件.这里可以在stackoverflow上找到一个非常类似的问题,但它似乎并不处理强类型视图.

控制器代码:

    public ActionResult Edit(int id)
    {
        var complaint = (from c in _entities.ComplaintSet.Include("Complainants")
                     where c.Id == id
                     select c).FirstOrDefault();

        return View(complaint);
    }

    //
    // POST: /Home/Edit/5
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Edit(Complaint complaint)
    {
        if (!ModelState.IsValid)
        {
            return View();
        }
        try
        {
            var originalComplaint = (from c in _entities.ComplaintSet.Include("Complainants")
                                     where c.Id == complaint.Id
                                     select c).FirstOrDefault();
            _entities.ApplyPropertyChanges(originalComplaint.EntityKey.EntitySetName, complaint);
            _entities.SaveChanges();
            return RedirectToAction("Index");
        }
        catch
        {
            return View();
        }
    }
Run Code Online (Sandbox Code Playgroud)

查看代码(这是由创建/编辑视图调用的部分视图,它也是使用Complaint强类型的):

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ProStand.Models.Complaint>" %>

<%= Html.ValidationSummary() %>
<% using (Html.BeginForm()) {%>

<table cellpadding="0" cellspacing="0" class="table">
    <tr>
        <td>
        <label for="DateReceived">Date Received:</label>
            <%= Html.TextBox("DateReceived") %>
            <%= Html.ValidationMessage("DateReceived", "*") %>    
        </td>
        <td>
            <label for="DateEntered">Date Entered:</label>
            <%= Html.TextBox("DateEntered")%>
            <%= Html.ValidationMessage("DateEntered", "*") %>
        </td>
    </tr>
    <tr>
        <td>
            <label for="Concluded">Concluded:</label>
            <%= Html.CheckBox("Concluded")%>
            <%= Html.ValidationMessage("Concluded", "*") %>
            </td>
        <td>
            <label for="IncidentDate">Incident Date:</label>
            <%= Html.TextBox("IncidentDate")%>
            <%= Html.ValidationMessage("IncidentDate", "*") %></td>
    </tr>
</table>
    <hr />
    <table>
    <% if (Model != null) {
           int i = 0;
       foreach (var complainant in Model.Complainants){ %>
       <%= Html.Hidden("Complainants[" + i + "].Id", complainant.Id)%>
    <tr>
        <td>
            <label for="Surname">Surname:</label>

            <%= Html.TextBox("Complainants[" + i + "].Surname", complainant.Surname)%>
            <%= Html.ValidationMessage("Surname", "*")%>
        </td>
        <td>
            <label for="GivenName1">GivenName1:</label>
            <%= Html.TextBox("Complainants[" + i + "].GivenName1", complainant.GivenName1)%>
            <%= Html.ValidationMessage("GivenName1", "*")%>
        </td>
    </tr>
    <% i++; %>
    <% }} %>
    <tr>
        <td colspan=2>
            <input type="submit" value="Submit" />
        </td>
    </tr>
</table>
<% } %>
<div>
    <%=Html.ActionLink("Back to List", "Index") %>
</div>
Run Code Online (Sandbox Code Playgroud)

Arn*_*psa 3

盲猜:

改变:

<%= Html.TextBox("Complainants[" + i + "].Surname", complainant.Surname)%>
Run Code Online (Sandbox Code Playgroud)

和:

<%= Html.TextBox("Complaint.Complainants[" + i + "].Surname",  
complainant.Surname)%>
Run Code Online (Sandbox Code Playgroud)

分别——添加“投诉”。在“投诉人[...”之前

编辑

这不是正确的答案。不删除它只是因为这可能会增加一些价值,直到出现正确的答案。

编辑2:

我可能是错的,但对我来说,实体框架(或者 - 你使用它的方式)似乎存在问题。我的意思是 - asp.net mvc 设法从请求中读取值,但无法初始化投诉人集合。

这里写的是:

InitializeRelatedCollection(TTargetEntity) 方法初始化使用默认构造函数创建的现有 EntityCollection(TEntity)。EntityCollection(TEntity) 使用提供的关系和目标角色名称进行初始化。

InitializeRelatedCollection(TTargetEntity) 方法仅在反序列化期间使用。

更多信息:

例外:

  • 无效操作异常

状况:

  • 当提供的 EntityCollection(TEntity) 已初始化时。
  • 当关系管理器已附加到 ObjectContext 时。
  • 当关系经理已包含具有此名称和目标角色的关系时。

不知何故,InitializeRelatedCollection 被触发两次。不幸的是 - 我没有什么好主意到底为什么。也许这个小小的调查会对其他人有所帮助 - 在 EF 方面更有经验。:)

EDIT3:
这不是这个特定问题的解决方案,更像是一种解决方法,一种处理 mvc 模型部分的正确方法。

创建视图模型仅用于演示目的。也从纯 POCO 创建新的域模型(因为 EF 仅在下一个版本中支持它们)。使用AutoMapper映射 EFDataContext<=>Model<=>ViewModel。

这需要一些努力,但应该这样处理。这种方法从模型中删除了表示责任,清理了域模型(从模型中删除了 EF 内容),并解决了绑定问题。