First time here? You are looking at the most recent posts. You may also want to check out older archives or the tag cloud. Please leave a comment, ask a question and consider subscribing to the latest posts via RSS. Thank you for visiting! (hide this)

One of the main design principles ASP.NET MVC has been designed with is extensibility. Everything (or most of) in the processing pipeline is replaceable so, if you don’t like the conventions (or lack of them) that ASP.NET MVC uses, you can create your own services to support your conventions and inject them into the main pipeline.

In this post I’m going to show 13 extensibility points that every ASP.NET MVC developer should know, starting from the beginning of the pipeline and going forward till the rendering of the view.

1. RouteConstraint

Usually you could put some constrains on url parameters using regular expressions, but if your constrains depend on something that is not only about the single parameter, you can implement the IRouteConstrains’s method and put your validation logic in it.

One example of this is the validation of a date: imagine an url that has year, month and date on different url tokens, and you want to be able to validate that the three parts make a valid date.

2. RouteHandler

Not really specific to ASP.NET MVC, the RouteHandler is the component that decide what to do after the route has been selected. Obviously if you change the RouteHandler you end up handling the request without ASP.NET MVC, but this can be useful if you want to handle a route directly with some specific HttpHanlders or even with a classic WebForm.

3. ControllerFactory

The controller factory is the component that, based on the route, chooses which controller to instantiate and instantiate it. The default factory looks for anything that implements IController and whose name ends with Controller, and than create an instance of it through reflection, using the parameter-less constructor.

But if you want to use Dependency Injection you cannot use it, and you have to use a IoC aware controller factory: there are already controller factory for most of the IoC containers. You can find them in MvcContrib or having a look at the Ninject Controller Factory.

4. ActionInvoker

ActionInvoker is responsible for invoking the action based on it’s name. The default action invoker looks for the action based on the method name, the action name and possibly other selector attributes. Then it invokes the action method together with any filter defined  and finally it executes the action result.

If you read carefully you probably understood that most of the execution pipeline is inside the logic of the default ControllerActionInvoker class. So if you want to change any of these conventions, from the action method’s selection logic, to the way http parameters are mapped to action parameters, to the way filters are chosen and executed, you have to extend that class and override the method you want to change.

A good example of this, is the NinjectActionInvoker I developed to allow injection of dependencies inside filters.

5. ActionMethodSelectorAttribute

Actions, with the default action invoker, are selected based on their name, but you can finer tune the selection of actions implementing your own Method Selector. The framework already comes with the AcceptVerbs attribute that allows you to specify to which HTTP Verb an action has to respond to.

A possible scenario for a custom selector attribute is if you want to choose one action or another based on languages supported by the browser or based on the type of browser, for example whether it is a mobile browser or a desktop browser.

6. AuthorizationFilter

These kind of filters are executed before the action is executed, and their role is to make sure the request is “valid”.

There are already a few Authorization filters inside the framework, the most “famous” of which is the Authorize attribute that checks whether the current user is allowed to execute the action. Another is the the ValidateAntiForgeryToken that prevents CSRF attacks. If you want to implement your own authorization schema, the interface you have to implement is IAuthorizationFilter. An example could be the hour of the day.

7. ActionFilter

Action Filters are executed before and after an action is executed. One of the core filters is the OutputCache filter, but you can find many other usages for this filter. This is the most likely extension point you are going to use, as, IMHO, it’s critical to a good componentization of views: the controller only has to do its main stuff, and all the other data needed by the view must be retrieved from inside action filters.

8. ModelBinder

The default model binder maps HTTP parameters to action method parameters using their names: a http parameter named user.address.city will be mapped to the City property of the Address object that itself is a property of the method parameter named user. The DefaultModelBinder works also with arrays, and other list types.

But it can be pushed even further: for example you might use it to convert the id of the person directly to the Person object looking up on the database. This approach is explained better in the following post Timothy Khouri (aka SingingEels): Model Binders in ASP.NET MVC. The code is based on the preview 5, but the concept remains the same.

9. ControllerBase

