I punti nell'URL causano 404 con ASP.NET mvc e IIS


303

Ho un progetto che richiede che i miei URL abbiano punti nel percorso. Ad esempio, potrei avere un URL come www.example.com/people/michael.phelps

Gli URL con il punto generano un 404. Il mio routing va bene. Se passo michaelphelps, senza il punto, allora tutto funziona. Se aggiungo il punto ottengo un errore 404. Il sito di esempio è in esecuzione su Windows 7 con IIS8 Express. URLScan non è in esecuzione.

Ho provato ad aggiungere quanto segue al mio web.config:

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

Sfortunatamente ciò non ha fatto differenza. Ho appena ricevuto un errore 404.0 Not Found.

Questo è un progetto MVC4 ma non credo sia rilevante. Il mio routing funziona bene e i parametri che mi aspetto sono lì, fino a quando non includono un punto.

Cosa devo configurare per poter avere punti nel mio URL?


93
Non riesco a credere di aver passato così tanto tempo su questo. L'URL funziona bene se aggiungo una barra finale. Ad esempio, www.example.com/people/michael.phelps/ tuttavia senza la barra finale IIS genera un errore 404.
Segna il

15
Mark: questo perché senza la barra finale, IIS pensa che sia un file che dovrebbe andare a cercare. L'aggiunta della barra ha l'effetto di ... questo non è un file reale. Inoltre, l'opzione di configurazione seguente indica a IIS che se non è un file, prova invece a instradarlo.
Tommy,

Sto riscontrando lo stesso problema dopo aver aggiornato il mio progetto a mvc 4 + asp.net 4.5.
Tadeu Maia,

Per aggirare il problema, sto usando IIS Rewrite per aggiungere la barra finale ai miei URL.
Segna il

4
Questo non funziona per me. L'URL funziona bene con "." all'interno dell'URL, ma alla fine genera un errore
Arcadian,

Risposte:


379

Ho funzionato modificando i gestori HTTP del mio sito. Per le mie esigenze questo funziona bene e risolve il mio problema.

Ho semplicemente aggiunto un nuovo gestore HTTP che cerca criteri di percorso specifici. Se la richiesta corrisponde, viene inviata correttamente a .NET per l'elaborazione. Sono molto più felice con questa soluzione che l'hacker URLRewrite o abilitando RAMMFAR.

Ad esempio, per far sì che .NET elabori l'URL www.example.com/people/michael.phelps aggiungi la seguente riga al web.config del tuo sito all'interno system.webServer / handlersdell'elemento:

<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" />

modificare

Ci sono altri post che suggeriscono che la soluzione a questo problema è RAMMFARo RunAllManagedModulesForAllRequests. Abilitando questa opzione verranno abilitati tutti i moduli gestiti per tutte le richieste. Ciò significa che i file statici come immagini, PDF e tutto il resto verranno elaborati da .NET quando non è necessario. Questa opzione è meglio lasciare a meno che tu non abbia un caso specifico per questo.


3
ecco un esempio completo stackoverflow.com/a/16607685/801189 basato su questa risposta
VB

10
dopo aver aggiunto questo con [path = "*"] tutte le richieste a qualsiasi file statico come .css, .js falliscono. Ho un percorso personalizzato che gestisce gli URL simili a questo " dominio / ABCDE.FGHIJ ". Tutti i miei file statici si trovano nella mia directory / Content. C'è un modo per escludere l'intera directory da questo? impostando RAMMFAR su true funziona, ma vorrei evitare questo sovraccarico.
Lamarant,

2
IIS locale funziona con l'avvio della barra, ma IIS8 comprende il percorso solo senza la prima barra.
Pavel Voronin,

2
Sto riscontrando lo stesso problema di @lamarant ... Blocca i file statici. Sai perché? Usando MVC4 qui.
est

3
Funziona in MVC5, ma se metti la barra all'inizio del percorso, funziona solo quando il percorso è immediatamente dopo il nome host (non è relativo alla cartella dell'app). Ad esempio path / people / * funzionerebbe per www.example.com/people/michael.phelps, ma non per www.example.com/app/people/michael.phelps. AFAIK non c'è modo di rendere il percorso relativo all'app.
Hogan,

46

