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

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

【问题讨论】:

  • 你不应该混合使用 .NET 和 .NET Core 项目,它们不在同一个框架下运行。
  • 共享代码真的需要访问这些静态数据吗?你能提取出那个逻辑吗?

标签: c# .net asp.net-core .net-standard


【解决方案1】:

您的方法存在问题:.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 及更早版本有很大不同。

【讨论】:

    【解决方案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);
            }
            

            **调用旧的类库方法

            【讨论】:

              猜你喜欢
              • 2018-05-23
              • 2016-11-08
              • 1970-01-01
              • 1970-01-01
              • 2017-09-18
              • 2018-01-11
              • 1970-01-01
              • 1970-01-01
              • 2018-11-06
              相关资源
              最近更新 更多