.net 标准库中的 HttpContext

Posted

技术标签:

【中文标题】.net 标准库中的 HttpContext【英文标题】:HttpContext in .net standard library 【发布时间】:2018-05-01 15:30:22 【问题描述】:

我正在处理几个项目,其中一个是ASP.NET 4.5 应用程序,另一个是.Net Core API 1.1 项目。 asp.net 应用程序使用HttpContext 类来读取cookie 和页眉。现在,我需要将它移动到一个可供两个项目使用的 .net 标准库。我在 .net 标准 SDK 中找不到 HttpContext。有什么建议吗?

【问题讨论】:

Access the current HttpContext in ASP.NET Core的可能重复 你不应该混合使用 .NET 和 .NET Core 项目,它们不在同一个框架下运行。 共享代码真的需要访问这些静态数据吗?你能提取出那个逻辑吗? 【参考方案1】:

您的方法存在问题:.NET Standard 是可用的最简单的 .NET 实现,这意味着仅实现与平台和场景无关的基本功能。HttpContext 两者都存在.NET Framework 和 .NET Core(顺便说一下,它们都实现了 .NET Standard),但特定于 Web,它在 .NET Standard 上不存在。

所以,你有三个选择:

    以 .NET Framework 为目标并使用 System.Web.HttpContext 以 .NET Core 为目标并使用 Microsoft.AspNetCore.Http.HttpContext 将使用 HttpContext 的逻辑从 .NET Standard 项目中移出

但请注意,这些类差异很大。 .NET Core 版本是为 ASP.NET Core 创建的,它与 ASP.NET 4.5 及更早版本有很大不同。

【讨论】:

【参考方案2】:

我不同意这些答案以及关于在 Web 项目中仅包含 HttpContext 的废话。这实际上是紧密耦合的,因为您希望能够重用代码,因此 .net 核心或 .net 标准中的类库应该能够使用HttpContext

所以在 .NET Standard 中您要添加:

Microsoft.AspNetCore.Http.Abstractions

遗憾的是,新的 HttpContext 有很多不同之处 HttpContext.Current 丢失,因此缺少会话和请求等。

(是的,我了解了设计模式以及为什么要分离出来并使其更可测试)

这里有一个小技巧,你也可以使用它来获得Current

namespace System.Web

    public static class HttpContext
        
            private static Microsoft.AspNetCore.Http.IHttpContextAccessor m_httpContextAccessor;


    public static void Configure(Microsoft.AspNetCore.Http.IHttpContextAccessor httpContextAccessor)
        
            m_httpContextAccessor = httpContextAccessor;
        


        public static Microsoft.AspNetCore.Http.HttpContext Current
        
            get
            
                return m_httpContextAccessor.HttpContext;
            
        

    

【讨论】:

调用Current 属性时出现空引用异常。最佳实践在哪里以及如何启动? 这里也一样,虽然这看起来应该可以工作,但我在调用 Current 属性时也遇到空引用异常 您需要先调用Configure(),然后才能调用Current 为其提供上下文。但是,问题在于线程之间的 HttpContext 是不同的。因此,最重要的是,这段代码似乎不太可能按预期工作。 @Manfred - 除非它对我有用,否则我不会发布它。 非常非常巧妙的想法@TomStickel【参考方案3】:

如果您的目标是 .NETStandard 2.0,您可以使用HttpContext

虽然它不包含在 .NET Standard 库中,但 Microsoft.AspNetCore.Http.Abstractions 包(面向 .NET Standard 2.0)将使您能够使用 HttpContext

【讨论】:

因为这不是同一个HttpContext。 (我没有对你投反对票) 这个 HttpContext 只有 Equals 和 ReferenceEquals 方法可用,没有用于访问运行时的属性。我错过了什么?【参考方案4】:

我需要将这个 [读取 cookie 和页眉] 移动到可供项目使用的 .NET 标准库中...

不要这样做。

