转大神文档:https://www.cnblogs.com/linJie1930906722/p/5708966.html

ASP.NET提供了静态属性System.Web.HttpContext.Current,因此获取HttpContext对象就非常方便了。也正是因为这个原因,所以我们经常能见到直接访问System.Web.HttpContext.Current的代码:

 1 using System;2 using System.Collections.Generic;3 using System.Linq;4 using System.Web;5 6 namespace Test_HttpContext.Current7 {8     public class Test9     {
10
11         public Test()
12         {
13             string file =System.Web.HttpContext.Current.Request.MapPath("~/App_Data/1.xml");
14
15             string text = System.IO.File.ReadAllText(file);
16
17             //..........其它的操作
18         }
19
20         // 或者在一些方法中直接使用HttpContext.Current
21         public void Test_1()
22         {
23             string url = System.Web.HttpContext.Current.Request.RawUrl;
24
25             string username = System.Web.HttpContext.Current.Session["username"].ToString();
26
27             string value = (string)System.Web.HttpContext.Current.Items["key"];
28         }
29
30         // 甚至还设计成静态属性
31         public static string Test_2
32         {
33             get
34             {
35                 return (string)System.Web.HttpContext.Current.Items["XXX"];
36             }
37         }
38
39         /// <summary>
40         /// 获取文件绝对路径
41         /// </summary>
42         /// <param name="fileName">文件名称</param>
43         /// <returns></returns>
44         public string Test_3(string fileName)
45         {
46             return System.Web.HttpContext.Current.Server.MapPath("~/Log" + fileName);
47         }
48
49     }
50 }

上面的这些代码这样写真的没有问题吗?
答案是否定的

请看下面的验证:

我们先来看看HttpContext到底存储在哪里:

 1 using System;2 using System.Collections.Generic;3 using System.Linq;4 using System.Web;5 using System.Web.UI;6 using System.Web.UI.WebControls;7 8 namespace Test_HttpContext.Current9 {
10     public partial class WebForm1 : System.Web.UI.Page
11     {
12         protected void Page_Load(object sender, EventArgs e)
13         {
14
15             HttpContext context1 = System.Web.HttpContext.Current;
16
17             HttpContext context2 = System.Runtime.Remoting.Messaging.CallContext.HostContext as HttpContext;  //当前(请求)线程上下文
18
19             bool isEqual = object.ReferenceEquals(context1, context2);
20
21             Response.Write("context1与context2是否相同的实例:" + isEqual);
22         }
23     }
24 }

上面的代码运行的结果是true:

从这段代码来看,HttpContext其实是保存在System.Runtime.Remoting.Messaging.CallContext.HostContext这个属性中, System.Runtime.Remoting.Messaging.CallContext.HostContext在MSDN的解释是 获取或设置与当前线程相关联的主机上下文

我们在一个ASP.NET程序中,为什么可以到处访问HttpContext.Current呢?
因为ASP.NET会为每个请求分配一个线程(也是当前线程),这个线程会执行我们的代码来生成响应结果, 即使我们的代码散落在不同的地方(类库),线程仍然会执行它们, 所以我们可以在任何地方访问System.Web.HttpContext.Current获取到与当前请求相关的HttpContext对象, 这些代码是由同一个线程来执行,所以得到的HttpContext引用也就是我们期待的那个与请求相关的对象。

当前线程是什么意思? 
我的理解是:
1. 当前线程是指与当前请求相关的线程。
2. 在ASP.NET程序中,有些线程并非总是与请求相关。

虽然在ASP.NET程序中,几乎所有的线程都应该是为响应请求而运行的,但是还有一些线程却不是为了响应请求而(产生)运行的,

例如:
1. 定时器的回调。
2. Cache的移除通知。
3. APM模式下异步完成回调。
4. 主动创建线程或者将任务交给线程池来执行。

5.异步任务Task

至于什么APM网上资料很多,这里我就不说明了

在这些情况下使用System.Web.HttpContext.Current获取HttpContext对象得到的结果都是null,因为处理他们的线程不是当前线程(为处理请求产生线程)

说的这里我们再回头看看本文开始写的(部分)代码:

1          /// <summary>
2         /// 获取文件绝对路径
3         /// </summary>
4         /// <param name="fileName">文件名称</param>
5         /// <returns></returns>
6         public string Test_3(string fileName)
7         {
8             return System.Web.HttpContext.Current.Server.MapPath("~/Log" + fileName);
9         }

如果这段代码在那5种情况下运行,都会抛空指针异常,因为System.Web.HttpContext.Current得到是null。

为什么会得到null呢?

因为运行这段代码线程不是处理当前请求的当前线程

为什么其他地方得到又不是null呢?

因为ASP.NET程序在调用您的代码前,已经将HttpContext对象设置到前面所说的System.Runtime.Remoting.Messaging.CallContext.HostContext属性中。

HttpApplication有个内部方法OnThreadEnter(),ASP.NET在调用外部代码前会调用这个方法来切换HttpContext, 例如:每当执行管线的事件处理器之前,或者同步上下文(AspNetSynchronizationContext)执行回调时。 切换线程的CallContext.HostContext属性之后,我们的代码就可以访问到HttpContext引用。 注意:HttpContext的引用其实是保存在HttpApplication对象中。

这种情况下该如何获取文件的绝对路径呢?

