为什么获取的System.Web.HttpContext.Current值为null,HttpContext对象为null时如何获取程序(站点)的根目录 contentEditable属性设置是否可编辑元素的内容 draggable属性设置元素是否可拖动。 请求一个action,将图片的二进制字节字符串在视图页面以图片形式输出
为什么获取的System.Web.HttpContext.Current值为null,HttpContext对象为null时如何获取程序(站点)的根目录
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.Current
7 {
8 public class Test
9 {
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.Current
9 {
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)
建议优先选择第二种方法,因为可以防止以后他人维护时数据成员被意外使用。

请求一个action,将图片的二进制字节字符串在视图页面以图片形式输出
有些时候需要将二进制图片字节在发送浏览器以图片形式显示:
下面是一些示例代码:
控制器:
1 /// <summary>
2 /// 将图片的二进制字节字符串在视图页面以图片形式输出
3 /// </summary>
4 public class HomeController : Controller
5 {
6
7 public ActionResult Test()
8 {
9 return View();
10 }
11
12 //方法一:
13 public FileResult TestFileResult_1()
14 {
15 byte[] mybyte;
16 using (WebClient client = new WebClient())
17 {
18 mybyte = client.DownloadData("http://img.baidu.com/video/img/video_logo_new.gif");
19 MemoryStream ms = new MemoryStream(mybyte);
20 //System.Drawing.Image img;
21 //img = System.Drawing.Image.FromStream(ms);
22 }
23 return File(mybyte, "image/gif");
24 }
25
26 //方法二:
27 public FileResult TestFileResult()
28 {
29 byte[] mybyte;
30 using (WebClient client = new WebClient())
31 {
32 mybyte = client.DownloadData("http://img.baidu.com/video/img/video_logo_new.gif");
33 MemoryStream ms = new MemoryStream(mybyte);
34 //System.Drawing.Image img;
35 //img = System.Drawing.Image.FromStream(ms);
36 }
37 return new FileContentResult(mybyte, "image/gif");
38 }
39
40 //方法三:
41 public ActionResult TestFileContentResult()
42 {
43 byte[] mybyte;
44 using (WebClient client = new WebClient())
45 {
46 mybyte = client.DownloadData("http://img.baidu.com/video/img/video_logo_new.gif");
47 MemoryStream ms = new MemoryStream(mybyte);
48 }
49 return new FileContentResult(mybyte, "image/gif");
50 }
51
52 //方法四:
53 public ActionResult TestFile()
54 {
55 byte[] mybyte;
56 using (WebClient client = new WebClient())
57 {
58 mybyte = client.DownloadData("http://img.baidu.com/video/img/video_logo_new.gif");
59 //MemoryStream ms = new MemoryStream(mybyte);
60 //System.Drawing.Image img;
61 // img = System.Drawing.Image.FromStream(ms);
62 }
63 return File(mybyte, "image/gif");
64 }
65
66
67
68
69 public ActionResult Index()
70 {
71 return View();
72 }
73 }
视图(view):
1 @{
2 ViewBag.Title = "Test";
3 Layout = "~/Views/Shared/_Layout.cshtml";
4 }
5
6 TestFile:<img src="@(Url.Action("TestFile", "Home"))"/>
7 <br/>
8 <br/>
9 TestFileContentResult:<img src="@(Url.Action("TestFileContentResult", "Home"))"/>
10
11 <br/>
12 <br/>
13 TestFileResult:<img src="@(Url.Action("TestFileResult", "Home"))"/>
14
15 <br/>
16 <br/>
17 TestFileResult:<img src="@(Url.Action("TestFileResult_1", "Home"))"/>
运行结果如下图所示:



浙公网安备 33010602011771号