博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
在ASP.NET Core中怎么使用HttpContext.Current (转载)
阅读量:6414 次
发布时间:2019-06-23

本文共 3175 字,大约阅读时间需要 10 分钟。

一、前言

  我们都知道,ASP.NET Core作为最新的框架,在MVC5和ASP.NET WebForm的基础上做了大量的重构。如果我们想使用以前版本中的HttpContext.Current的话,目前是不可用的,因为ASP.NET Core中是并没有这个API的。
  当然我们也可以通过在Controller中访问HttpContext,但是某些情况下,这样使用起来还是不如HttpContext.Current方便

 

二、IHttpContextAccessor

  利用ASP.NET Core的依赖注入容器系统,通过请求获取IHttpContextAccessor接口,我们拥有模拟使用HttpContext.Current这样API的可能性。但是因为IHttpContextAccessor接口默认不是由依赖注入进行实例管理的。我们先要将它注册到ServiceCollection中:

public void ConfigureServices(IServiceCollection services){    services.TryAddSingleton
(); // Other code...}

      来模拟一个HttpContext.Current吧:

namespace WebCore.Utils{    public static class HttpContext    {        public static IServiceCollection serviceCollection;        public static Microsoft.AspNetCore.Http.HttpContext Current        {            get            {                object factory = serviceCollection.BuildServiceProvider().GetService(typeof(IHttpContextAccessor));                Microsoft.AspNetCore.Http.HttpContext context = ((HttpContextAccessor)factory).HttpContext;                return context;            }        }    }}

       我们看到上面HttpContext类中的public static IServiceCollection serviceCollection是没有被赋值的,所以我们还要在Startup类中的ConfigureServices中为其赋值

public void ConfigureServices(IServiceCollection services){    services.TryAddSingleton
(); WebCore.Utils.HttpContext.serviceCollection = services; // Other code...}

       这样我们就可以像在以前ASP.NET中一样,在ASP.NET Core中也可以使用WebCore.Utils.HttpContext.Current了。

 

  其实说到HttpContext.Current就不得不提到多线程问题,在以前的ASP.NET版本中,如果遇到多线程环境很有可能HttpContext.Current为空的情况。说到这个问题以前就是有解决方案的,那就是CallContext;

  CallContext 是类似于方法调用的线程本地存储区的专用集合对象,并提供对每个逻辑执行线程都唯一的数据槽。数据槽不在其他逻辑线程上的调用上下文之间共享。当 CallContext 沿执行代码路径往返传播并且由该路径中的各个对象检查时,可将对象添加到其中。

  当使用ASP.NET的时候,虽然线城池里的线程是复用的,但是CallContext并不在一个线程的多次使用中共享。因为CallContext是针对逻辑线程的TLS,线程池中被复用的线程是操作系统中的内核对象而不是托管对象。就像数据库连接池中保存的是非托管资源而不是托管资源。因此,先后执行的两个托管线程可能在底层复用了一个物理线程(内核对象),但并不能共享同一组CallContext数据槽。就像先后new的两个SqlConnection对象可能在底层使用了同一个物理连接,但是托管对象的属性已经被重置。
  与此对照的是ThreadStaticAttribute,标记上这个特性的静态字段是往物理线程的TLS中保存数据(根据MSDN的描述猜的。具体没试过),因此如果两个托管线程对象内部使用的是同一个物理线程,则这个字段会复用(在两个线程通过这一字段访问同一个数据槽)。
  在.NET Core中,也有新的API选择,AsyncLocal<T>。

三、HttpContextAccessor

  我们来看看ASP.NET Core中的IHttpContextAccessor接口实现吧:

public class HttpContextAccessor : IHttpContextAccessor {#if NET451        private static readonly string LogicalDataKey = "__HttpContext_Current__" + AppDomain.CurrentDomain.Id;        public HttpContext HttpContext        {            get            {                var handle = CallContext.LogicalGetData(LogicalDataKey) as ObjectHandle;                return handle?.Unwrap() as HttpContext;            }            set            {                CallContext.LogicalSetData(LogicalDataKey, new ObjectHandle(value));            }        }#elif NETSTANDARD1_3        private AsyncLocal
_httpContextCurrent = new AsyncLocal
(); public HttpContext HttpContext { get { return _httpContextCurrent.Value; } set { _httpContextCurrent.Value = value; } }#endif}

       最后我只能说在ASP.NET Core中是万物皆DI啊,其实Core中的实现早就为我们想好了这些功能,只是改变了使用方式。

 

 

转载地址:http://oidra.baihongyu.com/

你可能感兴趣的文章
架构师入门ing
查看>>
[UOJ218]火车管理
查看>>
Android -- 自定义View(一)
查看>>
dp - HNU 13404 The Imp
查看>>
day29 类中的内置函数方法 __str__ __repr__ __call__ isinstance() issubclass()
查看>>
富文本编辑器 CKeditor 配置使用+上传图片
查看>>
Ignatius and the Princess I
查看>>
手写SqlHelper
查看>>
网易云音乐mp3外链、真实地址下载方法
查看>>
Bootstrap学习笔记(二)---常见工具和流程导航范例
查看>>
Linux下安装Python2.7
查看>>
eclipse快捷键(shift+ctrl+l能出来所有的快捷键)
查看>>
mysql
查看>>
一些比较神奇的思路
查看>>
[网络流24题-13]餐巾计划问题
查看>>
flex自定义preloader预加载进度条
查看>>
topcoder srm 420 div1
查看>>
topcoder srm 545 div1
查看>>
PowerShell收发UDP消息包
查看>>
ios 开发日记 13-剖析网易新闻标签栏视图切换(addChildViewController属性介绍)
查看>>