The asp.Net MCV framework is great in a lot of ways. But one of the things that really bugs me about it is that error handling and security are not applied to controllers by default. This means that you have to remember to apply them every time you create a new controller.

There are reasons for this, but insecure by default naturally begs for problems. So the other day I got tired of catching these problems in my current application and wrote the following simple unit tests to ensure that all my controllers are secure an handle errors.

This code uses NUnit but it could easily be ported to any other testing framework.

Likewise you will need to tweak the roles check to suit your needs.

Happy Coding!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using NUnit.Framework;
using MvCApplication1;
 
[TestFixture]
public class ControllerConfigurationTests : NUnitTestFixtureBase
{
    #region Test Data
 
    public IEnumerable<Type> AllControllers()
    {
        return typeof(MvcApplication).Assembly.GetTypes()
            .Where( t =>
                     !t.IsAbstract
                     && typeof(Controller).IsAssignableFrom(t));
    }
 
    public IEnumerable<Type> AllNonExemptControllers()
    {
        return AllControllers().Except(new []
                                           {
                                            typeof(HomeController),   
                                            typeof(NewAccountController),   
                                            typeof(LogonController),   
                                            });
    }
 
    #endregion
 
    #region Tests
 
    [Test, TestCaseSource("AllControllers")]
    public void All_controllers_must_declare_the_HandleError_attribute(
        Type controller)
    {
        var attributes = controller
            .GetCustomAttributes(typeof (HandleErrorAttribute), true);
 
        Assert.That(attributes.Length,  Is.EqualTo(1), 
            controller.Name + " does not declare the HandleError attribute.");
    }
 
    [Test, TestCaseSource("AllNonExemptControllers")]
    public void All_controllers_not_specifically_exempted_must_authorize_only_the_filer_role(
        Type controller)
    {
        var attributes = controller
            .GetCustomAttributes(typeof(AuthorizeAttribute), true);
 
        Assert.That(attributes.Length, Is.EqualTo(1), 
            controller.Name + " does not declare one and only one Authorize attribute.");
 
        Assert.That(((AuthorizeAttribute)attributes[0]).Roles, Is.EqualTo("user"), 
            controller.Name + " does not authorize the appropriate roles.");
    }
 
    #endregion
}