我有一个多层项目。层如下:
我在实体层有一个Category类:
public class Category : IEntity
{
public int Id { get; set; }
public string Name { get; set; }
}
我在业务层中还有一个CategoryValidator类:
public class CategoryValidator : AbstractValidator<Category>
{
public CategoryValidator(IEnumerable<Category> categories)
{
RuleFor(x => x.Name).NotEmpty().MaximumLength(50);
}
}
我在Core层有一个用于验证的类。
public class ValidatorTool
{
public static void FluentValidate(IValidator validator, object entity)
{
var result = validator.Validate(entity);
if (result.Errors.Any())
throw new ValidationException(result.Errors);
}
}
我正在使用FluentValidate方法在业务层中执行验证。
但是当涉及到MvcWebUI层时,我陷入了困境。根据{{3}},我需要将一个属性应用于实体类,如下所示:
[Validator(typeof(PersonValidator))]
但是由于业务层引用了实体层,所以我无法到达实体层中的CategoryValidator类。 (圆圈参考)
如何解决此问题? 我是否创建了错误的图层? 还是应该在Web层中再次将实体定义为模型? 请帮助我。
答案 0 :(得分:0)
通常,您有2种执行验证的方法:
对于第一点,您需要验证放置在Web项目中的视图模型(在客户端和服务器上)。在这种情况下,您也应该在Web项目中放置视图模型验证器。需要[Validator(typeof(PersonValidator))]
属性来链接动作的视图模型参数和动作本身,以在动作执行之前执行验证。如文档中所述:
在内部,FluentValidation的MVC集成利用验证器工厂来知道如何确定应使用哪个验证器来验证特定类型。默认情况下,FluentValidation附带了
AttributedValidatorFactory
,它允许您通过装饰类以使用标识其相应验证器的属性来验证器,使其与验证器类型链接。
如果您要验证业务模型(第二点),而不仅仅是/不仅要查看模型,则需要将实体验证器放置到业务项目中,然后将其注册到IoC容器中({{ 3}}和温莎城堡(Castle Windsor)),然后更改验证器工具:
public class ValidatorTool
{
public static void FluentValidate<T>(IContainer container, T entity) // replace IContainer with your actual container interface name
{
var validator = container.Resolve<IValidator<T>>();
var result = validator.Validate(entity);
if (result.Errors.Any())
throw new ValidationException(result.Errors);
}
}
答案 1 :(得分:0)
首先,您可能不应该直接在UI中公开您的实体,所以我建议您在其中创建新模型,并专门为它们编写验证器。
假设此方法正确连接,则此方法意味着在MVC应用程序的HTTP POST期间将自动触发验证程序,并使用错误列表自动更新模型状态。
尽管在调用内部API的MVC应用程序中,我仍广泛使用此方法。
在我的大多数情况下,MVC客户端会验证模型,如果通过了检查,则将使用与Automapper映射的DTO /服务/实体模型,然后调用API或服务层。
MVC验证通常比较简单,并且会检查必填字段,长度等。
API会再次进行验证,但是会在实体上进行验证,这次会更加深入,因为它会检查重复项,无效的实体状态等。
我要添加的最后一条评论。我不会在验证错误上抛出异常。 UI应该使用ModelState,并且服务层返回结果,客户端知道如何将其合并回ModelState,因此,无论哪种情况,都会导致用户获得大量要处理的错误列表。
希望这会有所帮助!