All controllers inherit from the base class Controller. A good way to encapsulate logic or conventions inside your actions is to create you own layer supertype and have all your controllers to inherit from it.

10. ResultFilter

Like the ActionFiters, the ResultFilters are execute before and after the ActionResult is executed. Again, the OutputCache filter is an example of a ResultFilter. The usual example that is done to explain this filter is logging. If you want to log that a page has been returned to the user, you can write a custom RenderFilter that logs after the ActionResult has been executed.

11. ActionResult

ASP.NET MVC comes with many different kind of results to render views, to render JSON, plain text, files and to redirect to other actions. But if you need some different kind of result you can write your own ActionResult and implement the ExecuteResult method. For example, if you want to send a PDF file as result you could write your own ActionResult that use a PDF library to generate the PDF. Another possible scenario is the RSS feed: read more about how to write a RssResult in this post.

Look at implementing a custom action result when the only peculiarity is how the result is returned to the user.

12. ViewEngine

Probably you are not going to write your own view engine, but there are a few that you might consider using instead of the default WebForm view engine. The most interesting one, IMHO, is Spark.

But if you really want to write your own view engine, have a look at this post by Brad Wilson: Partial Rendering & View Engines in ASP.NET MVC

13. HtmlHelper

Views must be very dumb and thin, and they should only have html markup and calls to HtmlHelpers. There should be no code inside the views, so helpers come very handy for extracting the code from the view and putting it into something that is testable. As Rob Conery says: “If there's an IF, make a Helper”.

What is an HtmlHelper? Basically it’s just an extension method of the HtmlHelper class, but that’s the only requirement.

You can read more about how HtmlHelpers are a great way to encapsulate code for view on Rob’s post: Avoiding Tag Soup.

Which one should you use in your applications?

As you might have guess, not all the application you write need you to extend the framework in all the 13 extension points above. The ones the are most likely needed in every applications are ActionFilters and HtmlHelpers. Then you might probably want to use extensions someone else wrote, like an alternative ControllerFactory to use a IoC container or ViewEngine to get rid of the WebForm taste.

But, it’s important to experiment on these extension points so that you know which are your options and you are ready to exploit their power when needed. In the next weeks I’m going to write a few posts on how some of these extension points can be used.

And if you want to read that topics covered more in detail you might consider buying one of the many books that are coming out about ASP.NET MVC, like, “Beginning ASP.NET MVC” (which I happen to be the author) or “Professional ASP.NET MVC” (written by the team that wrote the framework itself) or “ASP.NET MVC in Action” (by Jeffrey Palermo and Ben Scheirman)

Did I miss some extension point you think it’s important to use? Did you use any of the extension points I listed above? I’d love to hear from you which scenario you addressed.

kick it on DotNetKicks.com

posted on Wednesday, April 8, 2009 3:55 PM

Comments on this entry:

# re: 13 ASP.NET MVC extensibility points you have to know

Left by Chris Pietschmann at 4/9/2009 12:02 AM

What about the AjaxHelper? When should we use that instead of the HtmlHelper?? I've started using AjaxHelper Extension Methods to add more Ajaxy type stuff to the page instead of just "static" type stuff added using the HtmlHelper. Do you have any additional thoughts on this?

# ActionFilters

Left by Andrea Balducci at 4/9/2009 7:49 AM

"the controller only has to do its main stuff, and all the other data needed by the view must be retrieved from inside action filters"... I guessed that the controller had to create the "whole" view model. Why should I fill part of the model in actionfilters? any example that could explain this approach?

# re: 13 ASP.NET MVC extensibility points you have to know

Left by Simone at 4/9/2009 10:13 AM

@Chris:
I think that the only difference is semantic:
make extensions of HtmlHelper if they are used to build html
make extensions to AjaxHelper if they write something that is going to be handled via Ajax
but I guess the line between the two is very thin...

# re: 13 ASP.NET MVC extensibility points you have to know

Left by Simone at 4/9/2009 10:28 AM