假设您正在对从 cookie 中读取的数据执行 X 操作。您可以将此操作 X 移到库中。 ASP.NET 项目的工作是处理请求管道。读取 cookie 属于那里。

【讨论】:

【参考方案5】:

我同意上面的答案,如果可能的话,您希望保持 netstandard 库简单且没有网​​络请求。有一个针对 .net 标准的 System.Net.Http nuget 包。如果您正在创建库并且不想要 asp.net 核心的开销,则可以在为完整框架和 .net 核心更新 4.6.x 时使用此功能。

【讨论】:

【参考方案6】:

一种方法是让调用进程将 Http.Current.Request 作为对象类型的参数传递到您的 Standard 类中的方法中。然后使用反射来访问属性。在您的 Standard 类中,类似:

public void ProcessRequest(object Request)

    Type oT = Request.GetType();
    string URL = oT.GetProperty("RawUrl").GetValue(Request).ToString();
    // do something

然后从您的调用应用程序:

oRR.ProcessRequest(HttpContext.Current.Request);

我从 .Net Framework 而非 .Net Core 对此进行了测试。如果 Core 中的上下文库具有不同的属性,您可能需要检查 GetType 返回的类型以确定要访问的属性名称。

【讨论】:

【参考方案7】:

我知道你想要 HttpContext 但可能对创建任何频道没有什么帮助。因此我给出了一个 ContextChannel 的例子。因为我对类似的http上下文感兴趣。

我只是创建 ContextChannel,然后我使用 OperationContext,因为如果我没有创建上下文范围 Context Channel 总是会为空。

在我的示例中,它的工作方式如下;

  ChannelFactory<T> factory = channelFactory;
        factory.Endpoint.EndpointBehaviors.Add(new ClientMessagePropertyBehavior());

        var proxy = (IClientChannel)factory.CreateChannel();

  using (var contextScope = new OperationContextScope((IContextChannel)proxy))
            
                Stopwatch sw = Stopwatch.StartNew();

                HttpRequestMessageProperty requestMessage = new HttpRequestMessageProperty();
                requestMessage.Headers["Authorization"] = accessToken;
                OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = requestMessage;

                TResult result = codeBlock((T)proxy);

                sw.Stop();

                _tools.logInfo(string.Format(@"* Service client performance : 0 = 1 ms", codeBlock.Method.ToString(), sw.ElapsedMilliseconds));

                success = true;
                return result;
            

【讨论】:

【参考方案8】:

您可以在调用旧类之前创建 HttpContext.Current:

using System.Web;
using System.Web.SessionState;

System.Web.HttpContext.Current = new System.Web.HttpContext(new System.Web.HttpRequest("", "http://localhost", ""), new System.Web.HttpResponse(new System.IO.StringWriter()));

System.Web.SessionState.SessionStateUtility.AddHttpSessionStateToContext(
  System.Web.HttpContext.Current,
  new HttpSessionStateContainer("",
    new SessionStateItemCollection(),
    new HttpStaticObjectsCollection(),
    20000,
    true,
    HttpCookieMode.UseCookies,
    SessionStateMode.InProc,
    false
  )
);

HttpContext.Session.SetString("your_session_var", "1");

foreach (string item in HttpContext.Session.Keys)

  System.Web.HttpContext.Current.Session[item] = HttpContext.Session.GetString(item);

**调用旧的类库方法

【讨论】:

以上是关于.net 标准库中的 HttpContext的主要内容,如果未能解决你的问题,请参考以下文章

从 .net 核心控制台应用程序引用 .net 标准 2.0 库中的 dll 时出错

C# 标准库中的 B-tree 类? [关闭]

Xamarin - 在 .Net 标准库中使用 httpClient

从 .net 标准库中读取 appsettings.json

Python标准库中的列表(list数组)操作汇总(大约25种操作),附示例代码

如何在标准类库中读取 .Net Core 配置?