Limitations of MVC2’s ModelValidatorProviders

One of the new features in ASP.NET MVC 2 is the ability the ability to define multiple validation providers. These are used by the DefaultModelBinder to automatically validate your model objects when they are passed to action parameters.

I wanted to try and write one of these for FluentValidation (see this post) but after trying this it has become quite clear that the ModelValidatorProvider API does have some limitations which have caused me some problems.

Problem 1: Property-level validation

To understand this problem, first we need to look at how different validation frameworks perform their work.

When using FluentValidation, the validators work against a pre-populated object. For example:

public class CustomerValidator : AbstractValidator<Customer{ 
  public CustomerValidator() {
     RuleFor(x => x.Surname).NotNull();
     RuleFor(x => x.CreditLimit).GreaterThanOrEqualTo(0);
  }
}
 
var customer = new Customer { CreditLimit = -1, Surname = null };
var validator = new CustomerValidator();
var results = validator.Validate(customer);

You cannot reliably validate individual properties by themselves because they may have dependencies on *other* properties being set. For example:

RuleFor(x => x.Surname).NotEqual(x => x.Forename);

This rule says tht the Surname and Forename properties must not be equal. In this case, you cannot validate the surname property by itself without having first set the value for the Forename property. Other validation frameworks (eg the Castle Project’s validation attributes) work in a similar way.

The MVC Framework’s DefaultModelBinder is primarily designed to work with the System.ComponentModel.DataAnnotations attributes. These work in a different way – they validate individual values, not the entire object. To support this, the DefaultModelBinder allows validating both the individual property values (in the OnPropertyValidated method) as well as validating the entire instance (in the OnModelUpdated method).

Here are the relevant methods from DefaultModelBinder:

//OnPropertyValidated - called for each property being bound.
protected virtual void OnPropertyValidated(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, object value) {
    ModelMetadata propertyMetadata = bindingContext.PropertyMetadata[propertyDescriptor.Name];
    propertyMetadata.Model = value;
    string modelStateKey = CreateSubPropertyName(bindingContext.ModelName, propertyMetadata.PropertyName);
 
    // run validation
    foreach (ModelValidator validator in propertyMetadata.GetValidators(controllerContext)) {
        foreach (ModelValidationResult validationResult in validator.Validate(bindingContext.Model)) {
            bindingContext.ModelState.AddModelError(CreateSubPropertyName(modelStateKey, validationResult.MemberName), validationResult.Message);
        }
    }
 
    // only add a "value was required" error message if there were no validation errors
    if (bindingContext.ModelState.IsValidField(modelStateKey)) {
        if (value == null && !TypeHelpers.TypeAllowsNullValue(propertyDescriptor.PropertyType)) {
            bindingContext.ModelState.AddModelError(modelStateKey, GetValueRequiredResource(controllerContext));
        }
    }
}
//OnModelUpdated - called once the entire object has been bound. 
protected virtual void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext) {
    IDataErrorInfo errorProvider = bindingContext.Model as IDataErrorInfo;
    if (errorProvider != null) {
         string errorText = errorProvider.Error;
         if (!String.IsNullOrEmpty(errorText)) {
            bindingContext.ModelState.AddModelError(bindingContext.ModelName, errorText);
          }
    }
 
    if (!IsModelValid(bindingContext)) {
        return;
    }
 
    foreach (ModelValidator validator in bindingContext.ModelMetadata.GetValidators(controllerContext)) {
        foreach (ModelValidationResult validationResult in validator.Validate(null)) {
            bindingContext.ModelState.AddModelError(CreateSubPropertyName(bindingContext.ModelName, validationResult.MemberName), validationResult.Message);
        }
    }
}

On first glance, this looks like it will work. When OnPropertyValidated calls GetValidators, I can return an empty collection of validators and do all of my work in a single validator in OnModelUpdated. Unfortunately, this does not work.

See the end of OnPropertyValidated? Here, it checks if there have been any validation errors for the property and if not then it will go ahead and run its own built-in field validation anyway for non-nullable value types – it will put a message saying “A value was required” into ModelState. And you can’t turn this off. The *only way* to stop this built-in validation is to support property-level validation in your custom ValidatorProvider. Not very useful if the underlying framework does not support this.

To work around the above issue, I ended up adding property-level validation to FluentValidation, but this is not a completely reliable solution because of the issues related to cross-property validation I mentioned above.

Problem 2: The DataAnnotationsModelValidatorProvider is greedy

The next problem that I ran into is that the DataAnnotationsModelValidatorProvider will always run required field validation, even if you’re not using the DataAnnotations attributes!

Here is an example that uses FluentValidation to validate an object where a null value is being bound to a non-nullable value type:

[Validator(typeof(FooValidator))]
public class Foo {
	public int Id { get; set; }
}
 
public class FooValidator : AbstractValidator<Foo> {
	public FooValidator() {
		RuleFor(x => x.Id).NotEmpty();
	}
}
 
[Test]
public void AddsOneError() {
	var foo = new Foo();
 
	ModelValidatorProviders.Providers.Add(
		new FluentValidationModelValidatorProvider(new AttributedValidatorFactory())
	);
 
	var meta = ModelMetadataProviders.Current.GetMetadataForProperty(() => null, typeof(Foo), "Id");
	var validators = ModelValidatorProviders.Providers.GetValidators(meta, new ControllerContext());
 
	var results = validators.SelectMany(x => x.Validate(foo)).ToList();
 
	Assert.AreEqual(1, results.Count()); //fails - 2 instead of 1
}

This test fails because there are two error messages rather than one:

The Id field is required.
'Id' should not be empty.

…the first of these errors comes from the DataAnnotationsModelValidatorProvider even though I have NOT decorated the Id property with a [Required] attribute.

Why does this happen? The answer is in DataAnnotationsModelValidatorProvider’s GetValidators method:

 if (metadata.IsRequired && !attributes.Any(a => a is RequiredAttribute)) {
       attributes = attributes.Concat(new[] { new RequiredAttribute() });
 }

This checks to see if the property is a non-nullable type and it does not have a RequiredAttribute, then it assumes that the property should have a RequiredAttribute anyway!
You can work around this by removing the DataAnnotationsModelValidatorProvider:

ModelValidatorProviders.Providers.Clear();
ModelValidatorProviders.Providers.Add(
	new FluentValidationModelValidatorProvider(new AttributedValidatorFactory())
);

…and the test now passes.

Unfortunately, this is far from ideal. This means you cannot use the DataAnnotations attributes to validate one model and a custom provider for a different model. You have to choose one or the other.

One way to work around this problem is to use a composite validator provider that wraps the underlying providers:

public class CompositeValidatorProvider : ModelValidatorProvider {
	public static void Bootstrap(ModelValidatorProviderCollection providerCollection, params ModelValidatorProvider[] customProviders) {
		var validators = customProviders.ToList();
		validators.AddRange(providerCollection);
		providerCollection.Clear();
		providerCollection.Add(new CompositeValidatorProvider(validators));
	}
 
	readonly IEnumerable<ModelValidatorProvider> innerInnerProviders;
 
	protected CompositeValidatorProvider(IEnumerable<ModelValidatorProvider> innerProviders) {
		this.innerInnerProviders = innerProviders;
	}
 
	public override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context) {
		foreach(var provider in innerInnerProviders) {
			var validators = provider.GetValidators(metadata, context).ToList();
			if(validators.Count > 0) {
				return validators;	
			}
		}
 
		return Enumerable.Empty<ModelValidator>();
	}
}

This custom provider can be used to wrap the built-in providers (including the DataAnnotations provider) as well as your own custom providers. In its GetValidators method, it iterates over each of the inner providers and asks each one to create a collection of validators. It only returns validators from the first provider that returns a non-empty collection. This means that if your custom provider can validate the object then the DataAnnotations provider will not be executed.

Now, the following test passes:

[Test]
public void AddsOneError() {
	var foo = new Foo();
 
    	var fluentProvider = new FluentValidationModelValidatorProvider(new AttributedValidatorFactory());
 
	CompositeValidatorProvider.Bootstrap(ModelValidatorProviders.Providers, fluentProvider);
 
	var meta = ModelMetadataProviders.Current.GetMetadataForProperty(() => null, typeof(Foo), "Id");
	var validators = ModelValidatorProviders.Providers.GetValidators(meta, new ControllerContext());
 
	var results = validators.SelectMany(x => x.Validate(foo)).ToList();
 
	Assert.AreEqual(1, results.Count());
}

This raises the question: if you have to resort to doing this, what is the point in allowing multiple validation providers to be registered in the first place?

I am really hoping that the MVC team will fix this fairly significant problem before RTM, but as MVC2 is already at the RC stage I think this will be unlikely.

Controllerless Actions with ASP.NET MVC

There’s recently been some discussion online about the concept of using ‘controllerless’ actions with the MVC pattern and I wanted to see how easy this would be to implement on top of ASP.NET MVC.

What is a Controllerless Action?

In a typical ASP.MVC project, a controller maps to a class and and action maps to a method on that class, eg:

public class CustomerController : Controller {
 
   private CustomerRepository customerRepository;
 
   public CustomerRepository(CustomerRepository customerRepository) {
      this.customerRepository = customerRepository;
   }
 
   public ActionResult Index() {
      return View();
   }
 
   public ActionResult Edit(int id) {
      var customer = customerRepository.FindById(id);
      return View(customer);
   }
}

