【发布时间】:2014-02-21 11:01:04
【问题描述】:
ASP.Net MVC 4.0 - ViewModel 上基于数组的属性的验证问题。
场景: 当 ViewModel 具有字符串数组作为属性类型时,默认的 Scaffolding 模板(例如 Edit)不会在标记中呈现该属性。
说,我有这样的 ViewModel 设置:
Employee.cs
public class Employee
{
[Required]
public int EmpID
{
get;
set;
}
[Required]
public string FirstName
{
get;
set;
}
[Required]
public string LastName
{
get;
set;
}
[Required]
public string[] Skills
{
get;
set;
}
}
}
由脚手架模板生成的(强类型)编辑视图,如下所示,通常会跳过与字段技能相关的部分。
**Employee.cshtml**
@model StringArray.Models.Employee
@{
ViewBag.Title = "EditEmployee";
}
<h2>EditEmployee</h2>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Employee</legend>
<div class="editor-label">
@Html.LabelFor(model => model.EmpID)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.EmpID)
@Html.ValidationMessageFor(model => model.EmpID)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.FirstName)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.FirstName)
@Html.ValidationMessageFor(model => model.FirstName)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.LastName)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.LastName)
@Html.ValidationMessageFor(model => model.LastName)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
对应的Controller代码是
..
[HttpGet]
public ActionResult EditEmployee()
{
Employee E = new Employee()
{
EmpID = 1,
FirstName = "Sandy",
LastName = "Peterson",
Skills = new string[] { "Technology", "Management", "Sports" }
};
return View(E);
}
[HttpPost]
public ActionResult EditEmployee(Employee E)
{
return View(E);
}
为了获得技能字段的缺失部分,我添加了
-
视图片段
<div class="editor-label"> @Html.LabelFor(model => model.Skills) </div> <div class="editor-field"> @Html.EditorFor(model => model.Skills) @Html.ValidationMessageFor(model => model.Skills) </div> -
ViewModel对应的UIHint
[UIHint("String[]")] public string[] 技能...
-
相关文件夹内的EditorTemplates为 ~\View\shared\EditorTemplates\String[].cshtml 和 ~\View\shared\EditorTemplates\mystring.cshtml
字符串[].cshtml
@model System.String[] @if(Model != null && Model.Any()) { for (int i = 0; i < Model.Length; i++) { @Html.EditorFor(model => model[i], "mystring") //Html.ValidationMessageFor(model => model[i]) } }mystring.cshtml
@model System.String @{ //if(Model != null) { //To resolve issue/bug with extra dot getting rendered in the name - like //Skills.[0], Skills.[1], etc. //ViewData.TemplateInfo.HtmlFieldPrefix=ViewData.TemplateInfo.HtmlFieldPrefix.Replace(".[", "["); @Html.TextBoxFor(model => model) } }
尽管如此,技能部分的验证 [带有 3 个字段/元素 - 请参阅上面 Controller 中的 EditEmployee 方法。] 在回发时完全跳过。
我在 mystring.cshtml EditorTemplate 中尝试了以下更改:
//to correct the rendered names in the browser from Skills.[0] to Skills for all the 3 items in the
//Skills (string array), so that model binding works correctly.
string x = ViewData.TemplateInfo.HtmlFieldPrefix;
x = x.Substring(0, x.LastIndexOf("."));
@Html.TextBoxFor(model =>model, new { Name = x })
回发有效,但验证无效,因为“data-valmsg-for”仍然指向 <span class="field-validation-valid" data-valmsg-for="Skills" data-valmsg-replace="true"></span>
因此不适用于粒度级别 - 字符串元素级别。
最后,我尝试从 Employee.cshtml 中删除 @Html.ValidationMessageFor(model => model.Skills) 并相应地添加 与 string[].cshtml 和 @Html.ValidationMessageFor(model => model[i]) 相同。 但这导致 data-valmsg-for 被渲染为每个细粒度的字符串元素,如
data-valmsg-for="Skills.[0]" , data-valmsg-for="Skills.[1]" 和 data-valmsg-for="Skills.[2]" 分别。
注意:验证适用于其他字段 - EmpID、FirstName LastName,但不适用于技能。
问题 如何为上述与 Skills 属性相关的三个粒度元素中的每一个设置 data-valmsg-for="Skills"。
我已经坚持了很长一段时间了。如果有人能尽早指出问题,那就太好了。
谢谢,Sandesh L
【问题讨论】: