Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call the default asp.net HttpHandler from a custom handler

I'm adding ASP.NET routing to an older webforms app. I'm using a custom HttpHandler to process everything. In some situations I would like to map a particular path back to an aspx file, so I need to just pass control back to the default HttpHandler for asp.net.

The closest I've gotten is this

public void ProcessRequest(HttpContext context) {
    // .. when we decide to pass it on

    var handler = new System.Web.UI.Page();
    handler.ProcessRequest(context);

    MemoryStream steam = new MemoryStream();
    StreamWriter writer = new StreamWriter(stream);
    HtmlTextWriter htmlWriter = new HtmlTextWriter(writer);
    handler.RenderControl(htmlWriter);


    // write headers, etc. & send stream to Response
}

It doesn't do anything, there's nothing output to the stream. MS's documentation for System.Web.UI.Page (as an IHttpHandler) say something to the effect of "do not call the ProcessRequest method. It's for internal use."

From looking around it seems like you can do this with MVC, e.g. : MvcHttpHandler doesn't seem to implement IHttpHandler

There is also this thing System.Web.UI.PageHandlerFactory which appears that it would just produce a Page handler for an aspx file, but it's internal and I can't use it directly.

This page: http://msdn.microsoft.com/en-us/library/bb398986.aspx refers to the "default asp.net handler" but does not identify a class or give any indication how one might use it.

Any ideas on how I can do this? Is it possible?

like image 422
Jamie Treworgy Avatar asked Mar 29 '12 18:03

Jamie Treworgy


People also ask

What is HTTP handler in ASP NET MVC?

HTTPHandler is a low level request and response API in ASP.Net for injecting pre-processing logic to the pipeline based on file extensions and verbs. An HTTPhandler may be defined as an end point that is executed in response to a request and is used to handle specific requests based on extensions.

What is HTTP handler in .NET core?

Handlers are:Classes that implement IHttpHandler. Used to handle requests with a given file name or extension, such as .report. Configured in Web.

Which of the following elements registers the custom handler?

The configuration element registers the custom handler factory by class name and maps the . sample file name extension to that handler. Because you are registering a custom file name extension, you register the handler in both the handlers section and the httpHandlers section.


1 Answers

Persistence pays off! This actually works, and since this information seems to be available pretty much nowhere I thought I'd answer my own question. Thanks to Robert for this post on instantiating things with internal constructors, this is the key.

http://www.rvenables.com/2009/08/instantiating-classes-with-internal-constructors/

public void ProcessRequest(HttpContext context) {
    // the internal constructor doesn't do anything but prevent you from instantiating
    // the factory, so we can skip it.
    PageHandlerFactory factory =
        (PageHandlerFactory)System.Runtime.Serialization.FormatterServices
        .GetUninitializedObject(typeof(System.Web.UI.PageHandlerFactory));

     string newTarget  = "default.aspx"; 
     string newQueryString = // whatever you want
     string oldQueryString = context.Request.QueryString.ToString();
     string queryString = newQueryString + oldQueryString!="" ? 
         "&" + newQueryString :
         "";

     // the 3rd parameter must be just the file name.
     // the 4th parameter should be the physical path to the file, though it also
     //   works fine if you pass an empty string - perhaps that's only to override
     //   the usual presentation based on the path?

     var handler = factory.GetHandler(context, "GET",newTarget,
         context.Request.MapPath(context,newTarget));

     // Update the context object as it should appear to your page/app, and
     // assign your new handler.

     context.RewritePath(newTarget  , "", queryString);
     context.Handler = handler;

     // .. and done

     handler.ProcessRequest(context);
}

... and like some small miracle, an aspx page processes & renders completely in-process without the need to redirect.

I expect this will only work in IIS7.

like image 77
Jamie Treworgy Avatar answered Nov 12 '22 11:11

Jamie Treworgy