In this example visiting the URL /Customer/Index would invoke the Index method on the CustomerController, while /Customer/Edit/5 would invoke the Edit method (with the id coming in as a parameter).

The idea behind a controllerless aciton is that each action is a separate class, so our Index action above would look like this:

namespace MyApp.Controllers.Home {
   public class Index {
      public ActionResult Execute() {
          return new ViewResult();
      }
   }
}

What are the benefits of controllerless actions?

In a small/simple project there probably isn’t much benefit. However, in a large application you’ll often find that controllers can become quite large and complex. One of the biggest problems is that different actions in the same controller class require different dependencies. For example, check out this constructor from the OrderController in SutekiShop:

public OrderController(
   IRepository<Order> orderRepository, 
   IRepository<Country> countryRepository, 
   IRepository<CardType> cardTypeRepository, 
   IEncryptionService encryptionService, 
   IPostageService postageService, 
   IUserService userService, 
   IOrderSearchService searchService, 
   IRepository<OrderStatus> statusRepository)
{
   ...
}

Not all of the actions in the OrderController make use of all of these dependencies. For example, the OrderSearchService is only used by the Index action. In this situation it would make sense to split the controller up into a separate class for each action. This way, each action has less baggage to carry around – it only takes dependencies on those things it actually needs. As a side effect, this helps with testability as you can test each action without having to provide stubs for the dependencies that the action doesn’t use.

ASP.NET MVC Implementation

Jeffrey Palermo has already posted an excellent example of using controllerless actions with ASP.NET MVC. In his example, you have to inherit from a class called ActionController and then create a method called Execute to handle the request. Because ActionController inherits from the existing System.Web.Mvc.Controller this allows you to make use of all the existing features in ASP.NET MVC.

However, I wanted to try something slightly different. My aim here is:

  • To allow action classes to be POCO (ie, not inherit from a base class)
  • To allow method invocation semantics to be configurable by using IoC container
  • To allow action filters to be configured externally (rather than using attributes)
  • To re-use as much of the ASP.NET MVC framework infrastructure as possible

I managed to succeed with most of these points, but there are some fairly major problems with this approach (see below). To start with, let’s explore the end result:

Example Application

In this example I’ll be using the Autofac IoC container for driving the application. Code for this is example is linked to from the bottom of the post.

The first thing we need to do is configure our IoC container and register our controller factory (we also have to make our MvcApplication class implement Autofac’s IContainerProviderAccessor and set up the container disposal HTTP Module – see the sample code for the implementation):

protected void Application_Start() {
   RegisterRoutes(RouteTable.Routes);
   InitialiseContainer();
 
  //...more configuration
}
 
private void InitialiseContainer() {
   var builder = new ContainerBuilder();
   builder.RegisterModule(new ControllerlessActionsModule());
   provider = new ContainerProvider(builder.Build());
 
   ServiceLocator.SetLocatorProvider(() => provider.RequestContainer.Resolve<IServiceLocator>());
}

Note we register a ControllerlessActionsModule with our container builder. Autofac’s modules allow you to group registrations together:

public class ControllerlessActionsModule : Module {
   INamingConventions	namingConventions = new DefaultNamingConventions();
 
   protected override void Load(ContainerBuilder builder) {
      builder.Register(c => new AutofacServiceLocator(c)).As<IServiceLocator>().ContainerScoped();
      builder.Register(namingConventions).ExternallyOwned();
      builder.Register(c => new DefaultActionMethodSelector()).As<IActionMethodSelector>();
 
      var actionTypes = new ControllerActionLocator(namingConventions)
         .FindActionsFromAssemblyContaining<Index>()
         .Where(x => x.Namespace.StartsWith("Web.Controllers"));
 
         foreach(var action in actionTypes) {
            builder.Register(action.Type).FactoryScoped().Named(action.Name);
         }
     }
}

Here we set up our registrations with the container. Note that we are providing an implementation of INamingConventions. This is used to construct keys for the action registrations. The DefaultNamingConventions class assumes that action classes will live in a Namespace of [Application].Controllers.[Controller name]. So an “Index” action class in the “Home” namespace would be registered as “home.index.action”. We also register the DefaultActionMethodSelector (more on this below) and then use the ControllerActionLocator to find all the action classes in our assembly.

Back in our Global.asax, we also need to register the ControllerlessControllerFactory in Application_Start:

 ControllerBuilder.Current.SetControllerFactory(new ControllerlessControllerFactory(() => provider.RequestContainer.Resolve<IServiceLocator>()));

The ControllerlessControllerFactory asks the container to resolve our action class and then returns it for execution. Unfortunately, this is where things start to become difficult. The first problem is that the MVC Framework expects all controllers to implement the IController interface (which contains 1 method – Execute). This is a problem because we want our action classes to be POCO and have some other class responsible for their execution. To make matters worse, most of the framework expects controllers to inherit from ControllerBase (which raises the question why bother having the IController interface if you’re going to require the use of a base class?)

