Created
November 5, 2012 11:54
-
-
Save benfoster/4016852 to your computer and use it in GitHub Desktop.
Web API validation
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
using StructureMap; | |
using System; | |
using System.Collections.Generic; | |
using System.ComponentModel.DataAnnotations; | |
using System.Linq; | |
using System.Web.Http; | |
using System.Web.Mvc; | |
using System.Web.Optimization; | |
using System.Web.Routing; | |
using ValidationDemo.Application; | |
namespace ValidationDemo | |
{ | |
// Note: For instructions on enabling IIS6 or IIS7 classic mode, | |
// visit http://go.microsoft.com/?LinkId=9394801 | |
public class MvcApplication : System.Web.HttpApplication | |
{ | |
protected void Application_Start() | |
{ | |
AreaRegistration.RegisterAllAreas(); | |
WebApiConfig.Register(GlobalConfiguration.Configuration); | |
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); | |
RouteConfig.RegisterRoutes(RouteTable.Routes); | |
BundleConfig.RegisterBundles(BundleTable.Bundles); | |
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