代码之家  ›  专栏  ›  技术社区  ›  Jiveman

如何在页面加载时显示验证错误?

  •  1
  • Jiveman  · 技术社区  · 9 年前

    我正在我的应用程序中创建一个功能,用于处理上载的CSV文件,其中包含要导入的多个记录。数据需要验证,我想在 进口 单击按钮。高层计划:

    • 第2步:显示CSV文件中的所有记录以及每个记录旁边的任何验证错误(缺少必填字段等)

    以下是我所拥有内容的简化版本:

    public class UserViewModel
    {
        [Required]
        [StringLength(100)]
        public string Name { get; set; }
    
        [Required]
        [StringLength(150)]
        public string Email { get; set; }
    
        [Required]
        [StringLength(10)]
        public string Phone { get; set; }
    }
    

    文件上传操作帖子

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Upload(HttpPostedFileBase csvFile)
    {
        // var csvRecords = do stuff to retrieve data from CSV file
        var newUsersToCreate = new List<UserViewModel>();
    
        foreach (var csvRecord in csvRecords)
        {
            newUsersToCreate.Add(new UserViewModel
            {
                Name = csvRecord.Name,
                Email = csvRecord.Email,
                Phone = csvRecord.Phone
            });
        }
        return View("ImportPreview", newUsersToCreate);
    }
    

    @model IEnumerable<App.ViewModels.UserViewModel>
    
    @using (Html.BeginForm())
    {
        @Html.AntiForgeryToken()
        @Html.ValidationSummary(true, "", new { @class = "alert alert-danger", role = "alert" })
    
        <table>
            <thead>
                <tr>
                    <th>Name</th>
                    <th>Email</th>
                    <th>Phone</th>
                    <th>Validation Errors</th>
                </tr>
            </thead>
            <tbody>
                @Html.EditorFor(model => model)
            </tbody>
        </table>
    
        <button type="submit">Import</button>
    }
    

    UserViewModel的编辑器模板。cshtml

    @model App.ViewModels.UserViewModel
    
    <tr>
        <td>
            @Html.HiddenFor(model => model.Name)
            @Html.DisplayFor(model => model.Name)
        </td>
        <td>
            @Html.HiddenFor(model => model.Email)
            @Html.DisplayFor(model => model.Email)
        </td>
        <td>
            @Html.HiddenFor(model => model.Phone)
            @Html.DisplayFor(model => model.Phone)
        </td>
        <td>
            @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
            @Html.ValidationMessageFor(model => model.Email, "", new { @class = "text-danger" })
            @Html.ValidationMessageFor(model => model.Phone, "", new { @class = "text-danger" })
        </td>
    </tr>
    

    问题

    而这将生成一个很好的“预览”表,其中包含所有已准备好的内容 User 记录本质上是准备就绪的隐藏字段行,问题是在

    我如何让它在每行中显示每个字段的验证错误,就在 return View('ImportPreview', newUsersToCreate) 带着风景回来?

    1 回复  |  直到 9 年前
        1
  •  3
  •   user3559349 user3559349    9 年前

    您可以在视图中通过检查 $.validator 有效。由于默认情况下不会验证隐藏输入,因此还需要覆盖验证器。在后面添加以下内容 jquery-{version}.js jquery.validate.js 和 jquery.validate.unobtrusive.js 脚本(但不在 $(document).ready()

    <script>
        // override validator to include hidden inputs
        $.validator.setDefaults({ 
            ignore: [] 
        });
        // validate form and display errors
        $('form').valid();
    </script>
    

    请注意,您可能包括(比如) <p id="error" style="display:none;"> 包含数据无效的“常规”错误消息的标记,并使用

    if ($('form').valid()) {
        $('#error').show();
    }
    

    缺点是需要包含jQuery脚本,否则就不需要这些脚本。

    另一种选择是使用在控制器中进行验证 TryValidateObject ModelState 将显示在您的 ValidationMessageFor() 占位符。注意以下假设 csvRecords 机具 IList<T> 这样你就可以使用 for

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Upload(HttpPostedFileBase csvFile)
    {
        // var csvRecords = do stuff to retrieve data from CSV file
        var newUsersToCreate = new List<UserViewModel>();
        for (int i = 0; i < csvRecords.Count; i++)
        {
            UserViewModel model = new UserViewModel
            {
                Name = csvRecords[i].Name,
                ....
            };
            newUsersToCreate.Add(model);
            // validate the model and include the collection indexer
            bool isValid = ValidateModel(model, i));   
        }
        return View("ImportPreview", newUsersToCreate);
    }
    
    private bool ValidateModel(object model, int index) 
    { 
        var validationResults = new List<ValidationResult>(); 
        var context = new ValidationContext(model); 
        if (!Validator.TryValidateObject(model, context, validationResults, true)) 
        { 
            foreach (var error in validationResults) 
            { 
                string propertyName = $"[{index}].{error.MemberNames.First()}"; 
                ModelState.AddModelError(propertyName, error.ErrorMessage); 
            } 
            return false; 
        } 
        return true; 
    }
    

    控制器代码的优点是可以向视图模型中添加其他属性(例如 bool IsValid