We can work around this problem by using a ControllerAdaptor which inherits from System.Web.Mvc.Controller and wraps our action class. The ControllerlessControllerFactory’s CreateController method looks like this:

public IController CreateController(RequestContext requestContext, string controllerName) {
   string actionName = requestContext.RouteData.GetRequiredString("action");
   string key = NamingConventions.BuildKeyFromControllerAndAction(controllerName, actionName);
 
   object actionInstance;
 
   try {
      actionInstance =  serviceLocator().GetInstance(typeof(object), key);
   }
   catch (Exception ex) {
      throw new HttpException(404, "Controller not found", ex);
   }
 
   if (actionInstance == null) {
      throw new HttpException(404, "Controller not found");
   }
 
   return new ControllerAdaptor(actionInstance, serviceLocator());
}

The ControllerAdaptor replaces the MVC framework’s default ControllerActionInvoker with a ControllerlessActionInvoker. The ControllerlessActionInvoker calls into the implementation of IActionMethodSelector registered with our container to find the method on our action class to execute. The default behaviour is first to look for a method matching the current HTTP verb (Get or Post) or if one of these methods cannot be found then it will look for a method called Execute.

With all this wiered up, our Action class can look like this:

 
namespace Web.Controllers.Home {
   public class Index {
 
      public object Get(int? id) {
         return new HomeViewModel { Id = id };
      }
 
      public object Post(string name) {
         return new ContentResult { Content = "Hello there, " + name };
      }
   }
}

The Get method will respond to HTTP GET requests to /Home/Index and the Post method will respond to POSTs. Note that while our Post method returns a type derived from ActionResult, the Get method does not. By default in the MVC framework, if you return an object from a controller action which does not derive ActionResult then it is converted to a string and rendered to the response stream. However, we can use an ActionFilter to apply a different convention so that if an object is returned that is *not* an ActionResult then a View will be rendered with that object as its ViewData.

Action Filter Configuration

For the most part the controllerless ActionFilter implementation re-uses the MVC Framework’s default implementation. The only difference is how we declare the filters. By default, the framework expects ActionFilters to be declared as Attributes that decorate our controller classes and action methods. I am not particularly fond of this approach as it is not suitable for use with dependency injection (although there are some workarounds – see here and here) so I wanted to externalise the filter configuration.

The ControllerlessActions sample contains a FilterCollection class that the ControllerlessActionInvoker will use to obtain filters for the current action. This can be configured in our autofac module:

   var filters = new FilterCollection();
   builder.Register(filters).ExternallyOwned();
   builder.RegisterTypesAssignableTo<IActionFilter>().FactoryScoped();
   builder.RegisterTypesAssignableTo<IAuthorizationFilter>().FactoryScoped();
 
   filters.Apply<DecorateModelWithViewResult>().Always();

First, we register a FilterCollection with the container and also lazily register all ActionFilters and AuthorizationFilters that are in the project. The final line says that for every action that is invoked, execute the DecorateModelWithViewResult filter. This filter looks to see if the result of an action is an object that derives from ActionResult. If not, it wraps the object in a ViewResult:

public class DecorateModelWithViewResult : IActionFilter {
   public void OnActionExecuting(ActionExecutingContext filterContext) {}
 
   public void OnActionExecuted(ActionExecutedContext filterContext) {
      var result = filterContext.Result as ModelResult;
      if(result != null) {
         filterContext.Controller.ViewData.Model = result.Model;
         filterContext.Result = new ViewResult();
      }
   }
}

We can also configure action filters to only apply to certain actions:

filters.Apply<AddMessageToViewData>().When(action => action.ActionInstance is Controllers.Home.Index);

…or alternatively…

filters.Apply<AddMessageToViewData>().ForTypesAssignableTo<Controllers.Home.Index>();

Limitations

Unfortunately, the MVC Framework is really designed to work with controller classes that inherit from ControllerBase. Although we can hack around this by using a ControllerAdaptor and a custom ActionInvoker the implementation is not very neat and actually ends up having to bypass some key optimizations in the framework. For example, the ControllerDescriptorCache and the ActionMethodDispatcher cache only work for the default ActionInvoker implementation, and they cannot be extended as they are marked as internal (ugh). This probably means that my solution will not perform optimally (although I haven’t run any benchmarks).

I also ended up having to copy-and-paste several methods from the MVC framework source into my sample application because they were marked as private/internal.

In the end, I’d tend to suggest that if you want to use controllerless actions with the ASP.NET MVC framework then you should consider using something like Jeffrey’s ActionController base class as the solution is much cleaner and simpler. Using POCO is probably a more sensible choice if you’re using a more open framework such as FubuMVC

