我有三个级联下拉列表使用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>
}`
吉兹,我听起来像一个绝望的白痴。
谢谢你的帮助。
答案 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
属性,并且name
与id
相同,你的模型中必须有一个属性,如
public string dp1391795955619 { get; set; }
让它显示在你的控制器动作中。您可以手动设置name
,只要它以MVC的预期方式命名,以便在发布时将其传递给模型。
在我的例子中,我试图强调的部分是类和属性名称之间的关系,而不是MVC写入HTML文档的名称属性,以及它如何保持所有这些东西。在简单的示例中,您不必考虑它。但是在您的复杂场景中,您似乎必须手动管理一些命名约定,以便MVC能够理解您正在尝试做的事情。