Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to initialise a custom HTTP Context or HttpContextBase

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?

like image 763
Fixer Avatar asked Feb 22 '23 23:02

Fixer


1 Answers

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:

  • ASP.NET MVC : How to create own HttpContext
  • How is HttpContext being maintained over request-response
like image 177
dash Avatar answered Apr 02 '23 03:04

dash