如何初始化自定义 HTTP 上下文或 HttpContextBase

发布于 2024-12-24 23:24:40 字数 287 浏览 0 评论 0原文

我正在尝试创建自己的自定义 HTTP 上下文:

CustomHttpContext : HttpContextBase
{
    public override HttpRequestBase Request { }
}

我不明白的一件事是如何使用初始化基类

System.Web.HttpContext.Current

是否有人知道如何首先使用当前 Http 初始化自定义上下文,然后覆盖某些方法/属性为了我自己的目的?

I am experimenting with creating my own custom HTTP Context:

CustomHttpContext : HttpContextBase
{
    public override HttpRequestBase Request { }
}

One thing i can't figure out is how to initialize the base class with

System.Web.HttpContext.Current

Does anyone have any ideas how i can initialise the custom context first with the Current Http then override certain Methods/Properties to serve my own purpose?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

水中月 2024-12-31 23:24:40

简单的答案是否定的,这是不可能的。另请注意,HttpContext 不是从 HttpContextBase 继承的,相反,它们都实现了 IServiceProvider。最后,HttpContext 被密封,这表明作者不希望人们除了使用这个类之外做任何事情。

毫无疑问,您对 HttpContextBase 有一个无参数构造函数感到恼火,因此甚至没有为您提供像 HttpContext 这样从当前请求和响应实例化它的选项!

让我们使用'反编译器'来看看HttpContext.Current的实现:

// System.Web.HttpContext
/// <summary>Gets or sets the <see cref="T:System.Web.HttpContext" /> object for the current HTTP request.</summary>
/// <returns>The <see cref="T:System.Web.HttpContext" /> for the current HTTP request.</returns>
public static HttpContext Current
{
    get
    {
        return ContextBase.Current as HttpContext;
    }
    set
    {
        ContextBase.Current = value;
    }
}

如果我们看一下 ContextBase.Current(来自 System.Web.Hosting.ContextBase):

