2009-07-19 86 views
61

ASP.Net路由(而不是MVC)可用於提供靜態文件嗎?使用ASP.NET路由來提供靜態文件

說我想航線

http://domain.tld/static/picture.jpg 

http://domain.tld/a/b/c/picture.jpg 

,我要動態地做它在這個意義上,重寫URL計算的飛行。我無法一勞永逸地設置一條靜態路由。

反正,我可以創造這樣的路線:

routes.Add(
    "StaticRoute", new Route("static/{file}", new FileRouteHandler()) 
); 

FileRouteHandler.ProcessRequest方法我可以重寫從/static/picture.jpg/a/b/c/picture.jpg的路徑。然後我想爲靜態文件創建一個處理程序。 ASP.NET爲此使用StaticFileHandler。不幸的是,這門課是內部的。我試圖創建使用反射處理程序,它實際上工作:

Assembly assembly = Assembly.GetAssembly(typeof(IHttpHandler)); 
Type staticFileHandlerType = assembly.GetType("System.Web.StaticFileHandler"); 
ConstructorInfo constructorInfo = staticFileHandlerType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, Type.EmptyTypes, null); 
return (IHttpHandler) constructorInfo.Invoke(null); 

但使用內部類型似乎不是正確的解決方案。另一個選擇是實現我自己的StaticFileHandler,但是正確執行(支持範圍和etags之類的HTTP內容)並不重要。

我應該如何處理ASP.NET中靜態文件的路由?

回答

37

在仔細研究了這個問題幾個小時之後,我發現只需添加忽略規則就可以獲得靜態文件。

在的RegisterRoutes(RouteCollection路線),添加以下忽略的規則:

routes.IgnoreRoute("{file}.js"); 
routes.IgnoreRoute("{file}.html"); 
48

爲什麼不使用IIS來做到這一點?您可以創建重定向規則,將請求從第一條路徑指向第二條路徑,然後再將請求發送到您的應用程序。因此,這將是一個更快速的重定向請求的方法。

假設你有IIS7 +,你這樣做......

<rule name="Redirect Static Images" stopProcessing="true"> 
    <match url="^static/?(.*)$" /> 
    <action type="Redirect" url="https://stackoverflow.com/a/b/c/{R:1}" redirectType="Permanent" /> 
</rule> 

或者,如果你不需要重定向,如@ ni5ni6建議:

<rule name="Rewrite Static Images" stopProcessing="true"> 
    <match url="^static/?(.*)$" /> 
    <action type="Rewrite" url="https://stackoverflow.com/a/b/c/{R:1}" /> 
</rule> 

編輯2015-06-17 for @RyanDawkins

如果您想知道重寫規則在哪裏出現,這裏是它在web.config文件中的位置的地圖。

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <system.webServer> 
    <rewrite> 
     <rules> 
     <!-- rules go below --> 
     <rule name="Redirect Static Images" stopProcessing="true"> 
      <match url="^static/?(.*)$" /> 
      <action type="Redirect" url="https://stackoverflow.com/a/b/c/{R:1}" redirectType="Permanent" /> 
     </rule> 
     </rules> 
    </rewrite> 
    </system.webServer> 
</configuration> 
+0

我寧願這種做法,也是如此。將它移出到管道,並讓IIS工作進程處理重定向比通過運行時實際處理路徑的循環更有效,我假設。即使服務器上的流失量大致相同,我也會選擇不使用路由的路由(雙關語),並將重定向保留在應用程序之外。 – 2009-07-26 19:00:22

+0

從我的問題的最初版本中不清楚的是,重寫的URL是即時計算的(我不擔心這裏的性能)。我已經更新了這個問題來澄清這一點。無論如何,謝謝你的回覆。 – 2009-07-26 20:52:47

+0

(刪除我以前的評論,並重新添加一個非縮短的網址)。除了性能問題之外,爲什麼要在應用程序中處理這個URL,在外部處理時會更好?我想你可以創建一個處理這個的控制器動作,但這裏有一些你可以看看的東西: - http://geekswithblogs.net/sankarsan/archive/2009/01/18/developing-custom-routehandler.aspx – 2011-07-20 11:52:36

5

我想出了一個替代使用內部StaticFileHandler。在IRouteHandler我打電話HttpServerUtility.Transfer

public class FileRouteHandler : IRouteHandler { 

    public IHttpHandler GetHttpHandler(RequestContext requestContext) { 
    String fileName = (String) requestContext.RouteData.Values["file"]; 
    // Contrived example of mapping. 
    String routedPath = String.Format("https://stackoverflow.com/a/b/c/{0}", fileName); 
    HttpContext.Current.Server.Transfer(routedPath); 
    return null; // Never reached. 
    } 

} 

這是一個黑客。 IRouteHandler應該返回IHttpHandler而不是中止並傳輸當前請求。但是,它確實實現了我想要的。

使用內部StaticFileHandler也有點破解,因爲我需要反思才能訪問它,但至少有一些documentation on StaticFileHandler on MSDN使它成爲一個稍微更「官方」的類。不幸的是,我不認爲有可能在部分信任環境中反思內部類。

我會堅持使用StaticFileHandler,因爲我不認爲它會在可預見的將來從ASP.NET中刪除。