Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Detailed description of the filter for ASP.NET MVC

2025-03-31 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article mainly explains the "detailed introduction of the filter of ASP.NET MVC". The content of the explanation in the article is simple and clear, and it is easy to learn and understand. Please follow the editor's train of thought to study and learn "the detailed introduction of ASP.NET MVC filter".

Catalogue

1. Filter

II. FilterProvider

III. FilterAttribute and FilterAttributeFilterProvider

4. Controller and ControllerInstanceFilterProvider

5. GlobalFilterCollection

VI. Example demonstration: verifying the provision mechanism and execution sequence of Filter

1. Filter

Although the four types of filters provided by ASP.NET MVC have their own implemented interfaces, for the filter delivery system, all filters are represented by a Filter type with the following definition. The core of Filter is the Instance attribute, because it represents the object that actually implements the filtering function, which implements one or more interfaces based on the above four filter types.

Public class Filter {public const int DefaultOrder =-1; public Filter (object instance, FilterScope scope, int? Order); public object Instance {get; protected set;} public int Order {get; protected set;} public FilterScope Scope {get; protected set;}} public enum FilterScope {Action = 30, Controller = 20, First = 0, Global = 10, Last = 100}

Note: since System.Web.Mvc.Filter and types that implement IAuthorizationFilter, IActionFilter, IResultFilter and IExceptionFilter can be called "filters", in order not to cause confusion, we use English "Filter" and Chinese "filters" to represent them respectively without making it clear.

The Order and Scope properties of Filter ultimately determine the order in which the filter is executed. The lower the value of the Order attribute, the higher the priority of execution, and the default value for this attribute is-1 (corresponding to the constant DefaultOrder defined in Filter). If two Filter have the same value of the Order attribute, then the Scope attribute ultimately determines which execution takes precedence. The Scope attribute type of Filter is an enumeration of type FilterScope. This enumeration represents the scope of the application Filter; Action and Controller represent Action methods and Controller class levels; First and Last mean that they want to be executed as the first and last Filter; and Global represents a global Filter.

From the code snippet above, we can see that the five enumeration options for FilterScope are all set to a value that determines the order in which Filter is executed, and smaller enumeration values are given priority. From the definition of FilterScope, it can be concluded that for multiple Filter with the same Order attribute value, the Filter applied on Controller has higher execution priority than the Filter applied on Action method, and the execution priority of a global Filter is higher than that of Action-based Filter.

II. FilterProvider

The provision mechanism of Filter is similar to the previous provision mechanism based on ModelBinder and ModelValidator, which is provided through the corresponding Provider. The FilterProvider that provides the filter implements the interface IFilterProvider, as shown in the following code snippet, which defines the unique method GetFilters to get a collection of Filter objects based on the specified Controller context and the ActionDescriptor object used to describe the target Action.

Public interface IFilterProvider {IEnumerable GetFilters (ControllerContext controllerContext, ActionDescriptor actionDescriptor);}

We can register with the static type FilterProviders or get the FilterProvider used by the current application. As shown in the following code snippet, FilterProviders has a read-only property of type FilterProviderCollection, Providers, which represents a list of FilterProvider used across the entire Web application. FilterProviderCollection is a collection of element type IFilterProvider, and the GetFilters method is used for Filter objects provided by or all FilterProvider objects in the collection.

Public static class FilterProviders {public static FilterProviderCollection Providers {get;}} public class FilterProviderCollection: Collection {/ / other members public IEnumerable GetFilters (ControllerContext controllerContext, ActionDescriptor actionDescriptor);}

ASP.NET MVC provides three native FilterProvider, which are FilterAttributeFilterProvider, ControllerInstanceFilterProvider, and GlobalFilterCollection, which we will introduce separately.

III. FilterAttribute and FilterAttributeFilterProvider

We usually define filters as properties that are applied declaratively to Controller types or Action methods, while the abstract type FilterAttribute is the base class for all filters. As shown in the following code snippet, the FilterAttribute feature implements the IMvcFilter interface, which defines two read-only properties, Order and AllowMultiple, that control the order in which filters are executed and that multiple similar filters can be applied to the same target element (class or method) at the same time.