// System.Web.Hosting.ContextBase
internal static object Current
{
    get
    {
        return CallContext.HostContext;
    }
    [SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
    set
    {
        CallContext.HostContext = value;
    }
}

和 CallContext(在 System.Runtime.Messaging 中):

// System.Runtime.Remoting.Messaging.CallContext
/// <summary>Gets or sets the host context associated with the current thread.</summary>
/// <returns>The host context associated with the current thread.</returns>
/// <exception cref="T:System.Security.SecurityException">The immediate caller does not have infrastructure permission. </exception>
public static object HostContext
{
    [SecurityCritical]
    get
    {
        IllogicalCallContext illogicalCallContext = Thread.CurrentThread.GetIllogicalCallContext();
        object hostContext = illogicalCallContext.HostContext;
        if (hostContext == null)
        {
            LogicalCallContext logicalCallContext = CallContext.GetLogicalCallContext();
            hostContext = logicalCallContext.HostContext;
        }
        return hostContext;
    }
    [SecurityCritical]
    set
    {
        if (value is ILogicalThreadAffinative)
        {
            IllogicalCallContext illogicalCallContext = Thread.CurrentThread.GetIllogicalCallContext();
            illogicalCallContext.HostContext = null;
            LogicalCallContext logicalCallContext = CallContext.GetLogicalCallContext();
            logicalCallContext.HostContext = value;
            return;
        }
        LogicalCallContext logicalCallContext2 = CallContext.GetLogicalCallContext();
        logicalCallContext2.HostContext = null;
        IllogicalCallContext illogicalCallContext2 = Thread.CurrentThread.GetIllogicalCallContext();
        illogicalCallContext2.HostContext = value;
    }
}

我们开始了解 HttpContext 是如何工作的正在检索中。它与当前用户访问该网站时启动的线程打包在一起(这非常有意义!)。进一步深入研究,我们可以看到它也会根据请求重新创建(见下文)。

我们还可以看到,在接口层,不能将 HttpContext.Current 更改为指向您自己的 HttpContext,因为该属性不是虚拟的。它还使用许多私有或内部的 BCL 类,因此您不能简单地复制大部分实现。

更简单且不易出现任何其他问题的方法是简单地使用您自己的 CustomContext 对象包装 HttpContext。您可以简单地将 HttpContext.Current 包装在 BaseContext 属性中,然后在该类上拥有自己的属性(并使用您想要存储和检索自己的属性的任何会话、数据库或基于请求的状态存储机制)。

就我个人而言,我会使用我自己的类来存储我自己的信息,因为它属于我的应用程序和用户等,并且与 http 管道或请求/响应处理没有任何关系。

另请参阅:

The simple answer is no, it's not possible. Also note that HttpContext does not inherit from HttpContextBase, instead, they both implement IServiceProvider. Finally, HttpContext is sealed, suggesting that the authors did not want people to do anything other than consume this class.

As you are no doubt annoyed by HttpContextBase has a parameterless constructor so does not even give you the option of instantiating it from the current request and response like HttpContext!

Let's use a 'decompiler' to take a look at the implementation of HttpContext.Current:

// System.Web.HttpContext
/// <summary>Gets or sets the <see cref="T:System.Web.HttpContext" /> object for the current HTTP request.</summary>
/// <returns>The <see cref="T:System.Web.HttpContext" /> for the current HTTP request.</returns>
public static HttpContext Current
{
    get
    {
        return ContextBase.Current as HttpContext;
    }
    set
    {
        ContextBase.Current = value;
    }
}

If we take a look at ContextBase.Current (from System.Web.Hosting.ContextBase):

// System.Web.Hosting.ContextBase
internal static object Current
{
    get
    {
        return CallContext.HostContext;
    }
    [SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
    set
    {
        CallContext.HostContext = value;
    }
}

and CallContext (in System.Runtime.Messaging):

// System.Runtime.Remoting.Messaging.CallContext
/// <summary>Gets or sets the host context associated with the current thread.</summary>
/// <returns>The host context associated with the current thread.</returns>
/// <exception cref="T:System.Security.SecurityException">The immediate caller does not have infrastructure permission. </exception>
public static object HostContext
{
    [SecurityCritical]
    get
    {
        IllogicalCallContext illogicalCallContext = Thread.CurrentThread.GetIllogicalCallContext();
        object hostContext = illogicalCallContext.HostContext;
        if (hostContext == null)
        {
            LogicalCallContext logicalCallContext = CallContext.GetLogicalCallContext();
            hostContext = logicalCallContext.HostContext;
        }
        return hostContext;
    }
    [SecurityCritical]
    set
    {
        if (value is ILogicalThreadAffinative)
        {
            IllogicalCallContext illogicalCallContext = Thread.CurrentThread.GetIllogicalCallContext();
            illogicalCallContext.HostContext = null;
            LogicalCallContext logicalCallContext = CallContext.GetLogicalCallContext();
            logicalCallContext.HostContext = value;
            return;
        }
        LogicalCallContext logicalCallContext2 = CallContext.GetLogicalCallContext();
        logicalCallContext2.HostContext = null;
        IllogicalCallContext illogicalCallContext2 = Thread.CurrentThread.GetIllogicalCallContext();
        illogicalCallContext2.HostContext = value;
    }
}

We start to get a feel for how the HttpContext is being retrieved. It's being packaged in with the thread the current user started when they visted the website (which makes perfect sense!). Delving further we can see it also gets recreated per request (see below).

We can also see, at the interface layer, HttpContext.Current cannot be changed to point at your own HttpContext as the property is not virtual. It also uses many BCL classes that are private or internal so you can't simply copy most of the implementation.

What would be easier, and also less prone to any other issues would be to simply wrap HttpContext with your own CustomContext object. You could simply wrap HttpContext.Current in a BaseContext property, then have your own properties on the class (and use whatever session, database, or request based state storage mechanism you want to store and retrieve your own properties).

Personally, I'd use my own class for storing my own information, as it belongs to my application and user etc and isn't really anything to do with the http pipeline or request/response processing.

See also:

沧笙踏歌 2024-12-31 23:24:40

只是为了在 dash 的答案中添加一点,您还可以将 [ThreadStatic] 属性与一些静态属性一起使用。通过使用 global.cs 或编写您自己的 HttpModule/HttpHandler 在 BeginRequest 上对其进行初始化。

如何创建网络模块:
http://msdn.microsoft.com/en- us/library/ms227673(v=vs.100).aspx

线程静态:
http://msdn.microsoft.com/en-us/library/system .threadstaticattribute.aspx

Just to add on a bit to dash's answer, you can also use the [ThreadStatic] attribute with some static property. Initialize it on BeginRequest, either by using global.cs or by writing your own HttpModule/HttpHandler.

How to create a web module:
http://msdn.microsoft.com/en-us/library/ms227673(v=vs.100).aspx

Thread static:
http://msdn.microsoft.com/en-us/library/system.threadstaticattribute.aspx

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文