Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Adding IServiceProvider to ValidationContext in ASP.NET MVC
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
/* usual sh** ommitted for brevity */
var resolver = new CustomDependencyResolver();
DependencyResolver.SetResolver(resolver);
DataAnnotationsModelValidatorProvider.RegisterDefaultAdapterFactory(
(metadata, context, attribute) =>
new CustomDataAnnotationsModelValidator(resolver, metadata, context, attribute)
);
DataAnnotationsModelValidatorProvider.RegisterDefaultValidatableObjectAdapterFactory(
(metadata, context) => new CustomValidatableObjectAdapter(resolver, metadata, context)
);
}
}
public class CustomDependencyResolver : IDependencyResolver, IServiceProvider
{
public object GetService(Type serviceType)
{
if (serviceType == typeof(IEmailValidator))
return new EmailValidator();
return null;
}
public IEnumerable<object> GetServices(Type serviceType)
{
return Enumerable.Empty<object>();
}
}
public 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
};
}
}
}
public 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(
// String.Format(
// CultureInfo.CurrentCulture,
// MvcResources.ValidatableObjectAdapter_IncompatibleType,
// typeof(IValidatableObject).FullName,
// model.GetType().FullName));
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 };
}
}
}
}
}
}
public interface IEmailValidator
{
bool IsValid(string email);
}
public class EmailValidator : IEmailValidator
{
private string[] emails = new[] {
"john@evil.com",
"jane@killingkittens.com",
"me@you.com"
};
public bool IsValid(string email)
{
return (!string.IsNullOrEmpty(email) &&
!emails.Contains(email));
}
}
public class UniqueEmailAttribute : ValidationAttribute
{
IEmailValidator validator;
public override bool IsValid(object value)
{
if (validator == null)
return true;
return validator.IsValid(value as string);
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
validator = validationContext.GetService(typeof(IEmailValidator))
as EmailValidator;
return base.IsValid(value, validationContext);
}
}
public class RegistrationModel : IValidatableObject
{
[Required]
public string Name { get; set; }
[Required]
[EmailAddress]
[UniqueEmail]
public string Email { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
[Required]
[Display(Name = "Confirm Password")]
[DataType(DataType.Password)]
[Compare("Password")]
public string ConfirmPassword { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var validator = validationContext.GetService(typeof(IEmailValidator)) as IEmailValidator;
// could validate here...too
return Enumerable.Empty<ValidationResult>();
}
}
@hidegh

This comment has been minimized.

Copy link

commented May 17, 2017

what about when you got 2 kinds of dependency resolvers: webApi And Mvc?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.