[AttributeUsage (AttributeTargets.Method | AttributeTargets.Class, Inherited=true, AllowMultiple=false)] public abstract class FilterAttribute: Attribute, IMvcFilter {protected FilterAttribute (); public bool AllowMultiple {get;} public int Order {get; set;}} public interface IMvcFilter {bool AllowMultiple {get;} int Order {get;}}

From the definition of AttributeUsageAttribute applied to FilterAttribute, we can see that this feature can be applied to types and methods, which means that filters can generally be applied to Controller types and Action methods. The read-only property AllowMultiple actually returns a property of the same name for AttributeUsageAttribute, which we can see from the above definition that the value of this property is False by default.

Both ControllerDescriptor and ActionDescriptor used to describe Controller and Action implement ICustomAttributeProvider interfaces, and we can directly use them to obtain all the features of the application on the corresponding Controller type or Action method, including FilterAttribute. In fact, these two description types provide a separate method, GetFilterAttributes, that is specifically used to get a list of FilterAttribute features. As shown in the following code snippet, the method has a Boolean parameter useCache that indicates whether the parsed FilterAttribute feature needs to be cached to mitigate the performance impact of frequent reflection operations.

Public abstract class ControllerDescriptor: ICustomAttributeProvider, IUniquelyIdentifiable {/ / other members public virtual IEnumerable GetFilterAttributes (bool useCache);} public abstract class ActionDescriptor: ICustomAttributeProvider, IUniquelyIdentifiable {/ / other members public virtual IEnumerable GetFilterAttributes (bool useCache);}

Filter for the FilterAttribute feature is provided through the FilterAttributeFilterProvider object. FilterAttributeFilterProvider directly calls the GetFilterAttributes method of the current ControllerDescriptor and ActionDescriptor to get all the FilterAttribute properties applied to the Controller type and the current Action method, and creates the corresponding Filter object. The parameter cacheAttributeInstances of the FilterAttributeFilterProvider constructor indicates whether caching for FilterAttribute is enabled, which is used as a parameter to call the GetFilterAttributes method. By default (a FilterAttributeFilterProvider created by calling a default no-parameter constructor), caching for FilterAttribute is used.

Public class FilterAttributeFilterProvider: IFilterProvider {public FilterAttributeFilterProvider (); public FilterAttributeFilterProvider (bool cacheAttributeInstances); protected virtual IEnumerable GetActionAttributes (ControllerContext controllerContext, ActionDescriptor actionDescriptor); protected virtual IEnumerable GetControllerAttributes (ControllerContext controllerContext, ActionDescriptor actionDescriptor); public virtual IEnumerable GetFilters (ControllerContext controllerContext, ActionDescriptor actionDescriptor);}

For the Filter obtained by calling GetFilters, the corresponding FilterAttribute attribute is taken as its Instance attribute. The Order attribute comes from the FilterAttribute property of the same name, while the Scope attribute depends on whether the FilterAttribute attribute is applied to the Controller type (the Scope attribute value is Controller) or the current Action method (the Scope attribute value is Action).

4. Controller and ControllerInstanceFilterProvider

When it comes to ASP.NET MVC filters, most of them only think of using the FilterAttribute feature. In fact, Controller itself (inherited from the abstract class Controller) is a filter. As the following code snippet shows, the abstract class Controller implements four interfaces, IActionFilter, IAuthorizationFilter, IExceptionFilter, and IResultFilter, that correspond to different filter types.

Public abstract class Controller: ControllerBase, IActionFilter, IAuthorizationFilter, IExceptionFilter, IResultFilter,... {/ / omitted member}

The FilterProvider type for a unique filter such as a Controller object is ControllerInstanceFilterProvider with the following definition. In the implemented GetFilters method, it gets the corresponding Controller object based on the specified Controller context and creates a Filter (the Controller object is the value of the Instance property of the Filter object). The Scope of this Filter is not Controller, but First, and the value of Order is-2147483648 (Int32.MinValue). There is no doubt that such a Filter must be the first to be executed.

Public class ControllerInstanceFilterProvider: IFilterProvider {public IEnumerable GetFilters (ControllerContext controllerContext, ActionDescriptor actionDescriptor);}

5. GlobalFilterCollection

Filters defined in the form of FilterAttribute need to be explicitly annotated to the target Controller type or Action method, and in some cases a global Filter is required. The so-called global filter does not need to explicitly match a Controller or Action, but is used by default in all Action implementations. The FilterProvider used to provide this global Filter corresponds to a GlobalFilterCollection with the following definition.

Public sealed class GlobalFilterCollection: IEnumerable, IEnumerable, IFilterProvider {public GlobalFilterCollection (); public void Add (object filter); public void Add (object filter, int order); private void AddInternal (object filter, int? Order); public void Clear (); public bool Contains (object filter); public IEnumerator GetEnumerator (); public void Remove (object filter); IEnumerator IEnumerable.GetEnumerator (); IEnumerable IFilterProvider.GetFilters (ControllerContext controllerContext, ActionDescriptor actionDescriptor); public int Count {get;}}

From the naming and the definition given above, you can see that GlobalFilterCollection is just a list of Filter, and the implemented GetFilters method returns itself. Through the methods provided by GlobalFilterCollection, we can add, delete and clear the global Filter. The parameter filter of the Add method used to add Filter is not a Filter object, but a concrete filter (the corresponding filter interface is implemented). The added Filter object is created from this filter object, and its Scope property is set to Global. We add the Order property of the Filter object by specifying the Order property of the Filter object in the Add method. If the specified Order is not displayed and the specified filter is a FilterAttribute property, then the Order of this property will be the Order; of the Filter object otherwise use-1 as the value of the Order property.

The registration and acquisition of the global Filter (or global FilterProvider) for the entire Web application can be achieved through the static type GlobalFilters. As the following code snippet shows, GlobalFilters has a static read-only property Filters that returns a GlobalFilterCollection object.

Public static class GlobalFilters {public static GlobalFilterCollection Filters {get;}}

So far, we have introduced the three FilterProvider provided by default by ASP.NET MVC, as well as the Filter provision mechanism adopted by each. When the static type used to register FilterProvider is loaded, these three types of objects are created by default as Providers attribute values that represent the global FilterProvider collection, as shown in the following code snippet. That is, by default, ASP.NET MVC uses these three FilterProvider to provide all Filter objects.

Public static class FilterProviders {static FilterProviders () {Providers = new FilterProviderCollection (); Providers.Add (GlobalFilters.Filters); Providers.Add (new FilterAttributeFilterProvider ()); Providers.Add (new ControllerInstanceFilterProvider ());} public static FilterProviderCollection Providers {get;private set;}}

VI. Example demonstration: verifying the provision mechanism and execution sequence of Filter

To give readers a deeper impression of the Filter provisioning mechanism described above, let's do a simple example demonstration. In an empty Web project created from Visual Studio's ASP.NET MVC project template, we define one of the following FilterAttribute. FilterBaseAttribute is an abstract type that implements the IActionFilter interface, and three concrete FilterAttribute (FooAttribute, BarAttribute, and BazAttribute) are its successors.

Public abstract class FilterBaseAttribute:FilterAttribute, IActionFilter {public void OnActionExecuted (ActionExecutedContext filterContext) {} public void OnActionExecuting (ActionExecutingContext filterContext) {}} public class FooAttribute: FilterBaseAttribute {} public class BarAttribute: FilterBaseAttribute {} public class BazAttribute: FilterBaseAttribute {}

We first register BazAttribute as a global filter in Global.asax in the following way. Note that the Application_Start method defined in the default created Global.asax calls the RegisterGlobalFilters method to register an ExceptionFilter of type HandleErrorAttribute, and we need to comment this line of code.

Public class MvcApplication: System.Web.HttpApplication {/ / other members protected void Application_Start () {/ / other operations / / RegisterGlobalFilters (GlobalFilters.Filters); GlobalFilters.Filters.Add (new BazAttribute ());}}

Finally, we create the following default HomeController, an empty Action method Data that applies the BarAttribute feature we defined, and the FooAttribute feature applied to the HomeController class. In the default Action method Index, we get all the Filter objects for the Action method Data through the global FilterProvider list represented by the static property Providers of FilterProviders, and present their basic information (type, Order, and Scope properties).

[Foo] public class HomeController: Controller {public void Index () {ReflectedControllerDescriptor controllerDescriptor = new ReflectedControllerDescriptor (typeof (HomeController)); ActionDescriptor actionDescriptor = controllerDescriptor.FindAction (ControllerContext, "Data"); foreach (var filter in FilterProviders.Providers.GetFilters (ControllerContext, actionDescriptor)) {Response.Write (string.Format ("{0}", filter.Instance)) Response.Write (string.Format ("{0}: {1}", "Order", filter.Order)); Response.Write (string.Format ("{0}: {1}", "Scope", filter.Scope));} [Bar] public void Data () {}}

After running our program, the result shown in figure 7-5 will be rendered in the browser. We can clearly see that not only the FilterAttribute applied to its own Action method will be applied to the target Action, but also the FilterAttribute applied to the Controller class, the globally registered Filter, and the Filter embodied in the Controller object itself will eventually be applied to all Action.

The figure above shows the Order and Scope properties of the four Filter applied to the Action method Data. We mentioned earlier that these two properties determine the order in which similar filters are executed, and we now use this program to prove this. To do this, we need to make the following changes to FilterBaseAttribute, where we present the method name of the type of FilterAttribute currently executed in OnActionExecuting.

Public abstract class FilterBaseAttribute:FilterAttribute, IActionFilter {public void OnActionExecuted (ActionExecutedContext filterContext) {} public void OnActionExecuting (ActionExecutingContext filterContext) {filterContext.HttpContext.Response.Write (string.Format ("{0} .OnActionExecuting ()", this.GetType ();}}

Then we rewrite HomeController's OnActionExecuting method in the same way, rendering the current method name of the type of HomeController itself.

[Foo] public class HomeController: Controller {/ / other members protected override void OnActionExecuting (ActionExecutingContext filterContext) {Response.Write ("HomeController.OnActionExecuting ()");} [Bar] public void Data () {}}

We run our program again and specify the correct address on the browser to access the Action method Data defined in HomeController, which will render the result shown in the following figure in the browser. The output reflects the order in which the four ActionFilter applied to the Action method Data are executed, which is consistent with the Order and Scope property values corresponding to Filter.

There is another problem worth exploring about the provision of Filter: when we define FilterAttribute, we can set the AllowMultiple property of AttributeUsageAttribute applied to this type to False so that it can only be applied once on the same target element. However, we can still apply them to Action methods and their Controller types, or even register them as global Filter, will these FilterAttribute be valid?

Let's use an example to verify this now. Now we delete all FilterAttribute, define the following ActionFilter of type FooAttribute, and set the AllowMultiple property of the AttributeUsageAttribute feature applied to it to False.

[AttributeUsage (AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)] public class FooAttribute: FilterAttribute, IActionFilter {public void OnActionExecuted (ActionExecutedContext filterContext) {} public void OnActionExecuting (ActionExecutingContext filterContext) {}}

Now let's apply this FooAttribute feature to both the HomeController type and the Action method Data, and then register a global Filter for the FooAttribute feature in Global.asax.

[Foo] public class HomeController: Controller {/ / other members [Foo] public void Data () {}} public class MvcApplication: System.Web.HttpApplication {/ / other members protected void Application_Start () {/ / other operations / / RegisterGlobalFilters (GlobalFilters.Filters); GlobalFilters.Filters.Add (new FooAttribute ());}}

Now let's run our program directly, and the open browser will show the results shown in figure 7-7. You can clearly see that although we registered FooAttribute in three places, because the AllowMultiple attribute of this feature is False, only one of the FooAttribute is valid in the end.

For FilterAttribute with the AllowMultiple attribute of False, if we register multiple with different Scope, which one will be valid in the end? As you can see from the figure above, the FooAttribute applied to the Action method (Scope is Action) is valid. In fact, the specific logic is this: all created Filter is sorted by Order+Scope (that is, the order in which Filter executes), and is ranked last. For our example, the three Filter provided have the same Order attribute value (- 1), all of which will eventually be sorted by Scope (Scope, Controller, and Action), with Filter with Scope as Action.

Thank you for your reading, the above is the content of "detailed introduction of ASP.NET MVC filter". After the study of this article, I believe you have a deeper understanding of the detailed introduction of ASP.NET MVC filter, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report