Edit: Seb pointed out that one advantage of using POCO classes for your actions is that it makes it a lot easier to re-use them across different frameworks (eg OpenRasta).

Where’s the code?

All the code from this post is up on my svn repository at https://www.jeremyskinner.co.uk/svn/public/trunk/ControllerlessActions (username ‘guest’) on GitHub and can be downloaded here.

Using FluentValidation with ASP.NET MVC Opinionated Input Builders

I’ve been following Eric Hexter’s series on using opinionated input builders with ASP.NET MVC and wanted to see whether it would be possible to use his InputBuilder code together with FluentValidation.

In Eric’s example, he has a class called SampleModel whose properties are decorated by several attributes:

public class SampleModel
{
  public Guid Guid { get; set; }
 
  [Required]
   public string Name { get; set; }
 
  [Required]
  [Label("Number of Types")]
  [PartialView("RadioButtons")]
  public NumberOfTypeEnum EnumAsRadioButton { get; set; }
 
  public NumberOfTypeEnum Enum { get; set; }
 
  [Range(3, 15)]
  public int IntegerRangeValue { get; set; }
 
  [Example("mm/dd/yyyy hh:mm PM")]
  public DateTime TimeStamp { get; set; }
 
  [DataType(DataType.MultilineText)]
  public string Html { get; set; }
 
  public bool IsNeeded { get; set; }
}

These properties on this object are then rendered in the view by using the strongly-typed Input extension:

<%=Html.Input(c => c.Name)%>
<%=Html.Input(c => c.TimeStamp)%>
<%=Html.Input(c => c.Html)%>
...etc...

The attributes that decorate the properties drive the UI, so for example decorating the Html property with [DataType(DataType.MultilineText)] would cause a multi-line textbox to be rendered.

Rather than using attributes, my aim was to configure the InputBuilders by storing metadata alongside validation information in a Validator class.

Out of the box, FluentValidation supports several validator types. Some of these map nicely to the DataAnnotations attributes used by the SampleModel. For example, the [Required] attribute maps nicely to the NotNull and NotEmpty validators, and the [Range] attribute works nicely with the GreaterThan/LessThan validators:

public class SampleModelValidator : AbstractValidator<SampleModel> {
  public SampleModelValidator() {
    RuleFor(x => x.Name).NotEmpty();
 
    RuleFor(x => x.IntegerRangeValue)
      .GreaterThanOrEqualTo(3)
      .LessThanOrEqualTo(15);
  }
}

However, there are no equivalents for the metadata attributes such as [PartialView], [Example] or [DataType], but these can easily be built by constructing some ‘fake’ validators (these validators won’t actually perform any validation – they will simply hold metadata).

For example, to build an equivalent for the DataTypeAttribute, we can create a property validator like this:

public interface IDataTypeMetaData {
	DataType DataType { get; }
}
 
public class DataTypeValidator<T, TProperty> : IPropertyValidator<T, TProperty>, IDataTypeMetaData {
	private DataType datatype;
 
	public DataTypeValidator(DataType datatype) {
		this.datatype = datatype;
	}
 
	public PropertyValidatorResult Validate(PropertyValidatorContext<T, TProperty> context) {
		return PropertyValidatorResult.Success();
	}
 
	public DataType DataType {
		get { return datatype; }
	}
}

Note that we declare both a validator to hold the DataType information and also a non-generic interface (which we’ll use later to obtain the metadata). The Validate method is a no-op, always reporting success (as we don’t actually want to perform any validation).

Next, we can declare an extension method that allows this to be used from within our SampleModelValidator:

public static class ValidatorExtensions {
	public static IRuleBuilderOptions<T, TProperty> DataType<T, TProperty>(this IRuleBuilder<T, TProperty> ruleBuilder, DataType dataType) {
		return ruleBuilder.SetValidator(new DataTypeValidator<T, TProperty>(dataType));
	}
}

After using this approach to create equivalents for all the other metadata attributes, our SampleModelValidator now looks like this:

public class SampleModelValidator : AbstractValidator<SampleModel> {
	public SampleModelValidator() {
		RuleFor(x => x.Name).NotEmpty();
 
		RuleFor(x => x.EnumAsRadioButton)
			.NotNull()
			.RenderUsing("RadioButtons")
			.WithName("Number of Types");
 
		RuleFor(x => x.IntegerRangeValue)
			.GreaterThanOrEqualTo(3)
			.LessThanOrEqualTo(15);
 
		RuleFor(x => x.TimeStamp).Example("mm/dd/yyyy hh:mm PM");
 
		RuleFor(x => x.Html).DataType(DataType.MultilineText);
	}
}

