1

我正在为我公司的服务开发数据库输入系统。每个服务可以根据需要进行任意数量的操作。同样,每个操作可以根据需要具有任意数量的参数。我正在尝试做的是使用动态表单来更新我的服务/编辑视图中操作参数的数据。

我使用动态表单向服务添加操作,但不是从我的服务视图发布它们,而是从操作/创建发布它们。这应该不是问题,但我想我会指出这一点。

现在,我遇到的问题是将参数表单中的数据发布回服务器。ModelState.isValid 返回错误。当我查看我的模型状态时,我的所有服务数据成员和我的操作数据成员都在那里,但我所有的参数数据成员都丢失了。我使用 FormCollection 检查动态表单的名称,它们实际上遵循 MVC 的模型绑定命名约定 (Parameters[i].DataMembers)。

希望有人可以为我提供一些见解。以下是一些可能有用的代码:

在我的服务控制器中:

    public ActionResult Edit(int id = 0)
    {
        if (id == 0)
        {
            return HttpNotFound();
        }

        //Eager loads the operations and parameters for this service
        var service = db.Services.Include(s => s.Operations.Select(o => o.Parameters)).Where(s => s.ServiceID == id).Single();

        if (service == null)
        {
            return HttpNotFound();
        }

        return View(service);
    }

在我的服务/编辑视图中,我使用编辑器模板来显示操作的表单。我还在这个表单块之后放置了一个空 div,稍后通过 AJAX.ActionLink 填充参数表单:

    @Html.EditorFor(m => Model.Operations)

    <div id="parameter_container">
    </div>

然后在我的编辑器模板中,我设置了我的 AJAX.ActionLink:

    @Ajax.ActionLink("Edit Parameters", "EditParams", "Services", new { opID = Model.OperationID, ViewContext.FormContext.FormId },
            new AjaxOptions
            {
                UpdateTargetId = "parameter_container",
                InsertionMode = InsertionMode.Replace,
                HttpMethod = "Post"
            })

然后回到我的服务控制器,我有:

    public PartialViewResult EditParams(int opID = 0)
    {
        if (opID == 0)
        {
            return PartialView();
        }

        var operation = db.Operations.Include(o => o.Parameters).Where(o => o.OperationID == opID).Single();

        if (operation.parameters == null)
        {
            return PartialView();
        }

        return PartialView("ParameterEditorRow", operation);
    }

ParameterEditorRow 是强类型化到我的操作模型的局部视图(这需要在操作之后进行建模。将 Model.Parameters 传递到编辑器模板中会生成所需的命名约定(Parameters[i].DataMembers)。这很简单:

    @model InformationStore.Models.Operation
    @{if (this.ViewContext.FormContext == null)
        {
            this.ViewContext.FormContext = new FormContext();
        }  
     }
    <div class="editor_row">
       @Html.EditorFor(m => Model.Parameters)
    </div>

最后,我有一个用于参数的编辑器模板。我为这篇冗长的帖子道歉,但我已经坚持了几天了。我只是觉得我的方法存在根本性的问题。有什么建议么?

编辑以回应 StriplingWarrior

在我的编辑视图中,我所有的输入字段都在这个表单中:

 @using (Html.BeginForm("edit", "services", new {Model.ServiceID}, FormMethod.Post))

并发布到:

    [HttpPost]
    public ActionResult Edit(Service service)
    {
        if(ModelState.IsValid)
        {
           //update db
        }
        return View(service)
    }

我使用 IE 网络捕获来查看发回的内容,但它只是在中断时显示待处理,然后锁定。我必须承认,我不经常使用它,所以这可能是我的问题。

模型类(省略了特定于类的成员):

    public class Service
    {
       [Key]
       public int ServiceID {get; set;}

       public virtual List<Operation> Operations {get; set;}
    }

    public class Operation
    {
       [Key]
       public int OperationID { get; set; }

       [Required]
       public int ServiceID { get; set; }

       [Required]
       public virtual Service Service { get; set; }

       public virtual ICollection<Parameter> Parameters { get; set; }
    }

    public class Parameter
    {
       [Key]
       public int ParameterID { get; set; }

       [Required]
       public int OperationID { get; set; }

       [Required]
       public virtual Operation Operation { get; set; }
    }
4

1 回答 1

2

您正在调用:

   @Html.EditorFor(m => Model.Parameters)

...这导致发布的参数遵循约定Parameters[i].DataMembers。但是从长远来看,您要绑定的模型不是个体Operation:它是具有属性的整体ServiceOperations并且每个操作都有一个Parameters属性。因此,您希望发布的参数看起来更像Operations[i].Parameters[i].DataMembers.

为此,您需要在调用编辑器时指定 htmlFieldName:

   @Html.EditorFor(m => Model.Parameters, null, "Operations[0].Parameters")

当然,上面的行只适用于第零个操作:您需要动态创建字符串以传递您正在为其创建编辑器的操作的索引。这可能需要额外的修改才能让原始 AJAX 链接首先将索引传递给控制器​​,但您应该能够弄清楚这一点。

于 2012-07-05T17:43:34.333 回答