ASP.NET MVC 中的最佳实践 ViewModel 验证 [英] Best Practices ViewModel Validation in ASP.NET MVC

查看:27
本文介绍了ASP.NET MVC 中的最佳实践 ViewModel 验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 DataAnnotations 在客户端使用 jquery.validate.unobtrusive 和在 ASP 的服务器端验证我的 ViewModel.NET MVC 应用程序.

不久前,我发现我可以像这样编写验证:

[Required(ErrorMessage = "{0} is required")]公共字符串名称 { 获取;放;}

这样我就可以轻松地在 config 或资源中定义一些通用字符串,并始终在 DataAnnotations 中使用它.因此,将来在我的整个应用程序中更改验证消息会更容易.

我也知道有一个 FluentValidation 库,它允许将验证规则添加到现有的 ViewModel.我知道 Add/Edit ViewModels 可能有类似的字段但不同的 ValidationRules 存在问题.

来自客户端验证的另一个问题是应该解析新添加到 DOM(使用 ajax 请求)的 html 以启用验证.我是这样做的:

$('#some-ajax-form').data('validator', null);$.validator.unobtrusive.parse('#some-ajax-form');

所以我有一些问题:

  1. 是否有其他一些有用的做法可以帮助集中应用程序中的所有验证规则?
  2. 解决添加/编辑 ViewModel 验证问题的最佳方法是什么?我可以将 DataAnnotationsFluentValidation 一起使用,或者单独添加和编辑 ViewModels 仍然是最佳选择吗?
  3. 是否有更好的方法来初始化对通过 ajax 调用 接收的新 DOM 元素的验证?

<小时>

我不是在问如何创建我自己的 DataValidators 我知道如何去做.我正在寻找如何以更高效、更易于维护的方式使用它们.

解决方案

首先回答你的第三个问题:不,没有比你正在做的更简单的方法了.两行代码让它工作起来再简单不过了.尽管您可以使用一个插件,如问题中所述不显眼的验证不适用于动态内容

你的第一个问题,如何集中验证,我通常使用一个单独的类文件来存储我所有的验证规则.这样我就不必浏览每个类文件来查找规则,而是将它们全部放在一个地方.如果那更好,那就是选择问题.我开始使用它的主要原因是能够为自动生成的类添加验证,比如来自实体框架的类.

所以我的数据层中有一个名为 ModelValidation.cs 的文件,并且有我所有模型的代码,例如

////<摘要>///<see cref="Test"/> 的验证规则目的///</总结>///<备注>///2015-01-26:创建///</备注>[元数据类型(typeof(TestValidation))]公共部分类测试{}公共类测试验证{///<summary>名称是必需的</summary>[必需的][字符串长度(100)]公共字符串名称 { 获取;放;}///<summary>文本是多行的</summary>[数据类型(DataType.MultilineText)][允许HTML]公共字符串文本 { 获取;放;}}

现在你注意到我没有提供实际的错误信息.我使用 Haacked 的约定 添加消息.可以轻松添加本地化验证规则.

它基本上归结为一个包含以下内容的资源文件:

Test_Name = "提供名称"Test_Name_Required = "名称是必需的"

当你调用像

这样的常规MVC视图代码时,将使用这些消息和命名

<div class="editor-label">@Html.LabelFor(model => model.Name)

<div class="editor-field">@Html.EditorFor(model => model.Name)@Html.ValidationMessageFor(model => model.Name)

您的第二个问题,关于添加/编辑的不同验证可以通过两种方式处理.最好的方法是按照实际意图使用视图.这意味着您不会将实际模型传递给视图,而是创建一个仅包含数据的视图模型.所以你有一个带有正确验证规则的 Create 视图模型和一个带有正确规则的 Edit 视图模型,当它们通过时,你将结果插入到你的实际模型中.然而,这需要更多的代码和手动工作,所以我可以想象你不太愿意这样做.

另一种选择是使用 条件验证,如 viperguynaz 所述.现在,我的需要在编辑/添加之间进行更改的类不再是布尔值,而是具有 primary key Id int.所以我检查是否 Id>0 来确定它是否是一个编辑.

更新:

如果您想在每次 ajax 调用时更新验证,您可以使用 jQuery ajaxComplete.这将在每次 ajax 请求后重新验证所有表单.

$( 文档 ).ajaxComplete(function() {$('form').each(function() {var $el = $(this);$el.data('验证器', null);$.validator.unobtrusive.parse($el);})});

如果这是您想要的,取决于您通过AJAX 收到表单的频率.如果您有很多 AJAX 请求,比如每 10 秒轮询一次状态,那么您不希望这样.如果您偶尔有一个 AJAX 请求,其中主要包含一个表单,那么您可以使用它.

