在项目中使用异步(async await)的时候发现一个现象,HttpContext.Current为null,导致一系列的问题.

上网查了一些资料后找到了一个对象: System.Threading.SynchronizationContext (提供在各种同步模型中传播同步上下文的基本功能。), 跟踪代码后发现 SynchronizationContext.Current 返回的是一个叫 System.Web.LegacyAspNetSynchronizationContext 的内部类对象,这个对象中有个字段叫 _application,类型为 System.Web.HttpApplication. 有了 System.Web.HttpApplication 对象就好办多了,直接使用 Context 属性即可. (当然 SynchronizationContext.Current 不一定只可能返回 System.Web.LegacyAspNetSynchronizationContext ,具体没有研究了)

代码:

   class Test
{
void Test1()
{
SynchronizationContext context = SynchronizationContext.Current;
Delegate factory = null;
Type type = context.GetType();
if (!type.FullName.Equals("System.Web.LegacyAspNetSynchronizationContext"))
{
//目前只研究了这个
return;
}
//找到字段
ParameterExpression sourceExpression = Expression.Parameter(typeof(System.Threading.SynchronizationContext), "context");
//目前支持 System.Web.LegacyAspNetSynchronizationContext 内部类
//查找 private HttpApplication _application 字段
Expression sourceInstance = Expression.Convert(sourceExpression, type);
FieldInfo applicationFieldInfo = type.GetField("_application", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
Expression fieldExpression = Expression.Field(sourceInstance, applicationFieldInfo);
factory = Expression.Lambda<Func<System.Threading.SynchronizationContext, System.Web.HttpApplication>>(fieldExpression, sourceExpression).Compile(); //拿到了这个委托就好办了 System.Web.HttpApplication httpApplication = ((Func<System.Threading.SynchronizationContext, System.Web.HttpApplication>)factory)(context); //直接使用属性
System.Web.HttpContext httpContext = httpApplication.Context;
}
}

封装一下:

      /// <summary>
/// 在同步上下文中查找当前会话<see cref="System.Web.HttpContext" />对象
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public static HttpContext FindHttpContext(this SynchronizationContext context)
{
if (context == null)
{
return null;
}
var factory = GetFindApplicationDelegate(context);
if (factory == null)
{
return null;
}
return factory(context).Context;
}

接下来再为HttpContext对象添加一个System.Web命名空间的扩展方法:

        /// <summary>
/// 确定异步状态的上下文可用
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public static HttpContext Check(this HttpContext context)
{
if (context==null)
{
context = SynchronizationContext.Current.FindHttpContext();
}
return context;
}

为了性能考虑,把factory缓存起来即可.

完了之后,使用HttpContext对象就可以这么做:

HttpContext context=HttpContext.Current.Check();

//这时候context还为null的话,就是姿势不对了(包括 websocket ,没有在会话中使用等等)

以后就可以愉快的使用异步控制器啦!

解决Asp.net Mvc中使用异步的时候HttpContext.Current为null的方法的更多相关文章

  1. 解决asp.net mvc中*.resx资源文件访问报错

    个人笔记 问题重现 在asp.net mvc中,使用资源文件会出现一个问题,例如: 紧接着我进入视图界面,输入下面代码: <a href="javascript:void(0);&qu ...

  2. ASP.NET MVC中实现多个按钮提交的几种方法

    有时候会遇到这种情况:在一个表单上需要多个按钮来完成不同的功能,比如一个简单的审批功能. 如果是用webform那不需要讨论,但asp.net mvc中一个表单只能提交到一个Action处理,相对比较 ...

  3. 【MVC】ASP.NET MVC中实现多个按钮提交的几种方法

    有时候会遇到这种情况:在一个表单上需要多个按钮来完成不同的功能,比如一个简单的审批功能. 如果是用webform那不需要讨论,但asp.net mvc中一个表单只能提交到一个Action处理,相对比较 ...

  4. [转]ASP.NET MVC中实现多个按钮提交的几种方法

    本文转自:http://www.cnblogs.com/wuchang/archive/2010/01/29/1658916.html 有时候会遇到这种情况:在一个表单上需要多个按钮来完成不同的功能, ...