The next stage is to create a custom ValidatorDescriptor. The default ValidatorDescriptor doesn’t do very much so we’ll need to inherit from it and create some additional methods to retrieve the information needed by the InputBuilder:

using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using FluentValidation;
using FluentValidation.Internal;
using FluentValidation.Validators;
 
public interface ICustomValidatorDescriptor {
	string GetExample(PropertyInfo prop);
	string GetLabel(PropertyInfo prop);
	string GetPartialName(PropertyInfo prop);
	bool GetIsRequired(PropertyInfo prop);
}
 
public class CustomValidatorDescriptor<T> : ValidatorDescriptor<T>, ICustomValidatorDescriptor {
	public CustomValidatorDescriptor(IEnumerable<IValidationRule<T>> ruleBuilders) : base(ruleBuilders) {
	}
 
 
	public string GetExample(PropertyInfo prop) {
		return Rules.OfType<ISimplePropertyRule<T>>()
		       	.Where(x => x.Member == prop)
		       	.Select(x => x.Validator)
		       	.OfType<IExampleMetaData>()
		       	.Select(x => x.Example).FirstOrDefault() ?? string.Empty;
	}
 
	public string GetLabel(PropertyInfo prop) {
		return Rules.OfType<IPropertyRule<T>>()
				.Where(x => x.Member == prop)
				.Select(x => x.PropertyDescription).FirstOrDefault();
	}
 
	public string GetPartialName(PropertyInfo prop) {
		return Rules.OfType<ISimplePropertyRule<T>>()
				.Where(x => x.Member == prop)
				.Select(x => x.Validator)
				.OfType<IRenderUsingMetaData>()
				.Select(x => x.ViewName).FirstOrDefault();
	}
 
	public bool GetIsRequired(PropertyInfo prop) {
		return Rules.OfType<ISimplePropertyRule<T>>()
			.Where(x => x.Member == prop)
			.Select(x => x.Validator)
			.Where(x => x is INotNullValidator || x is INotEmptyValidator)
			.Any();
	}
}

The ValidatorDescriptor accepts in its constructor a collection of IValidationRule objects that represent the rules configured in the SampleModelValidator. Using some Linq magic we can retrieve the metadata information that we stored inside the validation rules. We also have to override the CreateDescriptor method in our SampleModelValidator to return an instance of our custom ValidatorDescriptor, rather than the default:

public override IValidatorDescriptor<SampleModel> CreateDescriptor() {
	return new CustomValidatorDescriptor<SampleModel>(this);
}

The next stage is to override the InputBuilder’s default conventions so that it will use our SampleModelValidator to obtain its metadata. To do this, we create a FluentValidationConventions class that accepts a ValidatorFactory in its constructor and contains methods that delegate to our CustomValidatorDescriptor:

public class FluentValidationConventions {
	private IValidatorFactory validatorFactory;
 
	public FluentValidationConventions(IValidatorFactory factory) {
		this.validatorFactory = factory;
	}
 
	private ICustomValidatorDescriptor GetDescriptor(Type type) {
		var validator = validatorFactory.GetValidator(type);
		return (ICustomValidatorDescriptor) validator.CreateDescriptor();
	}
 
	public string ExampleConvention(PropertyInfo prop) {
		return GetDescriptor(prop.ReflectedType).GetExample(prop);
	}
 
	public string LabelConvention(PropertyInfo prop) {
		return GetDescriptor(prop.ReflectedType).GetLabel(prop) ?? DefaultConventions.LabelForProperty(prop);
	}
 
	public string PartialNameConvention(PropertyInfo prop) {
		return GetDescriptor(prop.ReflectedType).GetPartialName(prop) ?? DefaultConventions.PartialName(prop);
	}
 
	public bool RequiredConvention(PropertyInfo prop) {
		return GetDescriptor(prop.ReflectedType).GetIsRequired(prop);
	}
}

Note that I used a very simple implementation of ValidatorFactory for this example that wraps a Dictionary. A real ValidatorFactory would probably wrap an IoC container or a Service Locator:

public class SampleValidatorFactory : IValidatorFactory {
	static Dictionary<Type, IValidator> validators = new Dictionary<Type, IValidator>() {
		{ typeof(SampleModel), new SampleModelValidator() }
	};
 
	public IValidator<T> GetValidator<T>() {
		return (IValidator<T>) GetValidator(typeof (T));
	}
 
	public IValidator GetValidator(Type type) {
		IValidator validator;
		if (validators.TryGetValue(type, out validator)) {
			return validator;
		}
		return null;
	}
}

In our global.asax, we can then replace the InputBuilder’s default conventions with our custom conventions:

protected void Application_Start()
{
	RegisterRoutes(RouteTable.Routes);
	InputBuilder.InputBuilder.BootStrap();
	SetupFluentValidationConventions();
}
 