Dopo aver frugato in giro ho scoperto che relaxedUrlToFileSystemMapping non ha funzionato affatto per me, ciò che ha funzionato nel mio caso è stato impostare RAMMFAR su true, lo stesso vale per (.net 4.0 + mvc3) e (.net 4.5 + mvc4).

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

Prestare attenzione quando si imposta RAMMFAR vero post Hanselman su RAMMFAR e le prestazioni


5
Fai attenzione quando imposti RAMMFAR ... C'è qualche perdita di prestazioni se uso questo <module runAllManagedModulesForAllRequests = "true">
Shanker Paudel,

1
Nel caso del poster originale non dovrebbe essere necessario, poiché utilizza IIS7 e versioni successive. Lì è l'impostazione predefinita e l'impostazione di RAMMFAR ti costa davvero exta. Vedi msdn.microsoft.com/en-us/library/…
Richard

Anche se questo è utile, questo non è stato sufficiente per ottenere dei periodi per smettere di restituire 404 secondi in MVC5 / IIS7 per me.
Chris Moschini,

Solo per ribadire. Vuoi evitare di attivare questa opzione
Strake,

Non farlo su un sito live, se possibile.
NickG

27

Credo che tu debba impostare la proprietà relaxedUrlToFileSystemMapping nel tuo web.config. Haack ha scritto un articolo su questo poco tempo fa (e ci sono altri post su SO che fanno gli stessi tipi di domande)

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

Modifica Dai commenti seguenti, le versioni successive di .NET / IIS potrebbero richiedere che questo sia presente system.WebServernell'elemento.

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

2
Questo è quello che ho avuto con mvc3 + .net4.0 e ha funzionato magnificamente, ma non funziona più con mvc4 + .net4.5.
Tadeu Maia,

4
Ho provato rilassatoUrlToFileSystemMapping senza successo. Non penso che funzioni con le versioni più recenti di MVC.
Mark

Questo mi ha permesso di prendere l'URL /WEB-INF./web.xml e reindirizzarlo a una pagina di errore personalizzata quando molti altri modi che ho provato non hanno funzionato.
Quentin-starin,

3
Interessante. Dato che non ha funzionato per te, stavo per presumere che non avrebbe funzionato per me ... dato che sono su MVC4 con .NET4.5. Ma il bingo, ha funzionato comunque. Nel mio caso avevo semplicemente un URL con un punto "." come l'ultimo personaggio. Stavo ottenendo 404 ma questo risolto.
PandaWood,

Il suo ha ripercussioni sulla sicurezza?
Paesano2000,

23

Mi sono bloccato su questo problema per molto tempo seguendo tutti i diversi rimedi senza successo.

Ho notato che quando si aggiunge una barra [/] alla fine dell'URL contenente i punti [.], Non viene generato un errore 404 e in realtà ha funzionato.

Alla fine ho risolto il problema utilizzando un riscrittore di URL come IIS URL Rewrite per cercare un modello particolare e aggiungere la barra di addestramento.

