为什么这种模型绑定不起作用?

时间:2012-07-05 17:49:18

标签: c# asp.net-mvc asp.net-mvc-3 razor model

我知道名字在HtmlHelper中的方式正在破坏模型绑定。但我还没弄清楚如何修复它。或者,如果有一个修复。

一点解释。我正在使用一个模型来填充:文本,控件,默认值(选择列表)和保存的值。我正在使用另一个ViewModel只返回:value,dataid和ctrltypeid。已经注释掉的是导致回发ViewModel未填充的代码(例如:Html.TextBoxFor)。工作代码(例如:Html.TextBox)按预期执行。所以我想知道我需要对注释代码做些什么才能让它像未注释的代码一样工作。实际上我可以做什么吗?

@model InspectionWebFormsMVC.ViewModels.FormRowModel

@using (Html.BeginForm("Index", "Section", FormMethod.Post))
    {

            <div style="clear:both; padding:1%;">       
                <div class="section">
                    @Model.Section
                </div>
                <div class="number">
                    @Model.SectionNumber
                </div>
                <div class="desc">
                    @Model.Description
                </div>
                <div class="ctrl">               
            @{
        int i = 0;
        //for (int i = 0; i < formRow.RowInput.Count; ++i)
        foreach (var RowInput in Model.RowInput)
        {
            var ddv = new SelectList(RowInput.RowCtrl.DefaultValues, "Value", "Label");
            switch (RowInput.RowCtrl.Type)
            {
                case "dropdown":
                    //@Html.DropDownListFor(blah => RowInput.InputtedData, ddv)
                    //@Html.HiddenFor(blah => RowInput.InputtedDataID)
                    //@Html.HiddenFor(blah => RowInput.RowCtrl.CtrlTypeID)

                                   @Html.DropDownList("InputtedData", ddv)                                   
                                   @Html.Hidden("InputtedDataID", RowInput.InputtedDataID)
                                   @Html.Hidden("CtrlTypeID", RowInput.RowCtrl.CtrlTypeID)
                                   <br /> 
                              break;
                case "text":
                                   //@Html.TextBoxFor(blah => RowInput.InputtedData)
                                   //@Html.HiddenFor(blah => RowInput.InputtedDataID)
                                   //@Html.HiddenFor(blah => RowInput.RowCtrl.CtrlTypeID)

                                   @Html.TextBox("InputtedData", RowInput.InputtedData)
                                   @Html.Hidden("InputtedDataID", RowInput.InputtedDataID)
                                   @Html.Hidden("CtrlTypeID", RowInput.RowCtrl.CtrlTypeID)   
                                   <br /> 
                              break;
            }
        }
        ++i;
                    }

显然是Postback的Viewmodel。

namespace InspectionWebFormsMVC.ViewModels
{
    public class SaveKeyValueInput
    {
        public long InputtedDataID { get; set; }
        public long CtrlTypeID { get; set; }
        public string InputtedData { get; set; }
    }
}

来自Controller。用于测试。

[HttpPost]
    public ActionResult Index(SaveKeyValueInput placeholder)
    {
        var ha = placeholder;
        var la = "Hello";

        FormRowProcessing placeholder2 = new FormRowProcessing();
        var stub = placeholder2.stub()[2];
        return View(stub);
    }

1 个答案:

答案 0 :(得分:3)

以下是如何使注释代码有效:

for (int i = 0; i < Model.RowInput.Count; i++)
{
    @Html.DropDownListFor(blah => blah.RowInputpi[i].InputtedData, ddv)
    @Html.HiddenFor(blah => blah.RowInput[i].InputtedDataID)
    @Html.HiddenFor(blah => blah.RowInput[i].RowCtrl.CtrlTypeID)
    ...
}

或更好的方法当然是完全摆脱这个丑陋的循环(for或foreach)并用一行代码替换它:

@Html.EditorFor(x => x.RowInput)

现在剩下的就是定义相应的编辑器模板(它将自动由框架为RowInput集合的每个元素呈现,这样您就不必编写任何循环)。编辑器模板按惯例工作。因此,如果您的RowInput属性定义如下:

public IEnumerable<FooBar> RowInput { get; set; }

您定义模板~/Views/Shared/EditorTemplates/FooBar.cshtml

@model FooBar

... put your switches and cases and stuff, but I remove this noise to 
... make the answer more readable

@Html.DropDownListFor(blah => blah.InputtedData, ddv)
@Html.HiddenFor(blah => blah.InputtedDataID)
@Html.HiddenFor(blah => blah.RowCtrl.CtrlTypeID)

但是由于您的表单包含所有记录,因此您发布的相应控制器操作必须与顶级视图模型一起使用,因为您要发送所有内容:

[HttpPost]
public ActionResult Index(FormRowModel model)
{
    ...
}