2012-03-29 77 views
11

我将ASP.NET路由添加到旧的Webforms应用程序。我正在使用自定义HttpHandler来处理所有内容。在某些情况下,我想将特定路径映射回aspx文件,所以我需要将控制权交还给asp.net的默认HttpHandler。从自定义处理程序中调用默认的asp.net HttpHandler

我已经得到的最接近的是这

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 
} 

它没有做任何事情,没有什么输出流中。 MS的System.Web.UI.Page文档(作为一个IHttpHandler)会说“不要调用ProcessRequest方法,它是为了内部使用”。

从环顾四周,您似乎可以用MVC做到这一点,例如, :MvcHttpHandler doesn't seem to implement IHttpHandler

还有这个东西System.Web.UI.PageHandlerFactory它似乎只会为aspx文件产生一个Page handler,但它是内部的,我不能直接使用它。

此页面:http://msdn.microsoft.com/en-us/library/bb398986.aspx引用“默认的asp.net处理程序”,但不标识类或给出任何指示如何使用它。

关于如何做到这一点的任何想法?可能吗?

回答

6

持久不负有心人!这实际上是有效的,因为这些信息似乎几乎无处可用,所以我想我会回答我自己的问题。感谢Robert在这篇文章中用内部构造函数实例化这些内容,这是关键。

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

...并像一些小的奇迹,一个aspx页面处理&过程中的完全呈现,而无需重新引导。

我预计这只会在IIS7中工作。

1

我是你在webforms中使用路由,你应该能够为你想要的特定.aspx文件添加一个忽略路由。这将由默认的HttpHandler处理。

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

+0

我试图将不同的路由映射到文件,例如:我希望“/ a/b/c”在不重定向的情况下调用“default.aspx?path = a/b/c”。我已经忽略* .aspx。 – 2012-03-29 18:46:14

+0

+1不过分复杂。重定向没有什么大不了的。此外,您的答案非常适合使用此页面的更一般的Google搜索条款。 – Thabo 2014-06-03 22:41:00

0

另一种选择是通过处理您不希望返回默认响应并将其他映射重新映射到您自己的IHttpHandler的情况来反转逻辑。每当myCondition为false时,响应将是“默认”。交换机实现为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; } 
} 
相关问题