-
-
Save tugberkugurlu/3848723 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() | |
{ | |
/* 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>(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
what about when you got 2 kinds of dependency resolvers: webApi And Mvc?