2012-03-29 80 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; } 
} 
相關問題