I thought the next stop on my MVC tour would be Filters and Model Binders. Since I am still grokking some of these bits – nothing detailed here, but wanted to share what I have found so far.
Filters allow us to perform actions against Controller Action methods (i.e. requests from users).
Types of Filters
There are four “types” of Filters:
- Authorization – Performed before the action method or any other filters run. Allows you to grant/deny access before any other code is executed. Example: AuthorizeAttribute).
- Action – Can be run before and after an action method. Ideal for doing any model data manipulation etc. Couldn’t find examples in the core framework but projects like MvcContrib has them.
- Result – Runs after the action method has completed, but before the response is returned to the view. Ideal spot for last-minute changes to the response. Example: OutputCache.
- Exception – Runs after everything else, allowing you to catch any/all exceptions that occur. Ideal for logging scenarios. Example: HandleErrorAttribute.
Creating a Custom Filter
Dead easy – simply inherit from FilterAttribute (NOT Attribute, I ran off and did this and it does not work!) Then implement the appropriate interface for the filter you want to create (IAuthorizationFilter, IActionFilter, IResultFilter or IExceptionFilter).
Since Action and Result filters are going to be the most common filters, we actually get a handy base class for these, ActionFilterAttribute (no, the naming is not great here).
Things to Note
- When creating authorisation filters – be sure to return HttpUnauthorizedResult if the user fails authorisation. This sets the appropriate HTTP Response code etc.
- OutputCache implementation is pretty wrecked since it relies on the Web Forms output caching. This can have weird side affects on other filters. May be fine for you, just saying: “dragons be here”. Great overview here by Steve Sanderson (@StevenSanderson).
Model Binders essentially map data sent to an action method to a POCO type. This “data” might be FORM values posted in a request, or variables passed in the route/URL.
What to Inherit/Implement
To be used as a Model Binder, a class need only implement the one method in the IModelBinder interface. However, it is strongly recommended that you actually inherit from DefaultModelBinder since there are some “quirks” that need to be accounted for.
Things to Note
- You don’t get a great deal of type and conversion support, so if you create you own ModelBinder, be sure to test thoroughly.
- Don’t forget to update your Global.asax
2: typeof(CustomType), new ModelBinderType());
- These look really powerful and a great way to remove duplicate code etc. from your controllers. Also some cool stuff done by others (such as binding ORMs).
Naturally, I have had a poke and a play. I threw together some code and published to GitHub.
Rough sample code includes:
- Basic authorisation filters.
- Simple “random quote” action filter.
- (Really) rough-round-the-edges model binder to bind full ARGB colour to a type (this is then consumed when rendering, setting an elements “opacity”).
As always, thoughts and comments welcome.