.NET标准库中的HttpContext

44

我正在开发几个项目,其中之一是一个 ASP.NET 4.5 应用程序,另一个是 .Net Core API 1.1 项目。ASP.NET应用程序使用 HttpContext 类读取cookie和页面头。现在,我需要将这个功能移植到一个 .net standard 库中,以便两个项目都能使用。但是我在 .net standard SDK 中找不到 HttpContext。有什么建议吗?


1
可能是在ASP.NET Core中访问当前HttpContext的重复问题。 - user47589
你不应该混合使用.NET和.NET Core项目,因为它们不能在同一框架下运行。 - Camilo Terevinto
共享代码真的需要访问这些静态变量吗?你能提取出那个逻辑吗? - Aluan Haddad
7个回答

34
你的方法存在问题:.NET Standard 是最基本的.NET实现,只实现了平台和场景无关的基本功能。
HttpContext 在 .NET Framework 和 .NET Core 上都有(它们都实现了 .NET Standard),但由于是特定于 Web 的,因此在 .NET Standard 上不存在。

所以,你有三个选择:
  1. 针对 .NET Framework 并使用System.Web.HttpContext
  2. 针对 .NET Core 并使用Microsoft.AspNetCore.Http.HttpContext
  3. 将使用 HttpContext 的逻辑移出 .NET Standard 项目
请注意,这些类差异很大。.NET Core 版本是为 ASP.NET Core 创建的,与 ASP.NET 4.5 及更早版本完全不同。

13

我不同意这些答案,也不同意只在 Web 项目中使用 HttpContext 的无稽之谈。这实际上是紧密耦合的,因为您希望能够重用代码,因此 .net core 或 .net standard 中的类库应该能够使用 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;
            }
        }

    }
}

1
在调用“Current”属性时,我遇到了空引用异常。在哪里以及如何最好地初始化它? - AleX_
在调用Current之前,您需要调用Configure()来为其提供上下文。然而,问题在于HttpContext在不同的线程之间是不同的。因此,总的来说,这段代码似乎不太可能按预期工作。 - Manfred
1
非常棒的想法 @TomStickel - pim
像大家说的那样,Current为空。如何调用Configure来设置它? - prem
@prem 这个在2.x或者1.x版本中是可行的,因为我写这篇回答的时候是在那个版本。但是那已经是2.5年前的事情了,现在我不确定是否还适用。抱歉。 - Tom Stickel
显示剩余3条评论

4
如果你的目标是.NETStandard 2.0,你可以使用HttpContext。尽管它没有包含在.NET Standard库中,但Microsoft.AspNetCore.Http.Abstractions包(它针对.NET Standard 2.0)将使您能够使用HttpContext

9
因为这不是同一个HttpContext。(我没有给你点踩) - House of Dexter
3
这个HttpContext只有Equals和ReferenceEquals方法可用,没有访问运行时的属性。我缺少什么? - Justin

2
我需要将“读取cookie和页面标头”移动到一个.NET标准库中,该库可供项目使用…

不要这样做。

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


有许多原因你可能想要将代码分成特定的库以便分享 - 这个建议有点短视。 - Robert Perry
@RobertPerry - 除非我们正在编写一个中间件或某个依赖于ASP.NET的库,否则库不应该读取/操作HTTP请求/响应头。这应该属于应用程序层。OP在2017年提出的问题是关于在ASP.NET Core和ASP.NET Classic之间共享代码的。 - galdin

0
一种方法是让调用进程将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 返回的类型以决定要访问哪些属性名称。


-1

我同意上面的答案,如果可能的话,应该让netstandard库保持简单并且没有网络请求。有一个System.Net.Http nuget包,它针对.net standard。如果您正在更新4.6.x及以上的完整框架和.net core,并且不想要asp.net core的开销,则可以使用此功能。


-2

在调用旧类之前,您可以创建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);
}

调用您的旧类库方法


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接