【问题标题】:ASP.Net MVC 4.0 - Validation Issues With array based properties on ViewModelASP.Net MVC 4.0 - ViewModel 上基于数组的属性的验证问题
【发布时间】: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”仍然指向 &lt;span class="field-validation-valid" data-valmsg-for="Skills" data-valmsg-replace="true"&gt;&lt;/span&gt; 因此不适用于粒度级别 - 字符串元素级别。

最后,我尝试从 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

【问题讨论】:

    标签: asp.net-mvc validation


    【解决方案1】:

    这是你想改变的地方

       [Required]
        public string[] Skills
        {
            get;
            set;
        }
    

    您正在对数组进行验证。

    你可能想要一个新的字符串类调用 Skill

    [Required]
    public string Skill
    {
                get;
                set;
    }
    

    您可以使用

    更改为您的模型
        [Required]
        public List<Skill> Skills
        {
            get;
            set;
        }
    

    我更喜欢使用 List 而不是数组。然后,您可以根据更新的模型更改您的技能视图

    你的模板视图可以是这样的

    @model IEnumerable<Skill>
    
    <div class="editor-label">
     <h3>@Html.LabelFor(model=> model.Skills)
    </h3> 
    </div> 
    
    <div class="editor-field"> 
    @foreach (var item in Model)
     { @Html.Label(model => item) 
       @Html.TextBoxFor(model => item) <br/> 
    } 
    @Html.ValidationMessageFor(model => item)
    

    【讨论】:

    • 尝试您的建议,对视图进行相应的更改,例如:

      @Html.LabelFor(model=> model.Skills)

      @for(int i =0; i )(Model.Skills)).Count; i++) { @Html.标签(Model.Skills[i].ToString()) @Html.TextBox("skill", Model.Skills[i].SkillName})
      } @Html.ValidationMessageFor(model => model.Skills),导致技能在回发时为空:(.
    • Sandesh Lohar,确保您将 Employee 模型回传到控制器。我遇到了和你一样的问题,数组永远不会有效,但米勒说的是正确的。您需要创建一个新模型,专门用于技能本身而不是数组所需的处理。
    猜你喜欢
    相关资源
    最近更新 更多
    热门标签