private void SetupFluentValidationConventions() {
	var conventions = new FluentValidationConventions(new SampleValidatorFactory());
 
	ModelPropertyFactory.ExampleForPropertyConvention = conventions.ExampleConvention;
	ModelPropertyFactory.LabelForPropertyConvention = conventions.LabelConvention;
	ModelPropertyFactory.PartialNameConvention = conventions.PartialNameConvention; 
	ModelPropertyFactory.PropertyIsRequiredConvention = conventions.RequiredConvention; 
}

…and that’s it. The InputBuilder will now get all its metadata from our Validator class rather than from attributes. If you want to play with the source code for this example it’s available in my svn repository at https://www.jeremyskinner.co.uk/svn/public/trunk/FluentValidationInputBuilders (username ‘guest’) on GitHub and can be downloaded from here.

Using ModelState with MvcContrib’s Fluent HTML Helpers

What is ModelState?

The ASP.NET MVC ModelState dictionary allows you to record validation errors which can then be displayed in your web page.

For example, imagine you add a textbox to a page using the MVC framework’s built-in HTML helpers, then this will render a standard text field:

Your name: <%= Html.TextBox("Name") %>

In your controller, if you add an error to the ModelState dictionary with the same name as the textbox, then the HTML helper will change the styling of the input field by adding a css class of “input-validation-error”.

public class HomeController : Controller {
   public ActionResult Index() {
       ModelState.AddModelError("Name", "Please enter a name");
       return View(new MyViewModel { Name = "" });
   }
}

Using the default ASP.NET MVC template, it will add a red border with a light pink background:

Textbox error

You can also display the actual validation errors by making use of the ValidationSummary helper:

<%= Html.ValidationSummary() %>
Enter your name: <%= Html.TextBox("Name") %>

Which will display something like this:

Validation Summary

ModelState with FluentHtml

By default, the Fluent HTML helpers in MvcContrib do not have support for ModelState. However, it is very easy to add support for this by writing a custom MemberBehaviour (I previously wrote about extending the HTML helpers with MemberBehaviors here)

Here is the implementation of the ModelStateMemberBehavior class:

public class ModelStateMemberBehavior : IMemberBehavior {
	private readonly ModelStateDictionary modelState;
 
	public ModelStateMemberBehavior(ModelStateDictionary modelState) {
		this.modelState = modelState;
	}
 
	public void Execute(IMemberElement element) {
		ModelState state;
		if (element.Builder.Attributes.ContainsKey("name")) {
			if (modelState.TryGetValue(element.Builder.Attributes["name"], out state)) {
				element.Builder.AddCssClass("input-validation-error");
			}
		}
	}
}

This class will check whether the name of the element being rendered is present in the specified ModelState dictionary. If so, it will add a css class of “input-validation-error” to the element being rendered.

Now we need to hook this into the HTML helpers. This can be done by implementing the IViewModelContainer interface on your base View Page:

public class MyBaseViewPage<T> : ViewPage<T>, IViewModelContainer<T> where T : class {
   private List<IMemberBehavior> memberBehaviors = new List<IMemberBehavior>();
 
   protected override void SetViewData(ViewDataDictionary viewData) {
      base.SetViewData(viewData);
      behaviors.Add(new ModelStateMemberBehavior(ViewData.ModelState));
   }
 
   public T ViewModel {
      get { return ViewData.Model; }
   }
 
   public IEnumerable<IMemberBehavior> MemberBehaviors {
	get { return memberBehaviors; }
   }
}

Now, so long as all your view pages inherit from MyBaseViewPage, any calls to the fluent HTML helpers will have support for ModelState:

Your name: <%= this.TextBox(model => model.Name) %>

Dependency Injection with ASP.NET MVC Action Filters

Action Filter attributes in ASP.NET MVC are a very nice way of encapsulating logic into small reusable components that can easily be reused across multiple controllers.

However, if you need your action filters to do anything complex, injecting services into action filters using an Inversion of Control container (such as Windsor or StructureMap) can be painful.

Typically, when using an IoC container it is necessary to register all your components with the container up-front and then use the container to create instances for you. When the container creates the object, it will also create any required dependencies and pass them to the constructor (or property setters).

However, as ActionFilters are defined as attributes, they cannot be instantiated by the container. One solution to this problem is to wrap the container with a static class and then make use of constructor chaining to create the illusion of automatic dependency resolution:

public class LoggingFilter : ActionFilterAttribute {
  private ILogger logger;
 
  public LoggingFilter() : this(IoC.Resolve<ILogger>()) {
  }
 
  public LoggingFilter(ILogger logger) {
    this.logger = logger;
  }
 
  public override void OnActionExecuting(ActionExecutingContext context) {
    logger.log("Entering action: " + context.RouteData.GetRequiredString("action"));
  }
}