@Andrea:
IMO the controller doesn't have to create the "whole" view model, otherwise you end up having the controller doing to many things:
imagine the usual sample of a blog post page, like this one. You have the main post with it's comments, and these goes into the controller, but then you have the "most recent posts", the "archive list", the "tag cloud", the "links", the "recent comments" and so on. These last parts are displayed in other pages as well, like the homepage, the archive page, etc...
If the controller action had to build the whole thing, he'd have to know how to retrieve all that stuff and, furthermore, most of the code to retrieve all the sidebar would be replicated: if you "decorate" an action (or the whole controller class) with ActionFilterAttributes, one per each "part", you clearly separate the responsibilities.
ActionFilter declared as attributes is not the best solution, but at least it's something.
Hope I explained that better. If not, feel free to comment again :)

# re: 13 ASP.NET MVC extensibility points you have to know

Left by Andrea Balducci at 4/9/2009 10:39 AM

In this case i define a Composite Model (the view model) embedding submodels (models of others components). Each model has only 1 builder class so the logic is not duplicated and i can compose models inside the action (so the action is fully testable).
I use this approach because i can reuse the Model builder logic in different places allowing full, composite, partial and event Json rendering with no effort.
I'm wrong?

# re: 13 ASP.NET MVC extensibility points you have to know

Left by Simone at 4/9/2009 12:01 PM

Kind of the same approach...
in my vision, submodels are created inside the actionfilters, and then added to the composite model.
The only difference I see here is that in your solution, the composition is performed by the action, in mine the composition is performed outside of the action, in an external component that manages the part of the view.
This is a discussion I proposed for the UGIALT.NET@DNM event at the end of June.

# re: 13 ASP.NET MVC extensibility points you have to know

Left by Andrea Balducci at 4/9/2009 12:21 PM

in my vision the action should do all the work, maybe in a single transaction. How do you test that the action is working fine if the model is incomplete?

# re: 13 ASP.NET MVC extensibility points you have to know

Left by Simone at 4/9/2009 12:28 PM

That's a good point :)
But do you really have to?
I mean, if you test every single component in isolation, and than you verify that the action is configured with the correct "filters", doesn't this test the same thing?

Furthermore, what if you want to add a new "widget" to your views? You have to add it to all your actions, instead of just decorating the controller with an attribute.

# re: 13 ASP.NET MVC extensibility points you have to know

Left by Andrea Balducci at 4/9/2009 2:08 PM

I expect (by naming convention) that the work (filling the model and providing an actionresult) is done by an Action not by a Filter..

btw using Filters can be a shortcut :D

I expect all the data coming from a db (or a different storage) is filled in an atomic Action other data (logging, etc...) could be generated by the Filters.

Maybe is what you call "main stuff".

Testing: why should i test the filter, the action and that the action is decorated with the correct filters if i can just test the Action?

btw, the good news is that the framework allow us to choose our preferred strategy and we are off the hell of WebForms pipeline.

See u @ UGIALT.NET@DNM :D

# re: 13 ASP.NET MVC extensibility points you have to know

Left by Simone at 4/9/2009 2:16 PM

Well... ASP.NET MVC is a pretty unopinionated framework, and IMHO, is a good base library on the top of which, thanks to the many extensibility points, you can add your own conventions.

Probably my opinions are different than yours :) Anyway, I'm going to write more about this in future posts.

Will be fun to see how different people solved that same problem... hope the session about Presentation Model and Componentization is going to happen. If it doesn't we can always do spin-off talk at the lounge or in another room :)

# re: 13 ASP.NET MVC extensibility points you have to know

Left by Koistya `Navin at 6/1/2009 3:37 PM

Good points.

# re: 13 ASP.NET MVC extensibility points you have to know

Left by Thomas G Mayfield at 6/1/2009 6:20 PM

Please change the heading of "AuthorizationFilter" to "IAuthorizationFilter" or otherwise indicate what must be implemented. I had to dig a bit to find what you were talking about.

# re: 13 ASP.NET MVC extensibility points you have to know

Left by Simone at 6/2/2009 9:09 PM

@Thomas: good point. I updated the text.

Comments have been closed on this topic.