Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hidegh/05d02e9c0d7c65c3acc18270fb9d34d4 to your computer and use it in GitHub Desktop.
Save hidegh/05d02e9c0d7c65c3acc18270fb9d34d4 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web.Mvc;
namespace My.Web.Code.Binder
{
/// <summary>
/// Inside Global.asax:
/// ModelValidatorProviders.Providers.Clear();
/// ModelValidatorProviders.Providers.Add(new MvcDataAnnotationsModelValidatorProviderWithDependencyResolverSupport());
/// </summary>
public class MvcDataAnnotationsModelValidatorProviderWithDependencyResolverSupport : DataAnnotationsModelValidatorProvider
{
private readonly IServiceProvider serviceProvider;
public MvcDataAnnotationsModelValidatorProviderWithDependencyResolverSupport() : this (new MvcServiceProvider())
{
}
public MvcDataAnnotationsModelValidatorProviderWithDependencyResolverSupport(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
RegisterDefaultAdapterFactory(
(metadata, context, attribute) =>
new CustomDataAnnotationsModelValidator(serviceProvider, metadata, context, attribute)
);
RegisterDefaultValidatableObjectAdapterFactory(
(metadata, context) => new CustomValidatableObjectAdapter(serviceProvider, metadata, context)
);
}
//
// Internal (private) classes
//
private class MvcServiceProvider : IServiceProvider
{
public object GetService(Type serviceType)
{
return DependencyResolver.Current.GetService(serviceType);
}
}
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