我们可以访问System.Web.HttpRuntime.AppDomainAppPath获取程序的根路径,然后再拼接文件的相对路径即可

上面的代码得到的HttpContext对象是null,再调用MapPath来获取站点根目录,就必死无疑了!

所以在此建议大家在获取程序(站点)的根目录时尽量使用System.Web.HttpRuntime.AppDomainAppPath进行获取站点的根目录

那么在异步调用调用时访问HttpContext对象呢?

前面我还提到在APM模式下的异步完成回调时,访问HttpContext.Current也会返回null,那么此时该怎么办呢?
1. 在类型中添加一个字段来保存HttpContext的引用(异步开始前)。
2. 将HttpContext赋值给BeginXXX方法的最后一个参数(object state)

建议优先选择第二种方法,因为可以防止以后他人维护时数据成员被意外使用。

转载于:https://www.cnblogs.com/janeaiai/p/8794066.html

HttpContext 来源(System.Web.HttpContext.Current值为null的问题)相关推荐

  1. System.Web.HttpContext.Current.Session为NULL解决方法

    http://www.cnblogs.com/tianguook/archive/2010/09/27/1836988.html 自定义 HTTP 处理程序,从IHttpHandler继承,在写Sys ...

  2. System.Web.HttpRequestValidationException——从客户端检测到危险的Request值

    这是比较常见的问题了,如果Web表单中有输入类似于Html标签之类的文本,在通过Request.QueryString或者Request.Form传递这些值的时候,就会触发这样的异常,出于脚本注入等安 ...

  3. 异步 HttpContext.Current 为空null 另一种解决方法

    异步 HttpContext.Current 为空null 另一种解决方法 参考文章: (1)异步 HttpContext.Current 为空null 另一种解决方法 (2)https://www. ...

  4. System.Web.Caching.Cache类 缓存 各种缓存依赖

    原文:System.Web.Caching.Cache类 缓存 各种缓存依赖 Cache类,是一个用于缓存常用信息的类.HttpRuntime.Cache以及HttpContext.Current.C ...

  5. System.Web.Caching

    缓存主要是为了提高数据的读取速度.因为服务器和应用客户端之间存在着流量的瓶颈,所以读取大容量数据时,使用缓存来直接为客户端服务,可以减少客户端与服务器端的数据交互,从而大大提高程序的性能. 本章从缓存 ...

  6. System.Web.Security

    System.Web.Security概述 System.Web.Security命名空间提供了asp.net 2.0中的一些安全措施,如登陆用户的身份验证.当前用户的角色管理等. 要了解System ...

  7. .net System.Web.Caching.Cache缓存类使用详解(转载)

    转自:http://www.cnblogs.com/virusswb/articles/1681561.html net System.Web.Caching.Cache缓存类使用详解 System. ...

  8. 返璞归真 asp.net mvc (2) - 路由(System.Web.Routing)

    [索引页] [×××] 返璞归真 asp.net mvc (2) - 路由(System.Web.Routing) 作者:webabcd 介绍 System.Web.Routing - 此命名空间提供 ...

  9. System.Web.Caching.Cache

            System.Web.Caching 命名空间提供用于缓存服务器上常用数据的类.这包括 Cache 类,该类是一个使您可以存储任意数据对象(如哈希表和数据集)的词典.它还为这些对象提供 ...

最新文章

  1. Python数据科学-技术详解与商业实践视频教程
  2. cocos lua 创建替换图片
  3. 学习笔记(一)(x264编码流程)
  4. linux常用命令:top 命令
  5. 1114D . Flood Fill
  6. 实现Android的消息通知栏
  7. 更名OpenShift容器平台,红帽实现战略性转变
  8. c语言system title,system() – C语言库函数
  9. Mysql 免安装版本
  10. 系统提示 api-ms-win-crt-runtime-l1-1-0.dll文件丢失,解决方法。。。
  11. java提取图片中的文字内容_java 提取图片中的文字,手写文字
  12. excel 日期选择器_Excel日期选择器工具
  13. 发现贝叶斯的乐高积木
  14. 设置网页头部图标icon
  15. PHP取整,四舍五入取整、向上取整、向下取整、小数截取
  16. Cisco(34)——BGP的十三条选路原则
  17. UVA - 10382- Watering Grass
  18. hdu5963 朋友(博弈找规律)
  19. 计算机模拟液体的飞溅,液滴自由下落与液面冲击过程的三维数值模拟.doc
  20. 微分方程组求解(Euler法、RK法)

热门文章

  1. mysql数据库定点任务_MySQL数据库Event定时执行任务详解
  2. C语言 十进制整数字符串转十六进制字符串
  3. 问题合集 ------- 用 Eclipse 平台进行 C/C++ 开发
  4. python批处理文件_Python文件夹批处理操作代码实例
  5. 台式电脑已连接但无法上网_电脑无法上网?五步帮你解决!
  6. 0x80070659系统策略禁止这个安装 vc_不安装DNS解析服务器下安装Vcenter6.7
  7. android opencv 识别文字_基于SpringBoot的车牌识别系统(附项目地址)
  8. ssh excel 导入 mysql_ssh poi解析excel并将数据存入数据库
  9. html文本打印lt;igt;字段,Web前端学习第九课,使用文本格式化标签
  10. java多线程传值覆盖_Java 多线程传值的四种方法