ASP.net MVC 中的流畅验证 - 数据库验证

Dis*_*ile 5 asp.net-mvc asp.net-mvc-validation fluentvalidation

我在我的 ASP.net MVC 3 项目中使用 Fluent Validation 框架。到目前为止,我所有的验证都非常简单(确保字符串不为空,只有特定长度等),但现在我需要验证数据库中是否存在某些内容。

  1. 在这种情况下应该使用 Fluent Validation 吗?
  2. 如果应该使用 Fluent Validation 完成数据库验证,那么我该如何处理依赖关系?验证器类是自动创建的,我需要以某种方式将我的存储库实例之一传递给它以查询我的数据库。

我试图验证的一个例子可能是:

我的页面上有一个下拉列表,其中包含所选项目的列表。我想在尝试保存新记录之前验证他们选择的项目是否确实存在于数据库中。

编辑
以下是 Fluent Validation 框架中常规验证的代码示例:

[Validator(typeof(CreateProductViewModelValidator))]
public class CreateProductViewModel
{
    public string Name { get; set; }
    public decimal Price { get; set; }
}

public class CreateProductViewModelValidator : AbstractValidator<CreateProductViewModel>
{
    public CreateProductViewModelValidator()
    {
        RuleFor(m => m.Name).NotEmpty();
    }
}
Run Code Online (Sandbox Code Playgroud)

控制器:

public ActionResult Create(CreateProductViewModel model)
{
    if(!ModelState.IsValid)
    {
        return View(model);
    }

    var product = new Product { Name = model.Name, Price = model.Price };
    repository.AddProduct(product);

    return RedirectToAction("Index");
}
Run Code Online (Sandbox Code Playgroud)

如您所见,我从不自己创建验证器。这是因为以下行Global.asax

FluentValidation.Mvc.FluentValidationModelValidatorProvider.Configure();
Run Code Online (Sandbox Code Playgroud)

问题是,现在我有一个验证器需要使用存储库与我的数据库进行交互,但是由于我没有创建验证器,因此除了硬编码具体类型之外,我不知道如何传入该依赖项。

gdo*_*ica 0

我正在使用 FluentValidation 进行数据库验证。只需将 Validation 类传递给 Ctor 中的会话即可。并在操作中进行验证,如下所示:

var validationResult = new ProdcutValidator(session).Validate(product);
Run Code Online (Sandbox Code Playgroud)

更新:根据您的示例,我添加了我的示例......

public class CreateProductViewModel
{
    public string Name { get; set; }
    public decimal Price { get; set; }
}

public class CreateProductViewModelValidator : abstractValidator<CreateProductViewModel>
{
    private readonly ISession _session;
    public CreateProductViewModelValidator(ISession session)
    {
        _session = session;
        RuleFor(m => m.Name).NotEmpty();
        RuleFor(m => m.Code).Must(m, Code => _session<Product>.Get(Code) == null);

    }
}
Controller:

public ActionResult Create(CreateProductViewModel model)
{
    var validator = new CreateProductViewModelValidator();
    var validationResult =validator.Validate(model);

    if(!validationResult.IsValid)
    {
        // You will have to add the errors by hand to the ModelState's errors so the
        // user will be able to know why the post didn't succeeded(It's better writing 
        // a global function(in your "base controller" That Derived From Controller)
        // that migrate the validation result to the 
        // ModelState so you could use the ModelState Only.
        return View(model);
    }

    var product = new Product { Name = model.Name, Price = model.Price };
    repository.AddProduct(product);

    return RedirectToAction("Index");
}
Run Code Online (Sandbox Code Playgroud)

第二次更新:
如果您坚持使用无参数构造函数,您将不得不使用一些反转控制容器,这是一个静态类,类似于对象的工厂。像这样使用它:

public class CreateProductViewModelValidator : abstractValidator<CreateProductViewModel>
{
    private readonly ISession _session;
    public CreateProductViewModelValidator()
    {
        _session = IoC.Container.Reslove<ISession>();
        RuleFor(m => m.Name).NotEmpty();
        RuleFor(m => m.Code).Must(m, Code => _session<Product>.Get(Code) == null);

    }
}
Run Code Online (Sandbox Code Playgroud)

你可以找到很多IoC容器,最著名的是WindsorNinject,你需要注册-指示容器一次来解析所有ISession以返回你的会话对象。