I'd like to use a class extending Controller
as the default base type for controllers in my project, as opposed to using Controller
itself. So, I would be doing this:
public class FooController : MyBaseController
Is there a way I can enforce this, so that people cannot create controllers which extend Controller
directly?
You can always create a unit test that (via reflection) retrieves all classes that derive from Controller
and asserts that each class is also a subclass of MyBaseController
. It would be along the lines of
[TestMethod]
public class All_Controllers_Derive_From_MyBaseController()
{
// Act
var controllerTypes = AppDomain.CurrentDomain
.GetAssemblies()
.SelectMany(asm => asm.GetTypes())
.Where(t => t.IsSubclassOf(typeof(Controller))
.ToList();
// Verify
foreach (var type in controllerTypes)
{
// Make sure the type isn't the actual controller type
if (type is Controller)
continue;
Assert.IsTrue(type.IsSubclassOf(typeof(MyBaseController)),
string.Format("{0} is not a subclass of the MyBaseController class", type.FullName));
}
}
Now if someone creates a controller that doesn't use your base controller your unit tests will fail and tell you which ones are not correct.
Note that this code was written free-hand, so it might need some adjustment but that's the basic idea.
However I prefer the unit testing approach above here is another one by using a custom controller factory.
public class MyControllerFactory<T> : DefaultControllerFactory where T : Controller
{
#region Overrides of DefaultControllerFactory
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (!typeof(T).IsAssignableFrom(controllerType))
{
throw new NotSupportedException();
}
return base.GetControllerInstance(requestContext, controllerType);
}
#endregion
}
You can set it up in the application start method of your Global.asax like this:
ControllerBuilder.Current.SetControllerFactory(new MyControllerFactory<MyBaseController>());
This of course causes a runtime exception when not deriving from MyBaseController
which may not be suitable in your current scenario.
You have two choices and both involve writing some code.
choice #1 You can create a filter and try and catch the error at runtime. You better have good a good user acceptance test process in place to touch all of the pages.
Choice #2 involves writing a task for MSBuild that checks that each controller class is derived from your specified class. Just load the application assembly (or assemblies) and go to town!
I prefer choice #2. It doesn't affect application runtime performance and gives you better coverage. You can run it at the end of a build.
http://msdn.microsoft.com/en-us/library/gg416513(VS.98).aspx
http://msdn.microsoft.com/en-us/library/t9883dzc.aspx
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With