如果您的 AJAX 返回一个您想要验证的表单,那么是的,更新验证是一种很好的做法.但我想一个更好的问题是我真的需要通过 AJAX 发送表单吗?"AJAX 既有趣又有用,但使用时应慎重.

I am using DataAnnotations to validate my ViewModel on client side with jquery.validate.unobtrusive and on server side in ASP.NET MVC application.

Not so long time ago, I figured out that I can write validation like this:

[Required(ErrorMessage = "{0} is required")]
public string Name { get; set; }

That way I can easily define some general strings in config or in resources and always use it in DataAnnotations. So it will be easier to change validation messages in my whole application in future.

Also I know that there is a FluentValidation library that allows to add validation rules to already existing ViewModel. I know that there is a problem with Add/Edit ViewModels that could have similar fields but different ValidationRules.

Another problem that comes from client validation is that html newly added to DOM (using ajax request) should be parsed to enable validation. This is how I do it:

$('#some-ajax-form').data('validator', null); 
$.validator.unobtrusive.parse('#some-ajax-form');

So I have some questions:

  1. Is there some other useful practises that could help centralize all validation rules in application?
  2. What's is a best way to solve Add/Edit ViewModel Validation problem? Can I use DataAnnotations with FluentValidation or separate Add and Edit ViewModels still is a best option?
  3. Is there any better way to initialize validation on new DOM elements that received with ajax call other that I mention?


I'm not asking how to create my own DataValidators I know how to do it. I seeking of ways how to use them in more productive and easy maintainable way.

解决方案

To answer your 3th question first: No there is no easier way then what you are doing. Two lines of code to get it working can hardly be easier. Although there is a plug-in you could use, like explained in the question unobtrusive validation not working with dynamic content

Your first question, how to centralize validation, I normally use a separate class file to store all my validation rules. This way I don't have to browse through every single class file to find the rules, but have them all in one place. If that's better, is matter of choice. The main reason I started to use it, is to be able to add validation to auto-generated classes, like classes from the Entity Framework.

So I have a file called ModelValidation.cs in my data layer, and have code for all my models like

/// <summary>
/// Validation rules for the <see cref="Test"/> object
/// </summary>
/// <remarks>
/// 2015-01-26: Created
/// </remarks>
[MetadataType(typeof(TestValidation))]
public partial class Test { }
public class TestValidation
{
    /// <summary>Name is required</summary>
    [Required]
    [StringLength(100)]
    public string Name { get; set; }

    /// <summary>Text is multiline</summary>
    [DataType(DataType.MultilineText)]
    [AllowHtml]
    public string Text { get; set; }
}

Now as you noticed I don't provide the actual error message. I use conventions by Haacked to add the messages. It makes it simple to add localized validation rules.

It basically comes down to a recource file containing something like:

Test_Name = "Provide name"
Test_Name_Required = "Name is required"

And these messages and naming will be used when you call regular MVC view code like

<div class="editor-container">
    <div class="editor-label">
        @Html.LabelFor(model => model.Name) <!--"Provide name"-->
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.Name)
        @Html.ValidationMessageFor(model => model.Name) <!--"Name is required"-->
    </div>
</div>

Your second question, about different validation for add/edit can be handled in two ways. The best way, would be to use views as they are actually intended. That means you don't pass your actual models to the views, but you create a view model that contains only the data. So you have a view model for Create with the proper validation rules and a view model for Edit with the proper rules, and when they pass you insert the result in your actual model. This however requires a lot more code and manual work, so I can imagine you're not really willing to do it like this.

Another option would be to use conditional validation like explained by viperguynaz. Now instead of a boolean, my classes that require a change between edit/add have a primary key Id int. So I check if Id>0 to determine if it is an edit or not.

UPDATE:

If you want to update validation on every ajax call, you could use jQuery ajaxComplete. This will revalidate all forms after every ajax request.

$( document ).ajaxComplete(function() {
    $('form').each(function() {
        var $el = $(this);
        $el.data('validator', null); 
        $.validator.unobtrusive.parse($el);
    })
});

If this is something you want, depends on how often you receive a form via AJAX. If you have a lot of AJAX request, like polling a status every 10seconds, than you don't want this. If you have an occasional AJAX request, that mostly contains a form, then you could use it.

If your AJAX returns a form you want to validate, then yes, it is good practise to update the validation. But I guess a better question would be "Do I really need to send the form by AJAX?" AJAX is fun and useful, but it should be used with care and thought.

这篇关于ASP.NET MVC 中的最佳实践 ViewModel 验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
C#/.NET最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