Il mio URL è simile al seguente: /Contact/~firstname.lastname quindi il mio modello è semplicemente: /Contact/~(.*[^/[)$

Ho avuto questa idea da Scott Forsyth, vedi link sotto: http://weblogs.asp.net/owscott/handing-mvc-paths-with-dots-in-the-path


Questo ha funzionato per me (MVC5). Altri suggerimenti sopra non funzionavano e non erano necessari, solo una barra finale. Cambierò i miei percorsi come suggerito da @ jonduncan05 qui .
Markau,

Grazie Leon. Mi ha salvato la giornata. Non sono sicuro di tutte le cose di web.config di cui parlano le persone qui intorno, ma l'aggiunta del finale / è stata la risposta di cui avevo bisogno. Nel mio caso, ho il controllo sul controller lato server e sul javascript che lo stava chiamando, quindi ho appena aggiornato JavaScript e voilà!
Frog Pr1nce,

21

Basta aggiungere questa sezione a Web.config e tutte le richieste alla route / {* pathInfo} saranno gestite dal gestore specificato, anche quando ci sono punti in pathInfo. (tratto dall'esempio Web.config dell'host MVC di ServiceStack e da questa risposta https://stackoverflow.com/a/12151501/801189 )

Questo dovrebbe funzionare sia per IIS 6 che per 7. È possibile assegnare gestori specifici a percorsi diversi dopo 'route' modificando path = "*" negli elementi 'add'

  <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>

2
Attenzione alle conseguenze sulle prestazioni di runAllManagedModulesForAllRequests (RAMMFAR). Ciò consentirà tutti i moduli gestiti per ogni richiesta. I file statici, come le immagini, possono essere elaborati direttamente da IIS ma ciò li elabora attraverso ogni modulo aggiungendo un overhead ad ogni richiesta.
Segna

@MarkS. sì, ma credo che ciò influirà solo sulla richiesta di route / ... se utilizziamo la sezione <location> e non impostiamo runAllManagedModulesForAllRequests nella sezione principale <system.webServer>.
VB,

@VB Penso che solo il gestore sia sufficiente, a meno che non ci siano file nel sistema che corrispondano a un URL che dovrebbe essere elaborato da .NET. E per qualche motivo, RAMMFAR non ha funzionato a livello di <location>, ma la soluzione del gestore ha funzionato.
webXL

@webXL <location> necessario quando non si desidera che MVC elabori le richieste su una route specificata e aggiunga route.IgnoreRoute ("route / {* pathInfo}"); Quindi IIS esaminerà la sezione della posizione <location path = "route"> e utilizzerà i gestori specificati nella sezione location, ma ignorerà completamente il routing di MVC e altri passaggi della pipeline di MVC. Nel mio progetto, ServiceStack api non funziona senza quella configurazione.
VB,

Perché semplicemente l'aggiunta del gestore non funziona? Nel mio caso, devo aggiungere RAMMFAR insieme al gestore. Alla ricerca di qualche buona spiegazione qui. :)
Aditya Patil,

6

Soluzione alternativa di MVC 5.0.

Molte delle risposte suggerite non sembrano funzionare in MVC 5.0.

Dato che il problema dei punti 404 nell'ultima sezione può essere risolto chiudendo quella sezione con una barra finale, ecco il piccolo trucco che uso, pulito e semplice.

Pur mantenendo un comodo segnaposto nella tua vista:

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

aggiungi un po 'di jquery / javascript per completare il lavoro:

<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>

si prega di notare la barra finale, che è responsabile del cambiamento

http://localhost:51003/GeoData/Manage/user@foo.com

in

http://localhost:51003/GeoData/Manage/user@foo.com/

5

Risposta semplicissima per coloro che hanno questo in una sola pagina web. Modifica il tuo actionlink e un + "/" alla fine di esso.

  @Html.ActionLink("Edit", "Edit", new { id = item.name + "/" }) |

Risolto per me! Semplice ed elegante! La cosa più irritante è che funziona senza "/" su Windows 10 durante lo sviluppo, ma per Windows 2012 sembra essere necessario.
Wim ten Brink,

2

Potresti pensare di usare i trattini anziché i punti.

In Pro ASP MVC 3 Framework suggeriscono ciò sulla creazione di URL intuitivi:

Evita simboli, codici e sequenze di caratteri. Se vuoi un separatore di parole, usa un trattino (/ my-great-article). I caratteri di sottolineatura sono ostili e gli spazi con codifica URL sono bizzarri (/ my + great + article) o disgustosi (/ my% 20great% 20article).

Indica anche che gli URL dovrebbero essere facili da leggere e modificare per gli umani. Forse un motivo per pensare all'utilizzo di un trattino anziché di un punto deriva anche dallo stesso libro:

Non utilizzare estensioni di file per pagine HTML (.aspx o .mvc), ma utilizzarle per tipi di file specializzati (.jpg, .pdf, .zip, ecc.). I browser Web non si preoccupano delle estensioni di file se si imposta il tipo MIME in modo appropriato, ma gli umani si aspettano ancora che i file PDF finiscano con .pdf

Quindi, mentre un periodo è ancora leggibile per gli umani (sebbene meno leggibile rispetto ai trattini, IMO), potrebbe comunque essere un po 'confuso / fuorviante a seconda di ciò che viene dopo il periodo. Cosa succede se qualcuno ha un cognome di zip? Quindi l'URL sarà /John.zip invece di / John-zip, qualcosa che può essere fuorviante anche per lo sviluppatore che ha scritto l'applicazione.


È probabilmente un nome utente o un altro campo che contiene intrinsecamente punti. Detto questo, StackOverflow sostituisce tutti i segni di punteggiatura (incluso .) con trattini negli URL dell'utente: P
jli

Ho riscontrato questo perché ho un servizio di recupero file sicuro che ovviamente contiene nomi di file nel parametro route ...
FlavorScape

Sottovalutato per l'ovvia ragione: non risponde alla domanda. Se potessi, non permetterei che i periodi vengano visualizzati nel mio URL. Appaiono perché l'URL viene generato e deve essere leggibile dall'uomo.
mg30rg

2

A seconda di quanto sia importante mantenere l'URI senza querystring, puoi anche passare il valore con i punti come parte della querystring, non l'URI.

Ad esempio www.example.com/people?name=michael.phelps funzionerà, senza dover modificare alcuna impostazione o altro.

Si perde l'eleganza di avere un URI pulito, ma questa soluzione non richiede la modifica o l'aggiunta di impostazioni o gestori.


1

Sarebbe possibile cambiare la struttura del tuo URL?
Per quello a cui stavo lavorando ho provato un percorso per

url: "Download/{fileName}"

ma fallì con tutto ciò che aveva un. dentro.

Ho cambiato il percorso verso

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

Ora posso inserire localhost:xxxxx/File1.doc/Downloade funziona benissimo.

Anche i miei aiutanti nella vista lo hanno raccolto

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

che crea anche un collegamento al localhost:xxxxx/File1.doc/Downloadformato.

Forse potresti mettere una parola non necessaria come "/ view" o azione alla fine del tuo percorso in modo che la tua proprietà possa terminare con un trailing /qualcosa come/mike.smith/view


1

È semplice come cambiare path = " ." al percorso = " ". Basta rimuovere il punto nel percorso per ExensionlessUrlHandler-Integrated-4.0 in web.config.

Ecco un bell'articolo https://weblog.west-wind.com/posts/2015/Nov/13/Serving-URLs-with-File-Extensions-in-an-ASPNET-MVC-Application


Questo link mi ha portato alla migliore soluzione al mio problema (il segmento contiene un carattere "." Ma i clienti non seguiranno un "/"). Risolto con questa riga in <system.webServer> di web.config - <modules runAllManagedModulesForAllRequests = "true" />
NickBeaugié

1

Ho provato tutte le soluzioni sopra, ma nessuna ha funzionato per me. Quello che ha funzionato è stato disinstallare le versioni .NET> 4.5, incluse tutte le sue versioni multilingue; Alla fine ho aggiunto le versioni più recenti (solo in inglese) pezzo per pezzo. In questo momento le versioni installate sul mio sistema sono queste:

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

E funziona ancora a questo punto. Ho paura di installare 4.6.2 perché potrebbe rovinare tutto.

Quindi ho potuto solo ipotizzare che la 4.6.2 o tutte quelle versioni non inglesi stessero rovinando la mia configurazione.



0

Come soluzione si potrebbe anche considerare la codifica in un formato che non contiene simboli ., come base64.

In js dovrebbe essere aggiunto

btoa(parameter); 

Nel controller

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

0

Aggiungi la regola di riscrittura URL all'archivio Web.config. Devi avere il modulo URL Rewrite già installato in IIS. Usa la seguente regola di riscrittura come ispirazione per il tuo.

<?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> 

0

Inoltre, (correlato) controlla l'ordine delle mappature del gestore. Avevamo un .ashx con un .svc (ad esempio /foo.asmx/bar.svc/path) nel percorso successivo. La mappatura .svc era prima quindi 404 per il percorso .svc che corrispondeva prima di .asmx. Non ci ho pensato troppo, ma forse l'URL che codifica il percorso si sarebbe occupato di questo.


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

1
In che modo risponde alla domanda di OP? Ti dispiace descriverlo per favore?
kayess,

non è una soluzione, è un trucco che richiede l'estensione del file da inserire nel percorso uri (senza punto) ad es. "~ / Image / jpg / cow" per recuperare il file "/ app_data / images / cow / jpg" - - Non è la soluzione che questo ragazzo e tutti gli altri trovano questo bisogno.
Shaun Wilson,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.