在项目中使用异步(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. Python-Jenkins API使用 —— 在后端代码中操控Jenkins

    最近在工作中需要用到在后台代码中触发Jenkins任务的构建,于是想到Jenkins是否有一些已经封装好的API类库提供,用于处理跟Jenkins相关的操作.下面就简单介绍下我的发现. Linux C ...

  2. 【翻译】Awesome R资源大全中文版来了,全球最火的R工具包一网打尽,超过300+工具,还在等什么?

    0.前言 虽然很早就知道R被微软收购,也很早知道R在统计分析处理方面很强大,开始一直没有行动过...直到 直到12月初在微软技术大会,看到我软的工程师演示R的使用,我就震惊了,然后最近在网上到处了解和 ...

  3. FragmentTabHost的基本用法

    开通博客以来已经约莫1个月了.几次想提笔写写东西,但总是由于各种各样的原因并没有开始.现在,年假刚结束,项目也还没有开始,但最终促使我写这篇博客的是,看了一篇博友写的新年计划,说是要在新的一年中写50 ...

  4. 实现一个类 RequireJS 的模块加载器 (二)

    2017 新年好 ! 新年第一天对我来说真是悲伤 ,早上兴冲冲地爬起来背着书包跑去实验室,结果今天大家都休息 .回宿舍的时候发现书包湿了,原来盒子装的牛奶盖子松了,泼了一书包,电脑风扇口和USB口都进 ...

  5. Expression Blend创建自定义按钮

    在 Expression Blend 中,我们可以在美工板上绘制形状.路径和控件,然后修改其外观和行为,从而直观地设计应用程序.Button按钮也是Expression Blend最常用的控件之一,在 ...

  6. autocomplete的使用

    autocomplete使用分为本地调用方法和读取远程读取数据源的方法 (1)本地调用方法 <script src="Scripts/jquery-1.4.1.min.js" ...

  7. 微信小程序体验(1):携程酒店机票火车票

    在 12 月 28 日微信公开课上,张小龙对微信小程序的形态进行了阐释,小程序有四个特定:无需安装.触手可及.用完即走.无需卸载. 由于携程这种订酒店.火车票和机票等工具性质非常强的服务,非常符合张小 ...

  8. BPM Domino集成解决方案

    一.需求分析 Lotus Notes/Domino是IBM的协同办公平台,在国内有广泛的用户. 但由于推出年头较早.采用文档数据库等特点, 导致其流程集成能力弱.统计分析难.不支持移动办公等问题,很多 ...

  9. Apache Cordova开发Android应用程序——番外篇

    很多天之前就安装了visual studio community 2015,今天闲着么事想试一下Apache Cordova,用它来开发跨平台App.在这之前需要配置N多东西,这里找到了一篇MS官方文 ...

  10. git图像化界面GUI的使用

    GIT学习笔记 一.        基础内容 1.git是一个版本控制软件,与svn类似,特点是分布式管理,不需要中间总的服务器,可以增加很多分支. 2.windows下的git叫msysgit,下载 ...