Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>As I was looking to solve this I wanted to make it so that the same validator instance could be used for MVC and Web API. I was able to accomplish this by making two factories and using them together.</p> <p>MVC Factory:</p> <pre><code>public class MVCValidationFactory : ValidatorFactoryBase { private readonly IKernel _kernel; public MVCValidationFactory(IKernel kernel) { _kernel = kernel; } public override IValidator CreateInstance(Type validatorType) { var returnType = _kernel.TryGet(validatorType); return returnType as IValidator; } } </code></pre> <p>API Factory:</p> <pre><code>public class WebAPIValidationFactory : ModelValidatorProvider { private readonly MVCValidationFactory _mvcValidationFactory; private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); public WebAPIValidationFactory(MVCValidationFactory mvcValidationFactory) { _mvcValidationFactory = mvcValidationFactory; } public override IEnumerable&lt;ModelValidator&gt; GetValidators(ModelMetadata metadata, IEnumerable&lt;ModelValidatorProvider&gt; validatorProviders) { try { var type = GetType(metadata); if (type != null) { var fluentValidator = _mvcValidationFactory.CreateInstance(typeof(FluentValidation.IValidator&lt;&gt;).MakeGenericType(type)); if (fluentValidator != null) { yield return new FluentValidationModelValidator(validatorProviders, fluentValidator); } } } catch (Exception ex) { Log.Error(ex); } return new List&lt;ModelValidator&gt;(); } private static Type GetType(ModelMetadata metadata) { return metadata.ContainerType != null ? metadata.ContainerType.UnderlyingSystemType : null; } </code></pre> <p>The trick then was figuring out how to run the validation for both MVC and Web API. I ended up creating a wrapper for the IValidator&lt;> that worked with the ModelValidator signature.</p> <pre><code>public class FluentValidationModelValidator : ModelValidator { public IValidator innerValidator { get; private set; } public FluentValidationModelValidator( IEnumerable&lt;ModelValidatorProvider&gt; validatorProviders, IValidator validator) : base(validatorProviders) { innerValidator = validator; } public override IEnumerable&lt;ModelValidationResult&gt; Validate(ModelMetadata metadata, object container) { if (InnerValidator != null &amp;&amp; container != null) { var result = innerValidator.Validate(container); return GetResults(result); } return new List&lt;ModelValidationResult&gt;(); } private static IEnumerable&lt;ModelValidationResult&gt; GetResults(FluentValidation.Results.ValidationResult result) { return result.Errors.Select(error =&gt; new ModelValidationResult { MemberName = error.PropertyName, Message = error.ErrorMessage })); } } </code></pre> <p>The last part was to wire up the validators in the Global.asax:</p> <pre><code>MVCValidationFactory mvcValidationFactory = new MVCValidationFactory(KernelProvider.Instance.GetKernel()); GlobalConfiguration.Configuration.Services.Add( typeof(ModelValidatorProvider), new WebAPIValidationFactory(mvcValidationFactory)); ModelValidatorProviders.Providers.Add(new FluentValidationModelValidatorProvider(mvcValidationFactory)); DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false; </code></pre> <p>Sorry this was a bit long, but hopefully it helps someone out.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload