Series directory
Filter context parameters
The previous section mentioned four built-in MVC filters. All of them provide filtercontext parameters in the key methods without exception. Although they have different types, they all inherit from controllercontext.
One of the important attributes is:
Public actionresult result {Get; set ;}
ResultIs the only notificationMVC FrameworkThe medium of the Current Filter execution result, that is, the MVC Framework always judges when necessary.Filtercontext. ResultIf the result is not empty, it indicates that you can continue. OtherwiseResultWill be executed (because it is an actionresult), and the subsequent process will be skipped. In the following discussion, you will gradually understand.
Iactionfilter and iresultfilter
IactionfilterAndIresultfilterIndicates the action before the action is executed and the action after the action is executed, respectively. From the class diagram in the previous article, we can see that MVC has built-inActionfilterattributeBoth interfaces are implemented at the same time, but all implementations are virtual methods and there is no actualCode. Therefore, you can inheritActionfilterattributeIactionfilter and iresultfilter. In addition, actionfilterattribute inheritsFilterattributeThis attribute defines only oneOrderAttribute. In fact, when multiple identical filters are defined on the same action or controller, order can sort their execution order. If this parameter is not specified, the following example shows the default situation:
[Showmessage (Message = "A")] [showmessage (Message = "B")] public actionresult someaction () {response. write ("action is running"); Return content ("result is running ");}
Assuming that the preceding showmessage inherits from actionfilterattribute and implements all four methods, the following output is obtained (the showmessage implementation is omitted, but you can guess it ):
[Beforeaction B] [beforeaction A] action is running [afteraction a] [afteraction B]
[Beforeresult B] [beforeresult A] result is running [afterresult a] [afterresult B]
If order is added, the default order can be changed:
[Showmessage (Message = "A", order = 1)] [showmessage (Message = "B", order = 2)] public actionresult someaction () {response. write ("action is running"); Return content ("result is running ");}
Output:
[Beforeaction a] [beforeaction B] action is running [afteraction B] [afteraction A]
[Beforeresult a] [beforeresult B] result is running [afterresult B] [afterresult A]
In short, iactionfilter and iresultfilter are relatively easy to understand, but there is a special problem to note, if you are executingIactionfilterOrIresultfilterWhen the code is abnormal, what should I do? The iactionfilter is used to describe the image in the book:
This figure provides us with such information. An action is added with three layers of iactionfilter,When onactionexecuting on the third layer throws an exception, it is captured by onactionexecuted on the second layer.And continue to execute the onactionexecuted at the first layer. The actionmethod and onactionexecuted on the third layer are skipped.
Iresultfilter actually performs the same behavior as iactionfilter.
In addition, the response. Redirect () method will throwThreadabortexceptionException. MVC captures this special exception on its own, so that this exception does not actually affect us. We can pretend to have no idea about this. The following code and comments are fromInvokeactionmethodfilterThe screenshot in the method illustrates the "painstaking efforts" of the MVC framework ".
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. postcontext = new actionexecutedcontext (precontext, precontext. actiondescriptor, false/* canceled */, null/* exception */); filter. onactionexecuted (postcontext); throw ;}
This partSource codeI will write a very incisive article.ArticleBy now, the above logic will be easier to understand.
In fact,OutputcacheattributeIsIresultfilterBesides some attributes, it only overrides onresultexecuting. For details about how to use it, refer to page 341.
Iauthorizationfilter
IauthorizationfilterUsed for page-level user verification, Authorizeattribute implements the iauthorizationfilter. The following code is the core verification logic of authorizeattribute. You must notify the authorizeattribute to meet the three conditions before the authentication succeeds:
1. httpcontext. User. Identity. isauthenticated must be true.
2. the username must be consistent (note that stringcomparer. ordinalignorecase indicates case insensitive)
3. The roles must be consistent.
Protected virtual bool authorizecore (httpcontextbase httpcontext) {If (httpcontext = NULL) {Throw new argumentnullexception ("httpcontext");} iprincipal user = httpcontext. User; If (! User. Identity. isauthenticated) {return false;} If (_ userssplit. length> 0 &&! _ Userssplit. Contains (user. Identity. Name, stringcomparer. ordinalignorecase) {return false;} If (_ rolessplit. length> 0 &&! _ Rolessplit. Any (user. isinrole) {return false;} return true ;}
The above source code clearly illustrates the problem. In addition, to implement role verification, you must configureRolemanager, Usually can be usedSqlroleproviderAnd can be customized.
if you consider output caching and authorization filters, is there any tricky? We can see a piece of code in onauthorization:
If (authorizecore (filtercontext. httpcontext) {// ** important ** // since we're using Ming authorization at the action level, the authorization code runs // After the output caching module. in the worst case this cocould allow an authorized user // to cause the page to be cached, then an unauthorized user wocould later be served the // cached page. we work around this by telling proxies not to cache the sensitive page, // then we hook our custom authorization code into the caching mechanism so that we have // the final say on whether a page shocould be served from the cache. httpcachepolicybase cachepolicy = filtercontext. httpcontext. response. cache; cachepolicy. setproxymaxage (New timespan (0); cachepolicy. addvalidationcallback (cachevalidatehandler, null/* Data */);}
This code is nothing surprising. First, call authorizecore and then see the comment,We put the verification into the Action Section so that the verification code will be executed after the cache module. In the worst case, an authenticated user gets a sensitive page and the page is cached. Then, an unverified user gets a cached page without verification. We bypassed this issue and directly told the proxy not to cache sensitive pages, and injected our verification mechanism into the cache mechanism, so that we finally decided whether to return to the cache page.
This comment clearly illustrates the conflict between the authentication mechanism and the cache mechanism, and also provides a solution. Therefore, if you want to implement iauthorizationfilter by yourself, be sure to inherit authorizeattribute and only rewrite authorizecore. If you still do not understand the following callback functionCachevalidatehandlerThe final calledOncacheauthorizationThe implementation:
Protected virtual httpvalidationstatus oncacheauthorization (httpcontextbase httpcontext) {If (httpcontext = NULL) {Throw new condition ("httpcontext");} bool isauthorized = authorizecore (httpcontext); Return (isauthorized )? Httpvalidationstatus. Valid: httpvalidationstatus. ignorethisrequest ;}
The authorizecore is still called before the output cache, which avoids the problems mentioned in the preceding annotations.
If authorizeattribute authentication fails,Httpunauthorizedresult,Attached to filtercontext. Result. Httpunauthorizedresult also inherits from actionresult. The executeresult method is as follows:
Context. httpcontext. response. statuscode = 401;
A 401 error is returned, indicating that the verification is not performed. Then, the verification module performs the next step based on the Web. config configuration. Generally, a logon page is displayed. If you do not want this, you can override the authorizeattributeHandleunauthorizedrequestMethod. For example, if an Ajax request is rejected due to a verification error, you obviously do not want the page to jump. It can be processed as follows:
Protected override void handleunauthorizedrequest (authorizationcontext context) {If (context. httpcontext. request. isajaxrequest () {urlhelper = new urlhelper (context. requestcontext); context. result = new jsonresult {DATA = new {error = "notauthorized", logonurl = urlhelper. action ("Logon", "account")}, jsonrequestbehavior = jsonrequestbehavior. allowget};} elsebase. handleunauthorizedrequest (context );}
Iexceptionfilter
We can see from the pseudocode in the previous section that,IexceptionfilterDesigned to capture exceptions. However, you must note that only exceptions after the action starts to be executed can be captured in this way (including the filter execution period). Prior to this, for example, controller cannot be found, exceptions such as action cannot be captured using iexceptionfilter.
MVC has a built-inHandleerrorattributeIt is used to inject 500 errors after capturing exceptions (404 errors will not be handled ). Let's take a look at its internal processing of filtercontext. Result:
Filtercontext. Result = new viewresult {viewname = view, mastername = Master, viewdata = new viewdatadictionary
It is noted that the user-specified view and master will be returned, andHandleerrorinfoThe model is encapsulated into viewdata and returned, and the tempdata of the current controller is attached. Handleerrorinfo encapsulates the exception object, controller and action names. This information can be used on our error page. Filtercontext. result will be executed by the MVC Framework, so we can use a non-viewresult, such as redirecttorouteresult.
ControlleractioninvokerIt will be judged before executing filtercontext. result.Filtercontext. exceptionhandledWhether it is true or not. If it is not true, filtercontext. result will not be executed, and the damn yellow pages will still be thrown to ASP. NET. Handleerrorattriled checks exceptionhandled. If it is true, nothing is returned. Otherwise, set exceptionhandled to true. When we need to implement the iexceptionfilter by ourselves and there are multiple iexceptionfilters at the same time, we can use the exceptionhandled to notify you whether the iexceptionfilter exception executed later is handled. Note that iactionfilter can also handle exceptions. You can guessActionexecutedcontextAndResultexecutedcontextIt also has exceptionhandled, corresponding. If you set exceptionhandled to true in onactionexecuted and onresultexecuted,The MVC framework will not throw an exception again.Therefore, no iexceptionfilter can be executed.
Filter by Controller
The Controller inherits from the preceding four interfaces and allows its inheritance class to overwrite the implementation. Therefore, we can rewrite onactionexecuting and other methods to set filter for the controller, this filtering takes precedence over the filtering execution set in the attribute mode.
Public abstract class Controller: iactionfilter, iauthorizationfilter, iexceptionfilter, iresultfilter
Labor fruit, reproduced please indicate the source: http://www.cnblogs.com/P_Chou/archive/2010/12/07/details-asp-net-mvc-08.html