2014-04-23 4 views
10

Ich habe eine ASP.NET MVC 4 App (mit .NET Framework 4.5) mit erweiterungsfreien URLs. Die Site enthält einige statische Dateien, aber alle erweiterungsfreien Anfragen sollten in MVC-Routing gehen.So leiten Sie eine Anforderung für ein Verzeichnis auf der Festplatte an ASP.NET MVC weiter?

Alles funktioniert gut für Anfragen wie:

  • /
  • /news
  • /fr/news

Allerdings, wenn ich eine Anfrage machen/fr ich den Fehler :

HTTP Error 403.14 - Forbidden, 
The Web server is configured to not list the contents of this directory. 

Ich verstehe, dass dies ist weil es tatsächlich ein/fr-Verzeichnis auf der Festplatte gibt, möchte ich diese Anfrage dennoch meiner MVC-App zuordnen. Es ist keine Option, das fr-Verzeichnis zu entfernen, da es einige statische Dateien enthält.

Ist das möglich? Ich habe versucht, runAllManagedModulesForAllRequests="true" zum Modulelement in system.webServer hinzuzufügen (ich will nicht wirklich tun, aber es half nicht irgendwie).

Bearbeiten - im Falle seiner nützlich, hier ist das Routing:

public static void RegisterRoutes(RouteCollection routes) 
    { 
     routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 
     routes.IgnoreRoute("cid/{*pathInfo}"); 
     routes.MapRoute(
      "Page", 
      "{*PageId}", 
      new { controller = "Page", action = "Page" }, // Parameter defaults 
      new { pageId = @"^(.*)?$" } // Parameter constraints 
     ); 
     routes.MapRoute(
      name: "Default", 
      url: "{controller}/{action}/{id}", 
      defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 
     ); 
    } 
+0

ich das Routing hinzugefügt, obwohl ich bin nicht sicher, dass dies relevant ist, da MVC Routing niemals für die/fr-Anfrage eintritt. Ich bin mir ziemlich sicher, dass dies auf das DirectoryListingModule zurückzuführen ist, aber ich kann das nicht aus dem Bild herausholen (wie beschrieben unter: http://stackoverflow.com/questions/21842206/how-to-disable- oder- repriorize-iis-directorylistingmodule-under-mvc-modul) – Will

+0

Schauen Sie hier [http://stackoverflow.com/a/17336588/3383479] (http://Stackoverflow.com/a/17336588/3383479) –

+0

Nicht sicher wie das hilft, wie gesagt ich kann das/fr-Verzeichnis nicht löschen – Will

Antwort

5

Der einfachste Weg, den Zugriff auf lokale Ordner und Dateien zu verhindern, ist RouteCollection.RouteExistingFiles Flag setzen ASP.NET Griff URLs Targeting physischen Dateien zu lassen. So Ihre Route ändern Register:

public static void RegisterRoutes(RouteCollection routes) 
{ 
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 
    routes.IgnoreRoute("cid/{*pathInfo}"); 

    routes.RouteExistingFiles = true; 
    routes.MapRoute(
     "Page", 
     "{*PageId}", 
     new { controller = "Page", action = "Page" }, // Parameter defaults 
     new { pageId = @"^(.*)?$" } // Parameter constraints 
    ); 
} 

Ihre "Default" Route nicht als "Page" erforderlich ist, ist wirklich ein allumfassender Fall.

Eine andere Methode besteht darin, die IIS-Konfiguration so zu ändern, dass ASP.NET MVC-Routing eine höhere Priorität erhält als die IIS-Verzeichnisliste. Wechseln Sie in IIS7 zu Ihrer Website, wählen Sie im Abschnitt IIS die Option Module und dann im Register Aktionen die Option Geordnete Liste anzeigen aus. Verschieben Sie UrlRoutingModule über DirectoryListingModule.


Als eine Randnotiz, von Ihren Kommentaren verstehe ich, dass Sie einen einzigen Controller mit einer einzigen Aktion haben. Die Aktion erfüllt alle Anforderungen, abgesehen von den statischen Ressourcen, die mit IgnoreRoute definiert sind. Dies ist kein empfohlenes Setup, da Sie alle Vorteile der MVC-Architektur verlieren. Darüber hinaus werden Sie feststellen, dass Ihre Page-Aktion schnell wächst und immer mehr Fälle einschließt. Genau das wollten Routing und Controller lösen.

Wenn Sie denken, eine einzige Catch-All-Methode ist die beste Lösung für Sie, als Sie nicht wirklich MVC benötigen und Sie wäre besser dran mit Web-API, die viel geringeren Anforderung Overhead hat.

+0

Ich hatte gehofft zu vermeiden, Anfragen nach physischen Dateien durch das MVC-Routing zu drängen, da ich mir nicht vorstellen kann, dass dies keine Auswirkungen auf die Leistung meiner Statik hätte. – Will

+0

Vielen Dank für den zusätzlichen Hinweis auf MVC-Architektur, aber keine Sorge - es ist eine "richtige" MVC-Architektur! Die Anwendung ist mit einem CMS verbunden. Wenn also eine Anfrage eingeht, ordnen wir die Anfrage-URL zuerst einem Seitenobjekt im CMS zu, das eine Reihe von Unteraktionen definiert, die die Standardroute und normale MVC-Dateien verwenden eine Reihe von Controllern, Aktionen und Ansichten) – Will

+0

@Will Kein Zweifel, das Routing hat einen Performance-Effekt, aber es könnte kleiner sein, dass Sie denken. ASP.NET versucht, so viel wie möglich an IIS zu übergeben, und IIS-Handler sind sehr gut im Caching. Wenn Ihre Einrichtung also ASP.NET 4.0 + auf IIS 7 + gehostet wird, würde ich mir nicht zu viele Gedanken über die Leistung machen. Hier finden Sie weitere Details: http://blogs.msdn.com/b/tmarq/archive/2010/04/01/asp-net-4-0-ablees-routing-of-extensionless-urls-without- Impinging-Static-Requests.aspx –

0

EDIT: Ich dachte zunächst, dass es notwendig war, die DirectoryListingModule zu entfernen, aber dies ist nicht der Fall, meine benutzerdefinierten Httpmodule Rewrite schlägt vor diesem in, so dass es in gelassen werden kann

Die Abhilfe, die ich. verwendet, um dies zu beheben, war, Logik zu einem benutzerdefinierten HttpModule hinzuzufügen, das eine Anfrageverarbeitung durchführte. Hier erkenne ich, ob die Anfrage der Wurzel einer meiner Lokalisierungen entspricht (/ fr// es/etc.) und wenn ja, schreibe die URL auf die Standardseite/fr/index zurück, für die das Routing normal funktioniert.

private void BeginRequest(object sender, EventArgs e) 
{ 
    HttpApplication application = (HttpApplication)sender; 
    HttpContext context = application.Context; 
    var url = context.Request.Url.AbsolutePath; 
    if (IsLocalizationRoot(url)) 
    { 
     context.RewritePath(url + GetDefaultPageName()); 
    } 
} 

Wenn Sie daran interessiert, wie die DirectoryListingModule zu entfernen (wie oben erwähnt, ist dies nicht notwendig, aber seine nützliche Informationen sowieso):

Als StaticFileHandler Referenzen es, müssen Sie es entfernen und entfernen und erneut hinzufügen, die StaticFileHandler (ohne DirectoryListingModule) in Ihrer web.config:

<system.webServer> 
    <handlers> 
     <remove name="StaticFile"/> 
     <add name="StaticFile" path="*" verb="*" modules="StaticFileModule,DefaultDocumentModule" 
      resourceType="Either" requireAccess="Read" /> 
    </handlers> 
    <modules> 
     <remove name="DirectoryListingModule"/> 
    </modules> 
</system.webServer> 

Dies ist wahrscheinlich eine HTTP-500-Fehler verursachen wird, aufgrund einer Sperre Verletzung. Sie müssen es in der IIS-applicationHost.config entsperren:

eine Eingabeaufforderung (als Administrator ausführen) und gehen Sie zu C: \ Windows \ system32 \ inetsrv

appcmd set module DirectoryListingModule /lockItem:false 
+0

Während dies funktioniert - es fühlt sich an wie ein Workaround und so frage ich mich, ob es eine reine Config-Lösung, die kein HTTP-Modul oder Routing statische Anfragen über MVC ... – Will

+0

Es ist auch keine generische Lösung zu dem Problem, dass bestehende Verzeichnisse nicht weitergeleitet werden - obwohl es für meinen Anwendungsfall funktioniert – Will