ASP.NET MVC 3:在需要模型外部信息时验证模型

时间:2011-10-12 17:10:40

标签: asp.net-mvc-3 validation

如果需要模型外部的信息才能进行验证,那么验证模型的好方法是什么?例如,请考虑以下模型:

public class Rating {
    public string Comment { get; set; }
    public int RatingLevel { get; set; }
}

然后,系统管理员可以设置需要注释的RatingLevels。这些设置可通过设置服务获得。

因此,为了完全验证模型,我需要外部信息,在这种情况下是设置服务。

到目前为止,我已经考虑了以下内容:

  1. 将服务注入模型。 DefaultModelBinder使用System.Activator创建对象,因此它不会通过正常的依赖项解析器,我无法注入服务进入模型而不创建新的模型绑定器(除此之外,这不是正确的方法)。
  2. 将服务注入注释。我还不确定这是否可行,但会尽快进行调查。它仍然感觉很笨拙。
  3. 使用自定义模型绑定器。显然,我可以实现OnPropertyValidating来进行自定义属性验证。到目前为止,这似乎是最优选的,但我还不确定该怎么做。
  4. 哪种方法,无论上述与否,最适合此类验证问题?

4 个答案:

答案 0 :(得分:14)

选项1不合适。唯一可行的方法是通过服务定位器反模式拉入依赖项。

选项2 不起作用虽然由于C#属性要求我无法看到这是如何可能的,但这是可能的。请参阅以下内容以获取参考:

选项3:我之前不知道这一点,但似乎是一种非常强大的编写验证器的方法是使用ModelValidator类和相应的{{3 }}

首先,您创建自定义ModelValidatorProvider:

public class CustomModelValidatorProvider : ModelValidatorProvider
{
    public CustomModelValidatorProvider(/* Your dependencies */) {}

    public override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context)
    {
        if (metadata.ModelType == typeof(YourModel))
        {
            yield return new YourModelValidator(...);
        }
    }
}

ASP.NET MVC的ModelValidatorProvider将尝试解析上述提供程序,因此只要它已在您的IoC容器中注册,您就不需要执行任何其他操作。然后是ModelValidator:

public class EntryRatingViewModelValidatorMvcAdapter : ModelValidator
{
    public EntryRatingViewModelValidatorMvcAdapter(
            ModelMetadata argMetadata,
            ControllerContext argContext)
                : base(argMetadata, argContext)
    {
        _validator = validator;
    }


    public override IEnumerable<ModelValidationResult> Validate(object container)
    {
        if (/* error condition */)
        {
            yield return new ModelValidationResult
              {
                MemberName = "Model.Member",
                Message = "Rating is required."
              };
        }
    }
}

当通过IDependencyResolver检索提供程序并且提供程序完全控制返回的ModelValidator时,我很容易注入依赖项并执行必要的验证。

答案 1 :(得分:5)

您可以尝试fluent validation。它支持asp.net mvc和DI,因此您可以将外部服务注入验证器。

答案 2 :(得分:1)

假设您希望根据服务返回的值对模型进行客户端和服务器端验证,我会选择2.,将服务注入注释

我在回复this question about adding validators to a model时提供了一些示例代码。在您的情况下,唯一的另一步是您需要将您的服务注入继承自DataAnnotationsModelValidatorProvider的类。

答案 3 :(得分:0)

如何简单地使用IValidateableObject并在该方法中确定验证是否合适并在那里设置错误?

How do I use IValidatableObject?