In this example, the default constructor will call into a static ‘IoC’ class (which wraps the underlying container) to resolve an ILogger instance and then pass this to the second constructor. In a unit-testing scenario, you can make use of the second constructor directly in order to supply a mocked ILogger instance.

There are several things I don’t like about this code:

  1. The filter now has a coupling to the container
  2. If you trigger the instantiation of the attribute without first initialising the container then this can lead to problems (eg reflecting over a method’s attributes in a unit-testing scenario)
  3. It’s just plain ugly!

Thankfully, there is a better way. Several IoC containers (including Autofac and Unity) can inject services into objects using property setters without the target object needing to be registered with the container. I’ll be using Autofac for the sample code.

We can write a custom ControllerActionInvoker to make use of this feature by intercepting the action filters before they are invoked. The custom action invoker looks like this:

namespace MyApp {
  using System;
  using System.Collections.Generic;
  using System.Reflection;
  using System.Web.Mvc;
  using Autofac;
 
  public class MyActionInvoker : ControllerActionInvoker {
    private readonly IContainer container;
 
    public MyActionInvoker(IContainer container) {
      this.container = container;
    }
 
    protected override ActionExecutedContext InvokeActionMethodWithFilters(MethodInfo methodInfo, IDictionary<string, object> parameters, IList<IActionFilter> filters) {
      foreach (var filter in filters) {
        container.InjectProperties(filter);
      }
      return base.InvokeActionMethodWithFilters(methodInfo, parameters, filters);
    }
  }
}

The custom action invoker takes an instance of IContainer (the autofac container) in its constructor, which it can then use to inject services into the action filter attributes before they are invoked. This is done by overriding the InvokeActionMethodWithFilters method and calling container.InjectProperties for each object in the filters collection.

In order to get Autofac working with ASP.NET MVC, you need to register an HTTP module as well as set up the AutofacControllerFactory (instructions here.)

It is also necessary to register the custom action invoker with Autofac in your global.asax:

var builder = new ContainerBuilder();
builder.Register<MyActionInvoker>().As<IActionInvoker>().FactoryScoped();

As well as the ActionInvoker, you also need to register your controllers. Autofac contains a ‘module’ for doing this (the AutofacControllerModule), but we need to make a slight modification in order to use our custom action invoker. The modified module looks like this:

public class ControllerModule : Module {
  private readonly Assembly assembly;
  private readonly IControllerIdentificationStrategy controllerNamingStrategy = new DefaultControllerIdentificationStrategy();
 
  public ControllerModule(Assembly assembly) {
    this.assembly = assembly;
  }
 
  protected override void Load(ContainerBuilder builder) {
    var controllers = from type in assembly.GetExportedTypes()
                           where typeof(IController).IsAssignableFrom(type) 
			   where !type.IsAbstract
		           select type;
 
    foreach (var type in controllers) {
      builder.Register(type)
        .FactoryScoped()
        .As(controllerNamingStrategy.ServiceForControllerType(type))
        .As(type)
        .OnActivating(InjectInvoker);
    }
  }
 
  private void InjectInvoker(object sender, ActivatingEventArgs e) {
    ((Controller)e.Instance).ActionInvoker = e.Context.Resolve<IActionInvoker>();
  }
}

Now when a controller is instantiated, the ActionInvoker property will be set to an instance of our custom action invoker. The module should be registered with the container builder:

builder.RegisterModule(new ControllerModule(typeof(HomeController).Assembly));

So, assuming an ILogger instance is registered with the container, the sample LoggingFilter could be written like this:

public class LoggingFilter : ActionFilterAttribute {
   public ILogger Logger { get; set; }
 
  public override void OnActionExecuting(ActionExecutingContext context) {
    Logger.log("Entering action: " + context.RouteData.GetRequiredString("action"));
  }
}

Much better!

The same approach can also be used for other filter types, (such as AuthorizationFilters) by overriding the appropriate method.

Note that container.InjectProperties makes use of reflection, so there is a potetial performance issue here.

Edit (5 December 2008): Here is an extension method that adds the InjectProperties method to the Microkernel from Castle Windsor.

using System;
using System.Reflection;
using Castle.MicroKernel;
using Castle.MicroKernel.ComponentActivator;
 
public static class WindsorExtension {
	public static void InjectProperties(this IKernel kernel, object target) {
		var type = target.GetType();
		foreach(var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance)) {
			if(property.CanWrite &&  kernel.HasComponent(property.PropertyType)) {
				var value = kernel.Resolve(property.PropertyType);
				try {
					property.SetValue(target, value, null);
				}
				catch(Exception ex) {
					var message = string.Format("Error setting property {0} on type {1}, See inner exception for more information.", property.Name, type.FullName);
					throw new ComponentActivatorException(message, ex);
				}
			}
		}
	}
}