ASP.NET MVC 3: Validating model when information external to the model is required

后端 未结 4 973
南笙
南笙 2020-12-14 22:30

What\'s a good way to validate a model when information external to the model is required in order for the validation to take place? For example, consider the following mod

4条回答
  •  有刺的猬
    2020-12-14 23:19

    Option 1 doesn't fit. The only way it would work would be to pull in the dependency via the service locator anti-pattern.

    Option 2 doesn't work. Although I couldn't see how this was possible because of the C# attribute requirements, it is possible. See the following for references:

    • Resolving IoC Container Services for Validation Attributes in ASP.NET MVC
    • NInjectDataAnnotationsModelValidatorProvider

    Option 3: I didn't know about this earlier, but what appears to be a very powerful way to write validators is to use the ModelValidator class and a corresponding ModelValidatorProvider.

    First, you create your custom ModelValidatorProvider:

    public class CustomModelValidatorProvider : ModelValidatorProvider
    {
        public CustomModelValidatorProvider(/* Your dependencies */) {}
    
        public override IEnumerable GetValidators(ModelMetadata metadata, ControllerContext context)
        {
            if (metadata.ModelType == typeof(YourModel))
            {
                yield return new YourModelValidator(...);
            }
        }
    }
    

    ASP.NET MVC's IDependencyResolver will attempt to resolve the above provider, so as long as it's registered with your IoC container you won't need to do anything else. And then the ModelValidator:

    public class EntryRatingViewModelValidatorMvcAdapter : ModelValidator
    {
        public EntryRatingViewModelValidatorMvcAdapter(
                ModelMetadata argMetadata,
                ControllerContext argContext)
                    : base(argMetadata, argContext)
        {
            _validator = validator;
        }
    
    
        public override IEnumerable Validate(object container)
        {
            if (/* error condition */)
            {
                yield return new ModelValidationResult
                  {
                    MemberName = "Model.Member",
                    Message = "Rating is required."
                  };
            }
        }
    }
    

    As the provider is retrieved through the IDependencyResolver and the provider has full control over the returned ModelValidators I was easily able to inject the dependencies and perform necessary validation.

提交回复
热议问题