Skip to content

Instantly share code, notes, and snippets.

@benfoster
Created October 7, 2012 15:45
Show Gist options
  • Save benfoster/3848715 to your computer and use it in GitHub Desktop.
Save benfoster/3848715 to your computer and use it in GitHub Desktop.
Adding IServiceProvider to ValidationContext in ASP.NET MVC
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