.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 时出错
Xamarin - 在 .Net 标准库中使用 httpClient
从 .net 标准库中读取 appsettings.json