  5. ASP.NET MVC中实现多个button提交的几种方法

    有时候会遇到这样的情况:在一个表单上须要多个button来完毕不同的功能,比方一个简单的审批功能. 假设是用webform那不须要讨论,但asp.net mvc中一个表单仅仅能提交到一个Action处 ...

  6. ASP.NET MVC中在Action获取提交的表单数据方法总结 (4种方法,转载备忘)

    有Index视图如下: 视图代码如下: <%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Mas ...

  7. ASP.NET MVC中在Action获取提交的表单数据方法

    有Index视图如下: 视图代码如下: <%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Mas ...

  8. mvc中尽量避免使用HttpContext.Current.Request

    在Mvc开发中滥用HttpContext.Current.Request,可能会造成非IE浏览器重复加载页面的情况. 不管你信不,反正我在Mvc3.0中遇到过.

  9. 解决asp.net MVC中 当前上下文中不存在名称“model” 的问题

    在vs2013下打开同事上传的cshtml视图文件报错,出现当前上下文中不存在名称“model”,ViewBag,Url等等,在视图中也没有智能提示了:但是不影响编译运行,只是开发时候比较麻烦,但在同 ...

随机推荐

  1. 通过三次优化,我将gif加载优化了16.9%

    WeTest 导读 现在app越来越炫,动不动就搞点动画,复杂的动画用原生实现起来挺复杂,如是就搞起gif播放动画的形式,节省开发成本.   背 景 设计同学准备给一个png序列,开发读取png序列, ...

  2. 《你不知道的JavaScript》整理(四)——原型

    一.[[Prototype]] JavaScript中的对象有一个特殊的[[Prototype]]内置属性,其实就是对于其他对象的引用. var myObject = { a: 2 }; myObje ...

  3. 最好的.NET开源免费ZIP库DotNetZip(.NET组件介绍之三)

    在项目开发中,除了对数据的展示更多的就是对文件的相关操作,例如文件的创建和删除,以及文件的压缩和解压.文件压缩的好处有很多,主要就是在文件传输的方面,文件压缩的好处就不需要赘述,因为无论是开发者,还是 ...

  4. StrategyPattern (策略模式)

    /** * 策略模式 * @author TMAC-J * 根据环境的不同选择不同的策略,把策略用接口抽象出来 */ public class StrategyPattern { interface ...

  5. Android之数据存储的五种方法

    1.Android数据存储的五种方法 (1)SharedPreferences数据存储 详情介绍:http://www.cnblogs.com/zhangmiao14/p/6201900.html 优 ...

  6. Android local.properties 文件读取

    转载请标明出处:http://www.cnblogs.com/zhaoyanjun/p/6202369.html 本文出自[赵彦军的博客] 在Android Studio项目里面有个local.pro ...

  7. Atitit.研发团队的管理原则---立长不立贤与按资排辈原则

    Atitit.研发团队的管理原则---立长不立贤与按资排辈原则 1. 组织任命原则概述1 2. 历史的角度看,大部分组织使用的立长不立贤原则1 3. 论资排辈 立长不立贤原则1 3.1. 资格和辈分是 ...

  8. SSIS 包部署 Package Store 后,在 IS 中可以执行,AGENT 执行却报错

    可以执行 SSIS Package ,证明用 SSIS Package 的账户是可以执行成功的.SQL Server Agent 默认指定账号是 Network Service. 那么可以尝试一下将 ...

  9. linux常用命令(3)mkdir命令

    mkdir命令1 命令格式:mkdir [选项]目录名2 命令功能:通过 mkdir 命令可以实现在指定位置创建以 DirName(指定的文件名)命名的文件夹或目录.要创建文件夹或目录的用户必须对所创 ...

  10. .NET跨平台之旅:数据库连接字符串写法引发的问题

    最近在一个ASP.NET Core站点中遇到一个奇怪问题.当用dotnet run命令启动站点后,开始的一段时间请求执行速度超慢,有时要超过20秒,有时甚至超过1分钟,日志中会记录这样的错误: Sys ...