For more information about OutputCache, see OutputCacheProvider OutputCache. Let's review the content of OutputCache. The processing of OutputCache is to register the ResolveRequestCache and UpdateRequestCache methods in the OutputCacheModule class, one is used to obtain one for setting the cache. The cache content is divided into two parts: the Cache Policy CachedVary and the cache data CachedRawResponse. A page Cache Policy has only one CachedVary, but it can have multiple cache content CachedRawResponse. The obtaining and setting of cached content mainly depends on the GetSnapshot () UseSnapshot (HttpRawResponse rawResponse, bool sendBody) method of HttpResponse. In general, it is very important that we use storage space to minimize the number of cached content copies. Now let's take a look at how the cache key is created, key creation depends on the CreateOutputCachedItemKey method. The content of the CreateOutputCachedItemKey method is still complicated. Let's take a look at its implementation.
How to call the CreateOutputCachedItemKey method? The code for creating the cache policy key is as follows: this. createOutputCachedItemKey (context, null); Code for creating a cache key: this. the difference between CreateOutputCachedItemKey (context, cachedVary) is that the value of the parameter CachedVary is null, and the value of the parameter CachedVary is a real cachedVary instance. The code here is decompiled by reflector.exe. It feels a little different from the real code, but it is logically the same.
I still use an actual example to change the parsing edge description. Here I am using a demo created by asp.net mvc. Request url: http: // localhost: 7503/Home/index, the path should be: Home/index
First, we need to distinguish whether our request is Get or Post, and Post with a1 as the header; otherwise, a2 is started, followed by the current Path:Copy codeThe Code is as follows: if (verb = HttpVerb. POST)
{
Builder = new StringBuilder ("a1", path. Length + "a1". Length );
}
Else
{
Builder = new StringBuilder ("a2", path. Length + "a2". Length );
}
Builder. Append (CultureInfo. InvariantCulture. TextInfo. ToLower (path ));
At this time, our cache policy key is determined. The policy key here is a2/home/index.
If our cachedVary is not null, continue to execute:Copy codeThe Code is as follows: for (int I = 0; I <= 2; I ++)
{
Int num;
String [] array = null;
NameValueCollection serverVarsWithoutDemand = null;
Bool flag = false;
Switch (I)
{
Case 0:
Builder. Append ("H ");
Array = cachedVary. _ headers;
If (array! = Null)
{
ServerVarsWithoutDemand = request. GetServerVarsWithoutDemand ();
}
Break;
Case 1:
Builder. Append ("Q ");
Array = cachedVary. _ params;
If (request. HasQueryString & (array! = Null) | cachedVary. _ varyByAllParams ))
{
ServerVarsWithoutDemand = request. QueryString;
Flag = cachedVary. _ varyByAllParams;
}
Break;
Default:
Builder. Append ("F ");
If (verb = HttpVerb. POST)
{
Array = cachedVary. _ params;
If (request. HasForm & (array! = Null) | cachedVary. _ varyByAllParams ))
{
ServerVarsWithoutDemand = request. Form;
Flag = cachedVary. _ varyByAllParams;
}
}
Break;
}
If (flag & (serverVarsWithoutDemand. Count> 0 ))
{
Array = serverVarsWithoutDemand. AllKeys;
Num = array. Length-1;
While (num> = 0)
{
If (array [num]! = Null)
{
Array [num] = CultureInfo. InvariantCulture. TextInfo. ToLower (array [num]);
}
Num --;
}
Array. Sort (array, InvariantComparer. Default );
}
If (array! = Null)
{
Num = 0;
Int length = array. Length;
While (num <length)
{
String str = array [num];
If (serverVarsWithoutDemand = null)
{
VaryByCustomString = "+ n + ";
}
Else
{
VaryByCustomString = serverVarsWithoutDemand [str];
If (varyByCustomString = null)
{
VaryByCustomString = "+ n + ";
}
}
Builder. Append ("N ");
Builder. Append (str );
Builder. Append ("V ");
Builder. Append (varyByCustomString );
Num ++;
}
}
}
This Code adds HQF3 characters to the key value. This loop first processes server data,
Array = cachedVary. _ headers;
ServerVarsWithoutDemand = request. GetServerVarsWithoutDemand ();
The second is to process QueryString data:
Array = cachedVary. _ params;
ServerVarsWithoutDemand = request. QueryString;
Final process Form data
Array = cachedVary. _ params;
ServerVarsWithoutDemand = request. Form;
ServerVarsWithoutDemand is the data of the NameValueCollection type. Here, every key in serverVarsWithoutDemand is cyclically stored. The append string corresponding to each key is N + key + V + value, if the value is null, the new value is "+ n +". You can see the keys and differences in different requests. The serverVarsWithoutDemand value and
CachedVary. _ varyByAllParams. The creation of cachedVary is in the OnLeave method of OutputCacheModule:
Vary = new CachedVary (varyByContentEncodings, varyByHeaders, varyByParams, varyByAllParams, currentSettings. VaryByCustom );
The value of varyByAllParams is as follows:Copy codeThe Code is as follows: bool varyByAllParams = false;
If (varyByParams! = Null)
{
VaryByAllParams = (varyByParams. Length = 1) & (varyByParams [0] = "*");
}
It can be seen that varyByAllParams is basically false. Only when varyByParams has a tight element and is *, varyByAllParams is true. If varyByAllParams is false, the serverVarsWithoutDemand method is GetServerVarsWithoutDemand, it has nothing to do with QueryString and Form3. You may not be familiar with the GetServerVarsWithoutDemand () method. Let's take a look at its definition:Copy codeThe Code is as follows: internal NameValueCollection GetServerVarsWithoutDemand ()
{
Return this. GetServerVars ();
}
It doesn't matter if you don't know about this method. We have a ServerVariables (set for getting Web Server variables) attribute that is similar to it:Copy codeThe Code is as follows: public NameValueCollection ServerVariables
{
Get
{
If (HttpRuntime. HasAspNetHostingPermission (AspNetHostingPermissionLevel. Low ))
{
Return this. GetServerVars ();
}
Return this. GetServerVarsWithDemand ();
}
}
The GetServerVarsWithDemand method also calls the GetServerVars method. Now we have figured out the serverVarsWithoutDemand data.
Builder. Append ("C"); then Append the character C
Next, we will handle the configuration of cache _ varyByCustom.Copy codeThe Code is as follows: if (cachedVary. _ varyByCustom! = Null)
{
Builder. Append ("N ");
Builder. Append (cachedVary. _ varyByCustom );
Builder. Append ("V ");
Try
{
VaryByCustomString = context. ApplicationInstance. GetVaryByCustomString (context, cachedVary. _ varyByCustom );
If (varyByCustomString = null)
{
VaryByCustomString = "+ n + ";
}
}
Catch (Exception exception)
{
VaryByCustomString = "+ e + ";
HttpApplicationFactory. RaiseError (exception );
}
Builder. Append (varyByCustomString );
}
This method is easy to understand. If _ varyByCustom is not null, We will append the characters in the N + key + V + value format. The key is the _ varyByCustom string, and the value is the call context. applicationInstance. getVaryByCustomString (context, cachedVary. _ varyByCustom). If the value is null, it is set to "+ n +" builder. append ("D ");Copy codeThe Code is as follows: if (verb = HttpVerb. POST) & cachedVary. _ varyByAllParams) & (request. Form. Count = 0 ))
{
Int contentLength = request. ContentLength;
If (contentLength> 0x3a98) | (contentLength <0 ))
{
Return null;
}
If (contentLength> 0)
{
Byte [] asByteArray = (HttpInputStream) request. InputStream). GetAsByteArray ();
If (asByteArray = null)
{
Return null;
}
VaryByCustomString = Convert. ToBase64String (MachineKeySection. HashData (asByteArray, null, 0, asByteArray. Length ));
Builder. Append (varyByCustomString );
}
}
This code mainly appends a character D to the key, and then processes the Post request (non-form request. form. count = 0) converts the request content (bytes) into characters and appends them to the key. This is rarely the case in http. Typically, Post requests in HttpWebRequest are triggered.Copy codeThe Code is as follows: builder. Append ("E ");
String [] strArray2 = cachedVary. _ contentEncodings;
If (strArray2! = Null)
{
String httpHeaderContentEncoding = context. Response. GetHttpHeaderContentEncoding ();
If (httpHeaderContentEncoding! = Null)
{
For (int j = 0; j <strArray2.Length; j ++)
{
If (strArray2 [j] = httpHeaderContentEncoding)
{
Builder. Append (httpHeaderContentEncoding );
Break;
}
}
}
}
This code first appends a character E to the key, and then the optimal ContentEncoding. The value of ContentEncoding is context. Response. GetHttpHeaderContentEncoding () and the value of _ contentEncodings in the cache policy is appended.
So far, our CreateOutputCachedItemKey method has been finished. The key of the cache policy has nothing to say, and it is related to the Path attribute of the Http Request Method Get, Post, and Request. But the key-related objects of the cached data:
(1) It is related to our _ headers, that is, the VaryByHeader attribute in the configuration is related. If the value of VaryByHeader is different, the key is different.
(2) It is related to _ varyByAllParams. When it is true, it is actually related to request. queryString. If this request is Post, it is also related to request. form. _ varyByAllParams is set to false by default. If it is set to true, varyByAllParams = (varyByParams. length = 1) & (varyByParams [0] = "*")
(3) It is related to _ varyByCustom. It will append the value of the context. ApplicationInstance. GetVaryByCustomString (context, cachedVary. _ varyByCustom) method to the key,
(4) It is related to _ contentEncodings. If the value returned by context. Response. GetHttpHeaderContentEncoding () is _ contentEncodings, the return value is appended.
Note: If this Http processing is a Post and request. Form. Count = 0 & _ varyByAllParams is rue, the post data is related to the sea area.