MVC 4模型未返回控制器

时间:2014-02-06 23:35:59

标签: asp.net-mvc-4

我有三个级联下拉列表使用Ajax在视图上填充自己。同样在视图中,我调用部分视图,该部分视图迭代模型中的容器,并且对于每个项目调用另一个部分以显示,以根据下拉列表中的所选项目编辑适当的模型属性。我构建了一个复杂的模型,其中包含下拉选项以及要编辑的属性,并将模型的一部分传递给显示要编辑的属性所需的最低级别部分。

我希望在用户通过普通的Html.BeginForm点击提交按钮时更新数据库,而不是使用Ajax。所以我必须只包含在表单中显示属性的部分,以便现有的Ajax功能不会发布到控制器。问题是虽然我可以构建所有这些,并且提交按钮按预期连接到控制器,但模型返回到控制器null。

模型是否不会从部分向上通过构建它们的路径返回?或者更准确地说,即使是使用partials构建模型,模型也不会在页面上持续存在?

我相信有人会建议我使用Ajax回发,但这不是我的最佳选择。或者有人可能会问页面上的html是什么样的。奇怪的是,我只能使用浏览器开发人员工具查看完整的html,它不会在View Source选择中显示。

有什么想法吗?

将其移至所属的位置:
我不确定我理解。我知道返回的模型需要匹配预期的模型,但我没有得到上面的解释。你说“所以,如果你的控制器看起来像这样:”,当然它确实如此,那么呢?那是错的? 我必须查看Chrome的开发工具才能看到实际的html输出,我在一个案例中看到了这一点:
<input class="text-box single-line" id="status_Comments" name="status.Comments" type="text" value="Last Install to be completed this weekend">

因此,如果'name'标签需要看起来合适,我认为确实如此。我错了吗?

我的日期字段如下所示:
<input type="text" value="8/19/2014" class="datepicker hasDatepicker" id="dp1391795955619">

所以没有'name'标签,但确实有id。我需要添加名称吗?

以下是生成上述内容的代码:
@foreach (Status status in Model) {
string date = status.Date.HasValue ? status.Date.Value.ToShortDateString() : string.Empty;
<tr>
<td style="width: 175px;">@Html.DisplayFor(model => status.Name)</td>
<td style="width: 75px;">@Html.DisplayDropdownColorFor(model => status.StatusValue)</td>
<td style="width: 80px;"><input type="text" value="@date" class="datepicker" /></td>
<td style="width: 80px;"><input type="text" value="" class="datepicker" /></td>
<td style="width: 375px;">@Html.EditorFor(model => status.Comments)</td>
</tr>         }`
吉兹,我听起来像一个绝望的白痴。 谢谢你的帮助。

1 个答案:

答案 0 :(得分:0)

假设您有几个这样的课程:

public class SomeClass1 
{
    public string Name { get; set; }
    public SomeClass2 class2Value { get; set; }
}

public class SomeClass2
{
    public string Description { get; set; }
}

你在Razor视图中有一个表单:

@model SomeClass1

@using (Html.BeginForm()) {
    <fieldset>
        <div class="editor-label">
            @Html.LabelFor(model => model.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Name)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.class2Value.Description)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.class2Value.Description)
        </div>

        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

实际的HTML代码看起来像这样:

<form id="form1" action="/pageurl" method="POST">
    <fieldset>
        <div class="editor-label">
            Name
        </div>
        <div class="editor-field">
            <input type="text" name="Name" id="Name" value="Name val 1" />
        </div>

        <div class="editor-label">
            Description
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.class2Value.Description)
            <input type="text" name="class2Value.Description" id="class2Value_Description" value="Desc val 2" />
        </div>

        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
</form>

如果您注意到,表单字段的name属性由MVC设置为遵循模型。在嵌套对象的情况下,它使用名称中的ID和句点中的下划线来跟踪值应该在帖子模型中的位置。

所以如果您的控制器看起来像这样:

[HttpPost]
protected ActionResult Save(SomeClass1 model)
{
    //Then 
    // SomeClass1.Name == "Name val 1"
    // and 
    // SomeClass1.class2Value.Description == "Desc val 2"
}

这就是@David在评论中得到的内容......无论您的网页有多复杂,当<form>发回服务器时,您返回的字段的name属性都有与控制器操作所期望的模型对齐......或者您将得到null值。

您甚至可以为帖子模型创建自定义类,只要name属性与模型对齐,即使它与顶部的@model不同在Razor视图中,MVC将使用键/值对并填充帖子模型中的数据。

<强>更新

我更新了上述内容以反映更正。下划线是ID属性中的分隔符,句点用于NAME属性。

@leemid:HTML form仅发布带有name属性的字段。提交name时,只有form'ed输入,选择,textareas等将传回服务器。这些名称必须与控制器所期望的模型内联。为了听起来多余,您展示示例的日期input字段没有name属性,并且nameid相同,你的模型中必须有一个属性,如

public string dp1391795955619 { get; set; }

让它显示在你的控制器动作中。您可以手动设置name,只要它以MVC的预期方式命名,以便在发布时将其传递给模型。

在我的例子中,我试图强调的部分是类和属性名称之间的关系,而不是MVC写入HTML文档的名称属性,以及它如何保持所有这些东西。在简单的示例中,您不必考虑它。但是在您的复杂场景中,您似乎必须手动管理一些命名约定,以便MVC能够理解您正在尝试做的事情。

相关问题