Each time I start working on a new ASP.NET MVC web application, I'm not sure whether or not to use DataAnnotations
validation. Something about it feels wrong.
每次我开始处理新的ASP.NET MVC Web应用程序时,我都不确定是否使用DataAnnotations验证。关于它的一些事情感觉不对。
For example, let's say I have a UserService
which is passed a CreateUserModel
from the Create
action of the AccountController
. To ensure the user always supplies a name, I set the model's Name
property to have the [Required]
attribute. I'm now safe in the knowledge that the model binder won't ever give me a CreateUserModel
unless it has a name.
例如,假设我有一个UserService,它从AccountController的Create操作传递CreateUserModel。为确保用户始终提供名称,我将模型的Name属性设置为具有[Required]属性。我现在安全地知道模型绑定器不会给我一个CreateUserModel,除非它有一个名字。
My problem is that for my UserService
to be a reusable component of my system, it can't rely on the fact the layer above is supplying valid data, and surely must also validate this data. The need for this is highlighted further when you consider that you may want to write a web service that fully reuses the UserService
(and wouldn't have the model binder to do all the data annotation validation for it).
我的问题是,我的UserService是我系统的可重用组件,它不能依赖上面的层提供有效数据的事实,当然还必须验证这些数据。当您考虑编写完全重用UserService的Web服务(并且没有模型绑定器为其执行所有数据注释验证)时,对此的需求会进一步突出显示。
So my question is: What is the best practice for this situation? Validate with data annotations and repeat that validation in the services? Validate only in the services and throw exceptions? A mix of both?
所以我的问题是:这种情况的最佳做法是什么?使用数据注释进行验证并在服务中重复该验证?仅在服务中验证并抛出异常?两者兼而有之?
I hope my question isn't too subjective, I'm mainly trying to establish a consensus on whether moving the validation to data annotations is going to end up biting me in the end.
我希望我的问题不是太主观,我主要是试图就是否最终将验证转移到数据注释上达成共识。
3 个解决方案
#1
6
I perform all my validation in the service layer, using a combination of manual validations (if x == y) and using Data Annotations.
我使用手动验证(如果x == y)和使用数据注释的组合在服务层执行所有验证。
To use Data Annotations in your service layer, you have to manually use the Validator class using the TryValidateObject()
method. A good example of this can be seen here.
要在服务层中使用数据注释,必须使用TryValidateObject()方法手动使用Validator类。这里可以看到一个很好的例子。
You then have to pass your validation errors down from your service layer to your controller, and have your controller add each error to the Model state error list.
然后,您必须将验证错误从服务层传递到控制器,并让控制器将每个错误添加到模型状态错误列表中。
#2
1
You are right, you should disable the validation on the controller and validate in the service layer. You can still use DataAnnotations if you want to. The service layer can throw an exception with the validation messages, the controller can catch that exception and add the validation messages to the ModelState. You can avoid doing that for each action by handling the validation exception on the OnException method of the controller.
你是对的,你应该在控制器上禁用验证并在服务层验证。如果需要,您仍然可以使用DataAnnotations。服务层可以使用验证消息抛出异常,控制器可以捕获该异常并将验证消息添加到ModelState。您可以通过在控制器的OnException方法上处理验证异常来避免为每个操作执行此操作。
#3
1
I would personally don't mind that things are validated twice, as long as the logic is defined in one single place, which is clearly the case in your situation. I'm not experienced enough to say much about MVC, but I can imagine that throwing exceptions from the service layer just won't give a user experience (UX) that is as good as what MVC can give you when validating (it can for instance show an error message next to the textbox that is invalid. It is much harder to do that when throwing exceptions from your service layer). When the UX is the same, do your validation only in the service, otherwise do it in both layers.
我个人并不介意事情经过两次验证,只要逻辑在一个地方定义,这在你的情况就是如此。我没有足够的经验来谈论MVC,但我可以想象,从服务层抛出异常只是不会给用户体验(UX),这与MVC在验证时可以提供的一样好(它可以用于实例在文本框旁边显示一条无效的错误消息。当从服务层抛出异常时,这样做要困难得多。)当UX相同时,仅在服务中进行验证,否则在两个层中进行验证。
#1
6
I perform all my validation in the service layer, using a combination of manual validations (if x == y) and using Data Annotations.
我使用手动验证(如果x == y)和使用数据注释的组合在服务层执行所有验证。
To use Data Annotations in your service layer, you have to manually use the Validator class using the TryValidateObject()
method. A good example of this can be seen here.
要在服务层中使用数据注释,必须使用TryValidateObject()方法手动使用Validator类。这里可以看到一个很好的例子。
You then have to pass your validation errors down from your service layer to your controller, and have your controller add each error to the Model state error list.
然后,您必须将验证错误从服务层传递到控制器,并让控制器将每个错误添加到模型状态错误列表中。
#2
1
You are right, you should disable the validation on the controller and validate in the service layer. You can still use DataAnnotations if you want to. The service layer can throw an exception with the validation messages, the controller can catch that exception and add the validation messages to the ModelState. You can avoid doing that for each action by handling the validation exception on the OnException method of the controller.
你是对的,你应该在控制器上禁用验证并在服务层验证。如果需要,您仍然可以使用DataAnnotations。服务层可以使用验证消息抛出异常,控制器可以捕获该异常并将验证消息添加到ModelState。您可以通过在控制器的OnException方法上处理验证异常来避免为每个操作执行此操作。
#3
1
I would personally don't mind that things are validated twice, as long as the logic is defined in one single place, which is clearly the case in your situation. I'm not experienced enough to say much about MVC, but I can imagine that throwing exceptions from the service layer just won't give a user experience (UX) that is as good as what MVC can give you when validating (it can for instance show an error message next to the textbox that is invalid. It is much harder to do that when throwing exceptions from your service layer). When the UX is the same, do your validation only in the service, otherwise do it in both layers.
我个人并不介意事情经过两次验证,只要逻辑在一个地方定义,这在你的情况就是如此。我没有足够的经验来谈论MVC,但我可以想象,从服务层抛出异常只是不会给用户体验(UX),这与MVC在验证时可以提供的一样好(它可以用于实例在文本框旁边显示一条无效的错误消息。当从服务层抛出异常时,这样做要困难得多。)当UX相同时,仅在服务中进行验证,否则在两个层中进行验证。