Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to copy/clone HttpContext of a web request

What's the easiest way to clone current request's HttpContext instance?

I'm developing an app in Asp.net MVC v1. I upgraded the regular PartialView capabilities to actually have sub-controllers that act very similar, but have their own context. When you use PartialViews you have to fill view data for the partial view in your main view's controller action. I created my own functionality that makes it possible to call controller actions from within a view. This way I get:

  • I don't have to provide sub-view's data in my main view's controller action
  • sub controller methods can manipulate data more encapsulated without any relation to other views/controllers

The problem is that each sub-controller request uses HttpContext. So when I set some HttpContext.Item in a sub-controller it actually populates HttpContext of the actual request.

That's why I want to clone HttpContext. I'm already using:

HttpContext subContext = new HttpContext(request, response);
// what happened to Session, User, Items etc. properties?

but this doesn't set anything else than request and response. But I would probably also need other properties and collections... Like Session, Items, User... etc.

like image 389
Robert Koritnik Avatar asked Mar 01 '23 06:03

Robert Koritnik


2 Answers

While the "Not Possible" answer is correct, there is an alternative that is much cleaner than writing values into the current context and then rewriting back to its original state. The solution is to make a new HttpContext object entirely that is based on the URL of your choosing.

// A new request/response is constructed to using a new URL.
// The new response is using a StreamWriter with null stream as a backing stream 
// which doesn't consume resources

using (var nullWriter = new StreamWriter(Stream.Null))
{
    var newRequestUri = new Uri("http://www.somewhere.com/some-resource/");
    var newRequest = new HttpRequest("", newRequestUri.ToString(), newRequestUri.Query);

    var newResponse = new HttpResponse(nullWriter);
    var newContext = new HttpContextWrapper(new HttpContext(newRequest, newResponse));

    // Work with the new context here before it is disposed...
} 

Reference: https://github.com/maartenba/MvcSiteMapProvider/issues/278#issuecomment-34905271

like image 75
NightOwl888 Avatar answered Mar 02 '23 21:03

NightOwl888


Not possible

I guess an actual deep cloning is not possible because of server session state. Cloning would also have to clone this value, which is web server specific internal resource that is intrinsically static and can not be cloned. In this case a web server would have multiple Session objects for instance.

Workaround
Anyway. The workaround was to set additional context values before instantiating sub-controller processing. After processing is finished I reverted values back to original. So I actually had context as it was before.

like image 25
Robert Koritnik Avatar answered Mar 02 '23 20:03

Robert Koritnik