ASP. net mvc exploration path-do not want to write the same fitlerattribute on multiple actions)

Source: Internet
Author: User
(After writing this article, I downloaded ASP. net MVC 3 RC, and found that it has enhanced the controllability of the filter-not only for globalfiltercollection of global filter-so this article is mainly for ASP. net MVC 2.0 RTM, of course, most of them apply to 3.0)

Taking the filter authorizeattribute as an example, a controller has several actions, including logon actions (such as login ). There are two ways to achieve this:
1. Implement an iauthorizationfilter again and judge in it that if it is a login action, it will not be verified. Then, the filter is placed on the Controller definition as filterattribute. Or the Controller implements iauthorizationfilter.
2. Add authorize to all actions except login.
Although these two methods can achieve the goal, they always feel that they are not elegant enough.

If I want to inject HTML into all actions to the bottom of the page, this injection may be temporary. Do I have to modify the controller? (ASP. net mvc 3 can add filters to the globalfilters set)
If I want to dynamically control which roles can access an action, can I modify the controller?
If I want to control the access by which roles at this time, what users do I want to control when the demand changes? Do I have to modify the controller? Or add or modify a filter?

In ASP. net mvc 2, the above requirements seem to need to be re-compiled.

Here we will sort out our requirements:Can I not modify the controller when adding, deleting, and modifying filters? It would be best to make all controllers and action definitions clean.

Put the filter outside the Controller for management. Make sure that the filter is ready before the action or actionresult is executed.

Before solving the problem, let's briefly review what happened before and after the action was executed.

We know that in ASP. net mvc, every request is usually located in a specific controller action.
By default, the action Executor (controlleractioninvoker) controls the execution of the action (or does not execute). The invokeaction method is used in actual operations.

The invokeaction method first searches for the action (by the findaction method). If the action is found, it will retrieve the filters owned by the Controller to which the action belongs and the filters owned by the action, if the Controller implements some filter interfaces, it will also be retrieved (by the getfilters method ). Put all the filters found into a filterinfo variable (of course, the filters placed in the filterinfo variable are sorted and cleared repeatedly ),The filter stored in filterinfo is not completely defined on the attribute of action..

Then execute all the iauthorizationfilters found (by the invokeauthorizationfilters method ). In the invokeauthorizationfilters method, as long as the actionresult of an iauthorizationfilter is not null, it will be immediately returned to the call, and no other iauthorizationfilter will be executed. After invokeauthorizationfilters is executed, the invokeaction method checks the execution result. If the actionresult is not null, the result is executed. If other iactionfilters are used, the iactionresult is ignored. Otherwise, the invokeaction method continues.

Then obtain the parameter set to be passed to the action (to the getparametervalue method), and execute the invokeactionmethodwithfilters method. The method name is enough to explain what it is.

If everything is normal, execute the invokeactionresultwithfilters method based on the results returned by the invokeactionmethodwithfilters method.

If an exception occurs throughout the invokeauthorizationfilters execution until invokeactionresultwithfilters is executed, invokeexceptionfilters is executed to handle the exception based on the caught exception.

Code Public   Virtual   Bool Invokeaction (controllercontext, String Actionname ){
If (Controllercontext =   Null ){
Throw   New Argumentnullexception ( " Controllercontext " );
}
If (String. isnullorempty (actionname )){
Throw   New Argumentexception (mvcresources. common_nullorempty, " Actionname " );
}

controllerdescriptor = getcontrollerdescriptor (controllercontext );
actiondescriptor = findaction (controllercontext, controllerdescriptor, actionname);
If (actiondescriptor ! = null ) {
filterinfo = getfilters (controllercontext, actiondescriptor);

Try {
Authorizationcontext authcontext = Invokeauthorizationfilters (controllercontext, filterinfo. authorizationfilters, actiondescriptor );
If (Authcontext. Result ! =   Null ){
// The auth filter signaled that we shoshould let it short-circuit the request
Invokeactionresult (controllercontext, authcontext. Result );
}
Else {
If (Controllercontext. Controller. validaterequest ){
Validaterequest (controllercontext );
}

Idictionary < String , Object > Parameters = Getparametervalues (controllercontext, actiondescriptor );
Actionexecutedcontext postactioncontext = Invokeactionmethodwithfilters (controllercontext, filterinfo. actionfilters, actiondescriptor, parameters );
Invokeactionresultwithfilters (controllercontext, filterinfo. resultfilters, postactioncontext. Result );
}
}
Catch (Threadabortexception ){
// This type of exception occurs as a result of response. Redirect (), but we special-case so that
// The filters don't see this as an error.
Throw ;
}
Catch (Exception ex ){
// Something blew up, So execute the exception Filters
Predictioncontext = Invokeexceptionfilters (controllercontext, filterinfo. exceptionfilters, ex );
If ( ! Exceptioncontext. exceptionhandled ){
Throw ;
}
Invokeactionresult (controllercontext, exceptioncontext. Result );
}

Return True;
}

//Using Y controller that no method matched
Return False;
}

Note that invokeaction, getfilters, invokeauthorizationfilters, getparametervalue, invokeactionmethodwithfilters, parameters, and invokeexceptionfilters are all virtual methods, unless there are enough reasons to inherit iactioninvoker to override an action executor, otherwise, I think rewriting some methods is enough to meet our expansion needs.

Even the controlleractioninvoker class itself can be replaced in the ASP. net mvc infrastructure. How can it be replaced? You can override the createactioninvoker method when inheriting the Controller class to implement our own controller.

In addition, you can assign values to the actioninvoker attribute of a controller object. How can this problem be solved? Override defacontrocontrollerfactory to create the getcontrollerinstance method of the controller instance. Then set the new controllerfactor in applicaion_start:
Controllerbuilder. Current. setcontrollerfactory (New yourcontrollerfactory ());

Return to the topic. We store the correspondence between filters and actions or the correspondence between filters and controllers in a collection and cache them. "Inject" in the appropriate location.

From finding an action to executing invokeauthorizationfilters, you must prepare the iauthorizationfilter. From finding an action to executing the invokeactionmethodwithfilters, you must prepare the iactionfilter. From finding an action to executing the invokeactionresultwithfilters, iresultfilter must be prepared. Before invokeexceptionfilters is executed, the iexceptionfilter must be ready. Based on the above points, we seem to be able to prepare the necessary filter before executing the findaction method getfilters method, invokeauthorizationfilters method, invokeactionresultwithfilters method, and getfilters method. Of course, the most appropriate method is the getfilters method.

In the getfilters method, we can search the "filter and action corresponding table" based on the features of the current action (such as the method name, or the request method get or post; you can also search for the filter and controller tables based on the features of the current controller (both the type and the full class name are acceptable. Add the matched filter to the filterinfo variable.

If you are interested, go to oxite, which meets some of the requirements mentioned in this chapter.
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.