HttpContext. Current is not everywhere

Source: Internet
Author: User
Tags apm net thread

Developers familiar with ASP. NET know that ASP. NET has a very powerful object HttpContext. For convenience, ASP. NET also provides it with a static attribute HttpContext. Current to access it,
Today's blog is going to start with HttpContext. Current.

Ubiquitous HttpContext

Because ASP. NET provides the static attribute HttpContext. Current, It is very convenient to obtain the HttpContext object.
For this reason, we often see the code for directly accessing HttpContext. Current:

Public class Class1 {public Class1 () {string file = HttpContext. Current. Request. MapPath ("~ /App_Data/xxxxxx. xml "); string text = System. IO. file. readAllText (file );//.......... other operations} // or use HttpContext directly in some methods. current public void XXXXX () {string url = HttpContext. current. request. rawUrl; string username = HttpContext. current. session ["username"]. toString (); string value = (string) HttpContext. current. items ["key"];} // It is even designed as a static property public static string XXX {get {return (string) HttpContext. current. items ["XXX"] ;}}

Such code is often seen in class library projects, so it can be seen that it is flooded.

Are these codes correct?
Some people may say that the code I wrote is for ASP. NET programs and not for console programs, so there is no problem.

Is that true?

Where is HttpContext. Current stored?

Indeed, in an ASP. NET program,AlmostAt any time, we can access HttpContext. Current to get an HttpContext object,
However, have you ever wondered how it is implemented?

If you have never thought about this, let me tell you today. See the following code:

protected void Page_Load(object sender, EventArgs e){    HttpContext context1 = HttpContext.Current;    HttpContext context2 = System.Runtime.Remoting.Messaging.CallContext.HostContext as HttpContext;    bool isEqual = object.ReferenceEquals(context1, context2);    Response.Write(isEqual);}

Guess what it will show?

This is what I see. If you don't believe it, you can try it.

From this code, HttpContext is actually saved in the CallContext. HostContext attribute,
If you still have feelings for hostcontext, you can use reflector.exe to check it. I don't want to post code any more, because some types and methods are not public.

Let's take a look at how MSDN explains CallContext. HostContext:

Gets or sets the host context associated with the current thread.

This explanation is vague, but we can write down two keywords: [current thread] and [Association ].

Is it something associated with the current thread?
I understand it in this way.

In an ASP. NET program, why can I access HttpContext. Current everywhere?
Because ASP. NET assigns a thread to each request, this thread will execute our code to generate response results,
Even if our code is scattered in different places (class libraries), the thread will still execute them,
Therefore, we can access HttpContext. Current anywhere to obtain the HttpContext object related to the Current request,
After all, these codes are executed by the same thread. Therefore, the HttpContext reference is the requested object.

Therefore, it is appropriate to design HttpContext. Current to be associated with the Current thread.

HttpContext is not everywhere!

What does [current thread] mean? Why should I highlight this word?

A:
1. The current thread is related to the current request.
2. in ASP. NET, some threads are not always related to requests.

Does it feel a bit difficult? Isn't it easy to understand? Let's continue.

Although in ASP. NET programs, almost all threads should be running in response to requests,
However, some threads are not running in response to the request, for example:
1. Timer callback.
2. Cache removal notification.
3. Callback is completed asynchronously in APM mode.
4. Actively create a thread or submit the task to the thread pool for execution.

In the above cases, if the thread runs to HttpContext. Current, what do you think will be returned?
Is it still a reference of an HttpContext instance?
How is it, and which request is associated with it?

Obviously, in both cases, access HttpContext. Current will return null.
Because it is very likely that the task does not have any request at runtime.
People who know about Asynchronization should be able to easily understand 3rd cases (should be a conclusion)
4th cases do not need to be explained, because it is indeed not the current thread.

Now, let's look at the code at the beginning of this article:

Public Class1 () {string file = HttpContext. Current. Request. MapPath ("~ /App_Data/xxxxxx. xml "); string text = System. IO. File. ReadAllText (file); // ...... other operations}

Imagine: If Class1 was created during the timer callback or Cache removal notification, do you think it can still run normally?

Now you have an answer in your mind, right?

You may wonder: why can I access HttpContext. Current anywhere else to get an HttpContext reference?
A: That's because ASP. NET has set HttpContext to the CallContext. HostContext attribute mentioned above before calling your code.
HttpApplication has an internal method OnThreadEnter (). ASP. NET will call this method to switch HttpContext before calling external code,
For example, when the callback is executed every time before the event processor of the pipeline is executed or the synchronization context (AspNetSynchronizationContext.
After the CallContext. HostContext attribute of the thread is switched, our code can access the HttpContext reference.
Note: The reference of HttpContext is actually saved in the HttpApplication object.

Sometimes we will see the word ASP. NET thread. Today I am talking about my understanding of this word:
The current thread is a thread related to HttpContext. Because the thread is associated with HttpContext, It is processing requests sent to ASP. NET.
Note: This thread is still the thread of the thread pool.

How to obtain the absolute file path?

In the timer callback or Cache removal notification, sometimes the file needs to be accessed. However, for developers,
They do not know which directory the website will be deployed, so it is impossible to write an absolute path,
They only know the relative path relative to the root directory of the website. To locate the file path, they can only call HttpContext. Current. Request. MapPath or
HttpContext. Current. Server. MapPath to obtain the absolute path of the file.
If HttpContext. Current returns null, how can I access the file?

In fact, the method is not MapPath. We can access HttpRuntime. AppDomainAppPath to obtain the path of the website, and then splice the relative path of the file:

No: HttpContext. Current in the image shows null. Therefore, if you call MapPath again, you will definitely die!

I would like to advise you:Do not use MapPath whenever possible. HttpRuntime. AppDomainAppPath is a safer choice.

How to access HttpContext in asynchronous calls?

As mentioned above, when asynchronous callback is completed in APM mode, access to HttpContext. Current will return null. What should I do now?

There are two answers:
1. Add a field to the type to save the reference of HttpContext (before the Asynchronous Start ).
2. Assign HttpContext to the last parameter (object state) of the BeginXXX Method)

We recommend that you first select the second method, because it can prevent accidental use of data members during maintenance by others in the future.

Use HttpContext. Current securely

Sometimes we will write some common class libraries for ASP. NET or WindowsService programs to use, such as the tool Method for exception record.
For ASP. NET programs, we certainly hope to record URL, form value, Cookie, and other data in case of exceptions, so as to facilitate post-event analysis.
However, for programs such as Windows service, you have never thought about recording cookies?
So how to implement a general function?

The method is also simple, that is, to determine whether HttpContext. Current returns null, for example, the following sample code:

Public static void LogException (Exception ex) {StringBuilder sb = new StringBuilder (); sb. append ("exception occurrence time :"). appendLine (DateTime. now. toString (); sb. appendLine (ex. toString (); // if it is ASP.. NET program, you also need to record the URL, FORM, COOKIE and other data HttpContext context = HttpContext. current; if (context! = Null) {// can run here, it must be processing ASP.. appendLine ("Url:" + context. request. rawUrl); // you can do it yourself. } System. IO. File. AppendAllText ("log File path", sb. ToString ());}

It is a judgment that solves all the problems, so please forget the following unsafe statements:

HttpContext.Current.Request.RawUrl;HttpContext.Current.Server.MapPath("xxxxxx");

The following method is safe:

HttpContext context = HttpContext. Current; if (context! = Null) {// access the request-related content here .}

If you believe that reading this blog has some benefits, click 【Recommendation] Button.
If you want to discover my new blog more easily, click 【Follow Fish Li].
Because my enthusiasm for writing is inseparable from your support.

Thank you for reading this article. If you are interested in the content of my blog, please continue to follow up on my blog. I am Fish Li.

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.