Punkte in der URL verursachen 404 mit ASP.NET mvc und IIS

303

Ich habe ein Projekt, für das meine URLs Punkte im Pfad enthalten müssen. Zum Beispiel kann ich eine URL wie www.example.com/people/michael.phelps haben

URLs mit dem Punkt erzeugen eine 404. Mein Routing ist in Ordnung. Wenn ich michaelphelps ohne Punkt übergebe, dann funktioniert alles. Wenn ich den Punkt hinzufüge, erhalte ich einen 404-Fehler. Die Beispielsite wird unter Windows 7 mit IIS8 Express ausgeführt. URLScan wird nicht ausgeführt.

Ich habe versucht, meiner web.config Folgendes hinzuzufügen:

<security>
  <requestFiltering allowDoubleEscaping="true"/>
</security>

Leider machte das keinen Unterschied. Ich erhalte gerade den Fehler 404.0 Not Found.

Dies ist ein MVC4-Projekt, aber ich denke nicht, dass dies relevant ist. Mein Routing funktioniert einwandfrei und die von mir erwarteten Parameter sind vorhanden, bis sie einen Punkt enthalten.

Was muss ich konfigurieren, damit meine URL Punkte enthält?

Kennzeichen
quelle
93
Ich kann nicht glauben, dass ich so viel Zeit damit verbracht habe. Die URL funktioniert einwandfrei, wenn ich einen abschließenden Schrägstrich hinzufüge. Beispielsweise gibt www.example.com/people/michael.phelps/ jedoch ohne den abschließenden Schrägstrich IIS einen 404-Fehler aus.
Mark
15
Markieren - das liegt daran, dass IIS ohne den abschließenden Schrägstrich der Meinung ist, dass es sich um eine Datei handelt, die gefunden werden sollte. Das Hinzufügen des Schrägstrichs hat den Effekt ... dass dies keine echte Datei ist. Darüber hinaus teilt die unten stehende Konfigurationsoption IIS mit, dass Sie versuchen sollten, sie stattdessen weiterzuleiten, wenn es sich nicht um eine Datei handelt.
Tommy
Ich habe das gleiche Problem, nachdem ich mein Projekt auf mvc 4 + asp.net 4.5 aktualisiert habe.
Tadeu Maia
Um dies zu umgehen, verwende ich IIS Rewrite, um meinen URLs den abschließenden Schrägstrich hinzuzufügen.
Mark
4
Das funktioniert bei mir nicht. Die URL funktioniert gut mit "." innerhalb der URL, aber wenn es ganz am Ende ist, gibt es einen Fehler
Arcadian

Antworten:

379

Ich habe dies durch Bearbeiten der HTTP-Handler meiner Site zum Laufen gebracht. Für meine Bedürfnisse funktioniert dies gut und löst mein Problem.

Ich habe einfach einen neuen HTTP-Handler hinzugefügt, der nach bestimmten Pfadkriterien sucht. Wenn die Anforderung übereinstimmt, wird sie zur Verarbeitung korrekt an .NET gesendet. Ich bin mit dieser Lösung viel glücklicher, dass URLRewrite HackMFAR hackt oder aktiviert.

Wenn .NET beispielsweise die URL www.example.com/people/michael.phelps verarbeiten soll, fügen Sie der web.config Ihrer Site innerhalb des system.webServer / handlersElements die folgende Zeile hinzu :

<add name="ApiURIs-ISAPI-Integrated-4.0"
     path="/people/*"
     verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
     type="System.Web.Handlers.TransferRequestHandler"
     preCondition="integratedMode,runtimeVersionv4.0" />

Bearbeiten

Es gibt andere Beiträge, die darauf hinweisen, dass die Lösung für dieses Problem RAMMFARoder ist RunAllManagedModulesForAllRequests. Durch Aktivieren dieser Option werden alle verwalteten Module für alle Anforderungen aktiviert. Das bedeutet, dass statische Dateien wie Bilder, PDFs und alles andere von .NET verarbeitet werden, wenn dies nicht erforderlich ist. Diese Option wird am besten weggelassen, es sei denn, Sie haben einen bestimmten Fall dafür.

