Created
October 7, 2012 15:45
-
-
Save benfoster/3848715 to your computer and use it in GitHub Desktop.
Adding IServiceProvider to ValidationContext in ASP.NET MVC
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class MvcApplication : System.Web.HttpApplication | |
{ | |
protected void Application_Start() | |
{ | |
ObjectFactory.Configure(cfg => | |
{ | |
cfg.For<IEmailValidator>().Use<EmailValidator>(); | |
}); | |
var resolver = new StructureMapDependencyResolver(ObjectFactory.Container); | |
ModelValidatorProviders.Providers.Clear(); | |
ModelValidatorProviders.Providers.Add( | |
new CustomDataAnnotationsModelValidatorProvider(resolver)); | |
} | |
} | |
public class StructureMapDependencyResolver : IDependencyResolver, IServiceProvider | |
{ | |
private readonly IContainer container; | |
public StructureMapDependencyResolver(IContainer container) | |
{ | |
this.container = container; | |
} | |
public object GetService(Type serviceType) | |
{ | |
if (serviceType.IsAbstract || serviceType.IsInterface) | |
return container.TryGetInstance(serviceType); | |
return container.GetInstance(serviceType); | |
} | |
public IEnumerable<object> GetServices(Type serviceType) | |
{ | |
return container.GetAllInstances(serviceType).Cast<object>(); | |
} | |
} | |
public class CustomDataAnnotationsModelValidatorProvider : DataAnnotationsModelValidatorProvider | |
{ | |
private readonly IServiceProvider serviceProvider; | |
public CustomDataAnnotationsModelValidatorProvider(IServiceProvider serviceProvider) | |
{ | |
this.serviceProvider = serviceProvider; | |
DataAnnotationsModelValidatorProvider.RegisterDefaultAdapterFactory( | |
(metadata, context, attribute) => | |
new CustomDataAnnotationsModelValidator(serviceProvider, metadata, context, attribute) | |
); | |
DataAnnotationsModelValidatorProvider.RegisterDefaultValidatableObjectAdapterFactory( | |
(metadata, context) => new CustomValidatableObjectAdapter(serviceProvider, metadata, context) | |
); | |
} | |
private class CustomDataAnnotationsModelValidator : DataAnnotationsModelValidator | |
{ | |
private readonly IServiceProvider serviceProvider; | |
public CustomDataAnnotationsModelValidator(IServiceProvider serviceProvider, ModelMetadata metadata, ControllerContext context, ValidationAttribute attribute) | |
: base(metadata, context, attribute) | |
{ | |
this.serviceProvider = serviceProvider; | |
} | |
public override IEnumerable<ModelValidationResult> Validate(object container) | |
{ | |
ValidationContext context = new ValidationContext(container ?? Metadata.Model, serviceProvider, null); | |
context.DisplayName = Metadata.GetDisplayName(); | |
ValidationResult result = Attribute.GetValidationResult(Metadata.Model, context); | |
if (result != ValidationResult.Success) | |
{ | |
yield return new ModelValidationResult | |
{ | |
Message = result.ErrorMessage | |
}; | |
} | |
} | |
} | |
private class CustomValidatableObjectAdapter : ValidatableObjectAdapter | |
{ | |
private readonly IServiceProvider serviceProvider; | |
public CustomValidatableObjectAdapter(IServiceProvider serviceProvider, ModelMetadata metadata, ControllerContext context) | |
: base(metadata, context) | |
{ | |
this.serviceProvider = serviceProvider; | |
} | |
public override IEnumerable<ModelValidationResult> Validate(object container) | |
{ | |
object model = Metadata.Model; | |
if (model == null) | |
{ | |
return Enumerable.Empty<ModelValidationResult>(); | |
} | |
IValidatableObject validatable = model as IValidatableObject; | |
if (validatable == null) | |
{ | |
throw new InvalidOperationException(); | |
} | |
ValidationContext validationContext = new ValidationContext(validatable, serviceProvider, null); | |
return ConvertResults(validatable.Validate(validationContext)); | |
} | |
private IEnumerable<ModelValidationResult> ConvertResults(IEnumerable<ValidationResult> results) | |
{ | |
foreach (ValidationResult result in results) | |
{ | |
if (result != ValidationResult.Success) | |
{ | |
if (result.MemberNames == null || !result.MemberNames.Any()) | |
{ | |
yield return new ModelValidationResult { Message = result.ErrorMessage }; | |
} | |
else | |
{ | |
foreach (string memberName in result.MemberNames) | |
{ | |
yield return new ModelValidationResult { Message = result.ErrorMessage, MemberName = memberName }; | |
} | |
} | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment