Using ASP.NET MVC Filters
utopian-io·@yissakhar·
0.000 HBDUsing ASP.NET MVC Filters
#### What Will I Learn? How to Use ASP.NET MVC Filters #### Requirements ASP.NET MVC framework #### Difficulty Intermediate #### Tutorial Contents - Filter Definition - 1: Custom Attributes - 2: Applying a Custom Attribute - 3: Sample Global Attribute - Action Metadata - IFilterProvider Interface - Custom Filter Providers - 4: Custom Filter Providers - 5: Registering the Custom Provider - Filter Scope/Ordering ## Using ASP.NET MVC Filters The ASP.NET MVC framework applied a popular technique of aspect-oriented programming, which incorporates the idea of using attributes to apply to a controller or action. These attributes are filters that can affect the runtime process. An action can run before or after an action or result, or even handle exceptions that occur. The ASP.NET MVC framework expanded on this framework to include global filters. Global filters run for each controller or action. Additionally, the new IFilterProvider interface provides full control over the filters that can be run for a controller or action. There are a lot of options available to developers that we're going to look at in this tutorial. ## Filter Definition Previously, filters had to be applied to the action method itself in traditional attribute form. This worked well for applying actions to attributes, and supported a wide array of customizations. For instance, the following custom attribute checks to see whether the user has the right permissions to access an action: #### 1: Custom Attributes ``` public class SecurityCheckAttribute : FilterAttribute, IAuthorizationFilter { public string Role { get; set; } public void OnAuthorization(AuthorizationContext filterContext) { if (!filterContext.RequestContext.HttpContext.User.IsInRole("Administrators")) throw new Exception("Error"); } } ``` These attributes can be easily applied to an action like the following: #### 2: Applying a Custom Attribute ``` Public class AdminController : Controller { [SecurityCheck(Role = "Administrator")] Public ActionResult Index() { .. } } ``` These attributes could be applied at both the action or controller level, depending on the scope needed. Attributes were a quick way to setup additional features for an action that attached to it in a loosely-coupled way, often reflecting Aspect-Oriented Programming (AOP) techniques. With MVC, another option for applying an attribute to a controller or action globally through the GlobalFilters collection. This component is a registry of filters applied globally to all of the controllers in the application. Global filters are an easy way to apply common logic to the entire application, and use the same syntax for its definition as illustrated in Listing 1. Global filter mappings must be registered in the global.asax file, as illustrated in Listing 3. #### 3: Sample Global Attribute ``` GlobalFilters.Filters.Add(new SecurityCheckAttribute()); ``` One interesting implication is how the attribute must be defined; previously, we could append additional metadata for an action method's implementation. In this scenario, since the attribute is global, it must be coded in such a way to be able to implement its logic across all the controller's actions. If more control is needed over this process, creating a custom filter provider might be a better option. ## Action Metadata Before we get into building a custom filter provider, I'd like to talk a little bit about the metadata that an action method gives you. When an action method executes, the framework builds an ActionDescriptor containing all of the metadata for that action method: the method definition, its action parameters, the controller instance, and more. Using this given metadata, the internal framework grabs the existing action filter attributes defined for that action method and executes the attributes/method. Now that we're talking building custom filter providers, it now becomes up to you to interpret the metadata, examine the attributes defined, check the global filters defined, and any other filter-related framework code, as we'll see it in the next section. ## IFilterProvider Interface The IFilterProvider interface provides the core functionality for finding reference to filters for the given action or controller. The interface provides a GetFilter method for returning the found filters. In built into the provider are three default implements: the GlobalFilters component, the FilterAttributeFilterProvider class (for finding FilterAttribute references), and the ControllerInstanceFilterProvider class (for finding references to filters for a controller). ## Custom Filter Providers The ASP.NET MVC team has done a great job of opening up the framework for customization by developers. The framework allows customization of controllers, view pages, and more, and continues with a custom way to inspect controllers and the executing action method for filter definitions. Previously, developers had to override the ControllerActionInvoker class, assign this new action invoker to each and every controller instance created from the factory, and override certain methods that controlled this process. It wasn't the easiest task. The IFilterProvider interface makes this task a lot easier. The provider completely controls the process of examining a controller or an action. Through this interface, it's possible to lookup filters from the database or text file. #### 4: Custom Filter Providers ``` public class CustomFilterProvider : IFilterProvider { public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor) { if (actionDescriptor.ActionName == "Admin") return new Filter[] { new Filter(new SecurityCheckAttribute { Role = "Administrator" }, FilterScope.Controller,100) }; else return new Filter[] { }; } } ``` The provider must be registered in the global assembly file by adding it to the FilterProviders component. #### 5: Registering the Custom Provider ``` FilterProviders.Providers.Add(new CustomFilterProvider()); ``` With our newly created filter provider in place, we're all set to use it to serve up our filter references. Whenever the provider finds an admin action name, it checks that the user is of the given role; if not, it throws an exception. Otherwise, when not an admin action, execution passes right through. ## Filter Scope/Ordering A filter provider has two attributes – scope and order, used to determine the order that a filter executes in. The default ordering for MVC filters is as follows: - First - Global - Controller - Action Method - Last However, the scope also affects this process because it determines the ordering. The scope is an integer value used to determine order, followed by the ordering. So a filter ordered last with a 100 scope runs before a filter ordered first with a 300 scope. #### Conclusion Filters provide an aspect-oriented programming approach to writing code. A couple of options exist for filters, using local filters or global filters. Global filters apply to all action methods across all controllers currently executing. However, these attributes must be applied to every controller or action. To completely control the filter process, the IFilterProvider interface serves up the attributes and can completely redesign the filter examination process. In-built to the framework are three implementations, but it's very easy to create your own. Each filter comes with an order and scope to determine the current execution order of each attribute. <br /><hr/><em>Posted on <a href="https://utopian.io/utopian-io/@yissakhar/using-asp-net-mvc-filters">Utopian.io - Rewarding Open Source Contributors</a></em><hr/>