Kennzeichen
quelle
3
Hier ist ein vollständiges Beispiel stackoverflow.com/a/16607685/801189 basierend auf dieser Antwort
VB
10
Nachdem Sie dies mit [path = "*"] hinzugefügt haben, schlagen alle Anforderungen an statische Dateien wie .css, .js fehl. Ich habe eine benutzerdefinierte Route, die URLs verarbeitet, die wie folgt aussehen: " domain / ABCDE.FGHIJ ". Alle meine statischen Dateien befinden sich in meinem Verzeichnis / Content. Gibt es eine Möglichkeit, das gesamte Verzeichnis davon auszuschließen? RAMMFAR auf true zu setzen funktioniert, aber ich möchte diesen Overhead vermeiden.
Lamarant
2
Lokaler IIS funktioniert mit dem Starten eines Schrägstrichs, aber IIS8 versteht die Route nur ohne ersten Schrägstrich.
Pavel Voronin
2
Ich habe das gleiche Problem wie @lamarant ... Es blockiert die statischen Dateien. Weißt du, warum? Hier MVC4 verwenden.
Eestein
3
Es funktioniert in MVC5, aber wenn Sie am Anfang des Pfads einen Schrägstrich einfügen, funktioniert es nur, wenn der Pfad unmittelbar nach dem Hostnamen liegt (er ist nicht relativ zum App-Ordner). Zum Beispiel würde path / people / * für www.example.com/people/michael.phelps funktionieren, nicht jedoch für www.example.com/app/people/michael.phelps. AFAIK gibt es keine Möglichkeit, den Pfad relativ zur App zu machen.
Hogan
46

Nach einigem Stöbern stellte ich fest, dass entspanntes UrlToFileSystemMapping bei mir überhaupt nicht funktionierte. In meinem Fall wurde RAMMFAR auf true gesetzt. Gleiches gilt für (.net 4.0 + mvc3) und (.net 4.5 + mvc4).

<system.webserver>
    <modules runAllManagedModulesForAllRequests="true">

Beachten Sie beim Einstellen von RAMMFAR den wahren Hanselman-Beitrag zu RAMMFAR und Leistung

Tadeu Maia
quelle
5
Seien Sie sich bewusst, wenn Sie RAMMFAR einstellen ... Gibt es einen Leistungsverlust, wenn ich dieses <modules runAllManagedModulesForAllRequests = "true"> verwende
Shanker Paudel
1
Im Falle des Originalplakats sollte es nicht benötigt werden, da er IIS7 und höher verwendet. Dort ist es die Standardeinstellung und das Einstellen des RAMMFAR kostet Sie in der Tat exta. Siehe msdn.microsoft.com/en-us/library/…
Richard
Obwohl dies nützlich ist, reichte dies nicht aus, um Zeiträume zu erhalten, in denen 404s in MVC5 / IIS7 nicht mehr für mich zurückgegeben werden.
Chris Moschini
Nur um es noch einmal zu wiederholen. Sie möchten vermeiden, dass diese Option aktiviert wird
Strake
Tun Sie dies jedoch nicht auf einer Live-Site, wenn dies überhaupt möglich ist.
NickG
27

Ich glaube, Sie müssen die Eigenschaft entspanntUrlToFileSystemMapping in Ihrer web.config festlegen. Haack hat vor einiger Zeit einen Artikel darüber geschrieben (und es gibt einige andere SO-Beiträge , die die gleichen Arten von Fragen stellen).

<system.web>
<httpRuntime relaxedUrlToFileSystemMapping="true" />

Bearbeiten In späteren Kommentaren von .NET / IIS muss dies möglicherweise im system.WebServerElement enthalten sein.

<system.webServer>
<httpRuntime relaxedUrlToFileSystemMapping="true" />
Tommy
quelle
2
Dies ist, was ich mit mvc3 + .net4.0 hatte und wunderbar funktionierte, aber nicht mehr mit mvc4 + .net4.5.
Tadeu Maia
4
Ich habe das RelaxedUrlToFileSystemMapping ohne Erfolg ausprobiert. Ich denke nicht, dass es mit den neuesten Versionen von MVC funktioniert.
Mark
Dadurch konnte ich die URL /WEB-INF./web.xml abrufen und auf eine benutzerdefinierte Fehlerseite umleiten, wenn sehr viele andere Methoden, die ich ausprobiert habe, nicht funktionierten.
Quentin-Starin
3
Interessant. Da es bei Ihnen nicht funktioniert hat, wollte ich davon ausgehen, dass dies bei mir nicht funktioniert ... vorausgesetzt, ich bin auf MVC4 mit .NET4.5. Aber Bingo, es hat trotzdem funktioniert. In meinem Fall hatte ich einfach eine URL mit einem Punkt "." als letztes Zeichen. Ich habe 404 bekommen, aber das hat es behoben.
PandaWood
Hat er Auswirkungen auf die Sicherheit?
Paesano2000
23

Ich habe mich lange mit diesem Thema beschäftigt, nachdem ich all die verschiedenen Mittel ohne Erfolg verfolgt hatte.

Ich habe festgestellt, dass beim Hinzufügen eines Schrägstrichs [/] am Ende der URL mit den Punkten [.] Kein 404-Fehler ausgegeben wurde und tatsächlich funktioniert hat.

Ich habe das Problem schließlich mit einem URL-Rewriter wie IIS URL Rewrite gelöst, um nach einem bestimmten Muster zu suchen und den Trainingsslash anzuhängen.

Meine URL sieht folgendermaßen aus: /Contact/~firstname.lastname, daher lautet mein Muster einfach: /Contact/~(.*[^/‹)$

Ich habe diese Idee von Scott Forsyth erhalten, siehe Link unten: http://weblogs.asp.net/owscott/handing-mvc-paths-with-dots-in-the-path

Leon van Wyk
quelle
Das hat bei mir funktioniert (MVC5). Andere Vorschläge oben haben nicht funktioniert und wurden nicht benötigt, nur ein abschließender Schrägstrich. Ich werde meine Routen wie von @ jonduncan05 hier vorgeschlagen ändern .
Markau
Danke, Leon. Hat mir den Tag gerettet. Ich bin mir nicht sicher über all die web.config-Sachen, über die die Leute hier reden, aber das Hinzufügen des Trailing / war die Antwort, die ich brauchte. In meinem Fall habe ich die Kontrolle über den serverseitigen Controller und das Javascript, das ihn aufgerufen hat, also habe ich gerade JavaScript und Voila aktualisiert!
Frosch Pr1nce
21

Fügen Sie diesen Abschnitt einfach zu Web.config hinzu, und alle Anforderungen an die Route / {* pathInfo} werden vom angegebenen Handler verarbeitet, auch wenn in pathInfo Punkte vorhanden sind. (entnommen aus dem Beispiel von ServiceStack MVC Host Web.config und dieser Antwort https://stackoverflow.com/a/12151501/801189 )

Dies sollte sowohl für IIS 6 als auch für IIS 7 funktionieren. Sie können bestimmten Handlern nach der 'Route' bestimmte Handler zuweisen, indem Sie path = "*" in den 'add'-Elementen ändern

  <location path="route">
    <system.web>
      <httpHandlers>
        <add path="*" type="System.Web.Handlers.TransferRequestHandler" verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" />
      </httpHandlers>
    </system.web>
    <!-- Required for IIS 7.0 -->
    <system.webServer>
      <modules runAllManagedModulesForAllRequests="true" />
      <validation validateIntegratedModeConfiguration="false" />
      <handlers>
        <add name="ApiURIs-ISAPI-Integrated-4.0" path="*" type="System.Web.Handlers.TransferRequestHandler" verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" preCondition="integratedMode,runtimeVersionv4.0" />
      </handlers>
    </system.webServer>
  </location>
VB
quelle
2
Beachten Sie die Leistungsfolgen, die runAllManagedModulesForAllRequests (RAMMFAR) hat. Dadurch werden alle verwalteten Module für jede Anforderung aktiviert. Statische Dateien, wie z. B. Bilder, können direkt von IIS verarbeitet werden. Dies verarbeitet sie jedoch über jedes Modul und erhöht den Overhead für jede Anforderung.
Mark
@ MarkS. Ja, aber ich glaube, dies wirkt sich nur auf die Anforderung an route / ... aus, wenn wir den Abschnitt <location> verwenden und die runAllManagedModulesForAllRequests nicht im Hauptabschnitt <system.webServer> festlegen.
VB
@VB Ich denke, nur der Handler ist ausreichend, es sei denn, Sie haben Dateien auf dem System, die mit einer URL übereinstimmen, die .NET verarbeiten soll. Aus irgendeinem Grund funktionierte RAMMFAR nicht auf der Ebene <Standort>, aber die Handlerlösung.
WebXL
@webXL <Standort> wird benötigt, wenn MVC keine Anforderungen an eine angegebene Route verarbeiten und Routen hinzufügen soll.IgnoreRoute ("route / {* pathInfo}"); Anschließend prüft IIS den Standortabschnitt <location path = "route"> und verwendet im Standortabschnitt die angegebenen Handler, umgeht jedoch das Routing von MVC und die Pipeline-Schritte anderer MVC vollständig. In meinem Projekt funktioniert die ServiceStack-API ohne dieses Setup einfach nicht.
VB
Warum wird die Handlerarbeit nicht einfach hinzugefügt? In meinem Fall muss ich RAMMFAR zusammen mit dem Handler hinzufügen. Ich suche hier eine gute Erklärung. :)
Aditya Patil
6

MVC 5.0-Problemumgehung.

Viele der vorgeschlagenen Antworten scheinen in MVC 5.0 nicht zu funktionieren.

Da das 404-Punkte-Problem im letzten Abschnitt gelöst werden kann, indem dieser Abschnitt mit einem abschließenden Schrägstrich geschlossen wird, ist hier der kleine Trick, den ich verwende, sauber und einfach.

Während Sie einen praktischen Platzhalter im Blick haben:

@Html.ActionLink("Change your Town", "Manage", "GeoData", new { id = User.Identity.Name }, null)

Fügen Sie ein wenig jquery / javascript hinzu, um die Arbeit zu erledigen:

<script>
    $('a:contains("Change your Town")').on("click", function (event) {
        event.preventDefault();
        window.location.href = '@Url.Action("Manage", "GeoData", new { id = User.Identity.Name })' + "/";
    });</script>

Bitte beachten Sie den abschließenden Schrägstrich, der für die Änderung verantwortlich ist

http://localhost:51003/GeoData/Manage/[email protected]

in

http://localhost:51003/GeoData/Manage/[email protected]/
Luke
quelle
5

Super einfache Antwort für diejenigen, die dies nur auf einer Webseite haben. Bearbeiten Sie Ihren Actionlink und ein + "/" am Ende.

  @Html.ActionLink("Edit", "Edit", new { id = item.name + "/" }) |
Jeremy Hobbs
quelle
Hat es für mich gelöst! Einfach und elegant! Am irritierendsten ist, dass es während der Entwicklung unter Windows 10 ohne das '/' funktioniert, aber für Windows 2012 scheint es erforderlich zu sein.
Wim zehn Brink
2

Vielleicht möchten Sie darüber nachdenken, Bindestriche anstelle von Punkten zu verwenden.

In Pro ASP MVC 3 Framework empfehlen sie Folgendes zum Erstellen benutzerfreundlicher URLs:

Vermeiden Sie Symbole, Codes und Zeichenfolgen. Wenn Sie ein Worttrennzeichen möchten, verwenden Sie einen Bindestrich (/ my-great-article). Unterstriche sind unfreundlich und URL-codierte Leerzeichen sind bizarr (/ mein + großartiger + Artikel) oder widerlich (/ mein% 20great% 20article).

Es wird auch erwähnt, dass URLs für Menschen leicht zu lesen und zu ändern sein sollten. Vielleicht kommt ein Grund, über die Verwendung eines Strichs anstelle eines Punktes nachzudenken, auch aus demselben Buch:

Verwenden Sie keine Dateinamenerweiterungen für HTML-Seiten (.aspx oder .mvc), sondern für spezielle Dateitypen (.jpg, .pdf, .zip usw.). Webbrowser interessieren sich nicht für Dateinamenerweiterungen, wenn Sie den MIME-Typ entsprechend einstellen, aber Menschen erwarten immer noch, dass PDF-Dateien mit .pdf enden

Während eine Periode für Menschen noch lesbar ist (obwohl sie weniger lesbar ist als Bindestriche, IMO), kann sie dennoch etwas verwirrend / irreführend sein, je nachdem, was nach der Periode kommt. Was ist, wenn jemand einen Nachnamen von zip hat? Dann lautet die URL /John.zip anstelle von / John-zip, was selbst für den Entwickler, der die Anwendung geschrieben hat, irreführend sein kann.

sdm350
quelle
Es ist wahrscheinlich ein Benutzername oder ein anderes Feld, das von Natur aus Punkte enthält. Das heißt, StackOverflow ersetzt alle Interpunktion (einschließlich .) durch Bindestriche in seinen Benutzer-URLs: P
jli
Ich bin darauf gestoßen, weil ich einen sicheren
Dateiabrufdienst habe
Aus dem offensichtlichen Grund abgelehnt: Es beantwortet die Frage nicht. Wenn ich könnte, würde ich keine Punkte in meiner URL erscheinen lassen. Sie werden angezeigt, weil die URL generiert wird und für Menschen lesbar sein muss.
mg30rg
2

Abhängig davon, wie wichtig es für Sie ist, Ihren URI ohne Abfrageringe zu halten, können Sie den Wert auch nur mit Punkten als Teil des Abfragerings und nicht als URI übergeben.

ZB funktioniert www.example.com/people?name=michael.phelps, ohne dass Einstellungen oder ähnliches geändert werden müssen.

Sie verlieren die Eleganz eines sauberen URI, aber für diese Lösung müssen keine Einstellungen oder Handler geändert oder hinzugefügt werden.

GR7
quelle
1

Wäre es möglich, Ihre URL-Struktur zu ändern?
Für das, woran ich arbeitete, habe ich eine Route ausprobiert

url: "Download/{fileName}"

aber es scheiterte mit allem, was eine hatte. drin.

Ich wechselte die Route zu

    routes.MapRoute(
        name: "Download",
        url:  "{fileName}/Download",
        defaults: new { controller = "Home", action = "Download", }
    );

Jetzt kann ich einfügen localhost:xxxxx/File1.doc/Downloadund es funktioniert gut.

Meine Helfer in der Ansicht haben es ebenfalls aufgegriffen

     @Html.ActionLink("click here", "Download", new { fileName = "File1.doc"})

das macht auch einen Link zum localhost:xxxxx/File1.doc/DownloadFormat.

Vielleicht könnten Sie ein nicht benötigtes Wort wie "/ view" oder eine Aktion am Ende Ihrer Route einfügen, damit Ihr Eigentum mit einem Nachlauf /wie " enden" kann/mike.smith/view

jonduncan05
quelle
1

Es ist so einfach wie das Ändern von path = " ." zu path = " ". Entfernen Sie einfach den Punkt im Pfad für ExensionlessUrlHandler-Integrated-4.0 in web.config.

Hier ist ein schöner Artikel https://weblog.west-wind.com/posts/2015/Nov/13/Serving-URLs-with-File-Extensions-in-an-ASPNET-MVC-Application

Jonny
quelle
Dieser Link führte mich zur besten Lösung für mein Problem (das Segment enthält ein "." - Zeichen, aber Clients folgen nicht mit einem "/"). Behoben durch diese Zeile in <system.webServer> von web.config - <modules runAllManagedModulesForAllRequests = "true" />
NickBeaugié
1

Versuchte alle oben genannten Lösungen, aber keine davon funktionierte für mich. Was funktioniert hat, war, dass ich .NET-Versionen> 4.5 deinstalliert habe, einschließlich aller mehrsprachigen Versionen. Schließlich fügte ich Stück für Stück neuere (nur auf Englisch) Versionen hinzu. Derzeit sind auf meinem System folgende Versionen installiert:

  • 2.0
  • 3.0
  • 3.5 4
  • 4.5
  • 4.5.1
  • 4.5.2
  • 4.6
  • 4.6.1

Und es funktioniert immer noch an diesem Punkt. Ich habe Angst, 4.6.2 zu installieren, weil es alles durcheinander bringen könnte.

Ich konnte also nur spekulieren, dass entweder 4.6.2 oder all diese nicht englischen Versionen meine Konfiguration durcheinander brachten.

Jokab
quelle
0

Als Lösung könnte auch in Betracht gezogen werden, in ein Format zu codieren, das kein Symbol enthält ., wie base64.

In js sollte hinzugefügt werden

btoa(parameter); 

In der Steuerung

byte[] bytes = Convert.FromBase64String(parameter);
string parameter= Encoding.UTF8.GetString(bytes);
Max Booreviy
quelle
0

Hinzufügen einer URL-Rewrite-Regel zum Web.config-Archiv. Das URL Rewrite-Modul muss bereits in IIS installiert sein. Verwenden Sie die folgende Umschreiberegel als Inspiration für Ihre eigenen.

<?xml version="1.0" encoding="utf-8"?>
<configuration>

<system.webServer>
  <rewrite>
    <rules>
      <rule name="Add trailing slash for some URLs" stopProcessing="true">
        <match url="^(.*(\.).+[^\/])$" />
          <conditions>
              <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
              <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
          </conditions>
          <action type="Redirect" url="{R:1}/" />
      </rule>
    </rules>
    </rewrite>
</system.webServer>

</configuration> 
Amadeus Sánchez
quelle
0

Überprüfen Sie außerdem (im Zusammenhang) die Reihenfolge Ihrer Handlerzuordnungen. Wir hatten eine .ashx mit einer .svc (zB /foo.asmx/bar.svc/path) im Pfad danach. Die .svc-Zuordnung war zuerst so 404 für den .svc-Pfad, der vor dem .asmx übereinstimmte. Ich habe nicht zu viel darüber nachgedacht, aber vielleicht würde sich die URL, die den Pfad codiert, darum kümmern.

stuartm9999
quelle
-3
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace WebApplication1.Controllers
{
    [RoutePrefix("File")]
    [Route("{action=index}")]
    public class FileController : Controller
    {
        // GET: File
        public ActionResult Index()
        {
            return View();
        }

        [AllowAnonymous]
        [Route("Image/{extension?}/{filename}")]
        public ActionResult Image(string extension, string filename)
        {
            var dir = Server.MapPath("/app_data/images");

            var path = Path.Combine(dir, filename+"."+ (extension!=null?    extension:"jpg"));
           // var extension = filename.Substring(0,filename.LastIndexOf("."));

            return base.File(path, "image/jpeg");
        }
    }
}
hamyari afarinesh
quelle
1
Wie beantwortet dies die Frage von OP? Möchtest du es bitte beschreiben?
Kayess
Es ist keine Lösung, es ist ein Hack, bei dem die Dateierweiterung in den URL-Pfad eingefügt werden muss (ohne Punkt), z. B. "~ / Image / jpg / cow", um die Datei "/ app_data / images / cow / jpg" abzurufen. - nicht die Lösung, die dieser Typ und alle anderen, die dies finden, brauchen.
Shaun Wilson