2012-03-29 16 views
11

Estoy agregando enrutamiento ASP.NET a una aplicación webforms más antigua. Estoy usando un HttpHandler personalizado para procesar todo. En algunas situaciones, me gustaría asignar una ruta particular a un archivo aspx, por lo que necesito simplemente pasar el control de nuevo al HttpHandler predeterminado para asp.net.Llame al HttpHandler asp.net predeterminado desde un controlador personalizado

Lo más cerca que he conseguido es este

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 
} 

No sirve de nada, no hay ninguna salida al arroyo. La documentación de MS para System.Web.UI.Page (como IHttpHandler) dice algo así como "no llame al método ProcessRequest. Es para uso interno".

Al mirar a su alrededor parece que puede hacer esto con MVC, p. Ej. : MvcHttpHandler doesn't seem to implement IHttpHandler

También existe esta cosa System.Web.UI.PageHandlerFactory que parece que solo produciría un controlador de página para un archivo aspx, pero es interno y no puedo usarlo directamente.

Esta página: http://msdn.microsoft.com/en-us/library/bb398986.aspx hace referencia al "manejador de asp.net predeterminado" pero no identifica una clase ni da ninguna indicación de cómo se podría usar.

¿Alguna idea sobre cómo puedo hacer esto? ¿Es posible?

Respuesta

6

La persistencia da! Esto realmente funciona, y como esta información parece estar disponible prácticamente en ninguna parte, pensé que respondería mi propia pregunta. Gracias a Robert por este post sobre la creación de instancias con constructores internos, esta es la clave.

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); 
} 

... y como un pequeño milagro, una página aspx procesa & hace por completo durante el proceso sin la necesidad de reorientar.

Espero que esto solo funcione en IIS7.

1

Estoy utilizando el enrutamiento en formularios web, solo debería agregar una ruta de ignorar para los archivos .aspx específicos que desee. Esto será manejado por HttpHandler por defecto.

http://msdn.microsoft.com/en-us/library/dd505203.aspx

+0

Estoy intentando asignar una ruta diferente a un archivo, p. Quiero "/ a/b/c" para invocar "default.aspx? Path = a/b/c" sin redireccionar. Ya estoy ignorando * .aspx. –

+0

+1 para no complicar demasiado. Los redireccionamientos no son un gran problema. Además, tu respuesta es excelente para los términos más generales de búsqueda de google que te llevan a esta página. – Thabo

0

Otra opción es invertir la lógica manejando los casos en los que NO quieres devolver la respuesta predeterminada y reasignar los demás a tu propio IHttpHandler. Siempre que myCondition sea falso, la respuesta será el "predeterminado". El conmutador se implementa como un IHttpModule:

public class SwitchModule: IHttpModule 
{ 
    public void Init(HttpApplication context) 
    { 
     context.PostAuthenticateRequest += app_PostAuthenticateRequest; 
    } 

    void app_PostAuthenticateRequest(object sender, EventArgs e) 
    { 
     // Check for whatever condition you like   
     if (true) 
      HttpContext.Current.RemapHandler(new CustomHandler()); 

    } 

    public void Dispose()   
} 

internal class CustomHandler: IHttpHandler 
{ 
    public void ProcessRequest(HttpContext context) 
    { 
     context.Response.Write("hallo"); 
    } 

    public bool IsReusable { get; } 
} 
Cuestiones relacionadas