web-dev-qa-db-fra.com

Points dans l'URL provoque 404 avec ASP.NET MVC et IIS

J'ai un projet qui nécessite que mes URL aient des points dans le chemin. Par exemple, je peux avoir une URL telle que www.example.com/people/michael.phelps

Les URL avec le point génèrent un 404. Mon routage convient. Si je passe en michaelphelps, sans le point, alors tout fonctionne. Si j'ajoute le point, j'obtiens une erreur 404. Le site exemple s'exécute sous Windows 7 avec IIS8 Express. URLScan n'est pas en cours d'exécution.

J'ai essayé d'ajouter ce qui suit à mon web.config:

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

Malheureusement, cela n'a pas fait de différence. Je viens de recevoir une erreur 404.0 Not Found.

Ceci est un projet MVC4 mais je ne pense pas que ce soit pertinent. Mon routage fonctionne bien et les paramètres que j'attends sont là, jusqu'à ce qu'ils incluent un point.

Que dois-je configurer pour pouvoir avoir des points dans mon URL?

291
Mark

Je travaille en modifiant les gestionnaires HTTP de mon site. Pour mes besoins, cela fonctionne bien et résout mon problème.

J'ai simplement ajouté un nouveau gestionnaire HTTP qui recherche des critères de chemin spécifiques. Si la demande correspond, elle est correctement envoyée à .NET pour traitement. Je suis beaucoup plus heureux avec cette solution que URLRewrite piratent ou activant RAMMFAR.

Par exemple, pour que .NET traite l'URL www.example.com/people/michael.phelps, ajoutez la ligne suivante à la configuration web de votre site dans l'élément system.webServer / handlers:

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

Éditer

D'autres publications suggèrent que la solution à ce problème est RAMMFAR ou RunAllManagedModulesForAllRequests. L'activation de cette option activera tous les modules gérés pour toutes les demandes. Cela signifie que les fichiers statiques tels que les images, les PDF et tout le reste seront traités par .NET quand ils n'auront pas besoin de l'être. Il vaut mieux laisser cette option, sauf si vous avez un cas spécifique.

365
Mark

Après quelques fouilles, j'ai constaté que RelaxUrlToFileSystemMapping ne fonctionnait pas du tout pour moi. Ce qui a fonctionné dans mon cas était de définir RAMMFAR sur true, la même chose est valable pour (.net 4.0 + mvc3) et (.net 4.5 + mvc4).

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

Soyez conscient lorsque vous définissez RAMMFAR sur true article de Hanselman sur RAMMFAR et ses performances

46
Tadeu Maia

Je crois que vous devez définir la propriété relaxedUrlToFileSystemMapping dans votre web.config. Haack a écrit un article à ce sujet il y a quelque temps (et il y en a d'autres SO posts posant le même type de question)

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

Je suis resté bloqué sur cette question pendant longtemps en suivant tous les remèdes sans succès.

J'ai remarqué que, lors de l'ajout d'une barre oblique [/] à la fin de l'URL contenant les points [.], L'erreur 404 n'était pas générée et que cela fonctionnait réellement.

J'ai finalement résolu le problème en utilisant un enregistreur d'URL tel que IIS URL Rewrite pour surveiller un modèle particulier et ajouter la barre oblique d'apprentissage.

Mon URL ressemble à ceci: /Contact/~firstname.lastname donc mon modèle est simplement: /Contact/~(.*[^/])$

J'ai eu cette idée de Scott Forsyth, voir le lien ci-dessous: http://weblogs.asp.net/owscott/handing-mvc-paths-with-dots-in-the-path

23
Leon van Wyk

Ajoutez simplement cette section à Web.config, et toutes les demandes de la route/{* pathInfo} seront gérées par le gestionnaire spécifié, même s'il existe des points dans pathInfo. (extrait de l'exemple Web.config de l'hôte ServiceStack MVC et de cette réponse https://stackoverflow.com/a/12151501/801189 )

Cela devrait fonctionner pour les deux IIS 6 & 7. Vous pouvez affecter des gestionnaires spécifiques à des chemins différents après la 'route' en modifiant path = "*" dans les éléments '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>
21
V.B.

Solution de contournement de MVC 5.0.

Beaucoup de réponses suggérées ne semblent pas fonctionner dans MVC 5.0.

Comme le problème des points 404 de la dernière section peut être résolu en fermant cette section par une barre oblique, voici le petit truc que j’utilise, propre et simple.

Tout en gardant un espace réservé pratique à votre vue:

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

ajoutez un peu de jquery/javascript pour faire le travail:

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

s'il vous plaît noter la barre oblique de fin, qui est responsable de la modification

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

dans

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

Réponse super facile pour ceux qui ne l'ont que sur une seule page Web. Modifiez votre lien action et un + "/" à la fin.

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

En fonction de l'importance pour vous de conserver votre URI sans chaîne de requête, vous pouvez également simplement transmettre la valeur avec des points dans le cadre de la chaîne de requête, et non de l'URI.

Par exemple. www.example.com/people?name=michael.phelps fonctionnera sans qu'il soit nécessaire de modifier les paramètres ni quoi que ce soit.

Vous perdez l'élégance d'avoir un URI propre, mais cette solution ne nécessite ni modification ni ajout de paramètres ou de gestionnaires.

2
GR7

Vous voudrez peut-être penser à utiliser des tirets au lieu de points.

Dans Pro ASP MVC 3 Framework , ils suggèrent ceci pour créer des URL conviviales:

Évitez les symboles, les codes et les séquences de caractères. Si vous voulez un séparateur de mots, utilisez un tiret (/ my-great-article). Les caractères de soulignement sont hostiles et les espaces codés par URL sont bizarres (/ mon + excellent + article) ou dégoûtants (/ mon% 20great% 20article).

Il mentionne également que les URL doivent être faciles à lire et à modifier pour les humains. Peut-être une raison de penser à utiliser un tiret au lieu d'un point provient également du même livre:

N'utilisez pas les extensions de nom de fichier pour les pages HTML (.aspx ou .mvc), mais utilisez-les pour des types de fichiers spécialisés (.jpg, .pdf, .zip, etc.). Les navigateurs Web ne se soucient pas des extensions de nom de fichier si vous définissez le type MIME de manière appropriée, mais les humains s’attendent toujours à ce que les fichiers PDF se terminent par .pdf

Ainsi, même si une période est toujours lisible par les humains (bien que moins lisible que les tirets, IMO), elle peut tout de même être un peu déroutante/trompeuse selon ce qui vient après la période. Et si quelqu'un a un nom de famille de zip? Ensuite, l'URL sera /John.Zip au lieu de/John-Zip, ce qui peut induire en erreur même pour le développeur qui a écrit l'application.

2
sdm350

J'ai essayé toutes les solutions ci-dessus, mais aucune d'entre elles n'a fonctionné pour moi. Ce qui a bien fonctionné, c’est que je désinstalle les versions .NET> 4.5, y compris toutes ses versions multilingues; Finalement, j'ai ajouté des versions plus récentes (en anglais seulement) pièce par pièce. En ce moment, les versions installées sur mon système sont les suivantes:

  • 2.0
  • 3.0
  • 3,5 4
  • 4,5
  • 4.5.1
  • 4.5.2
  • 4.6
  • 4.6.1

Et sa fonctionne toujours à ce stade. J'ai peur d'installer la version 4.6.2 car cela pourrait tout gâcher.

Je ne pouvais donc que supposer que la version 4.6.2 ou toutes ces versions non anglaises fouillaient ma configuration.

HTH quelqu'un.

1
jokab

Serait-il possible de changer votre structure d'URL?
Pour ce sur quoi je travaillais, j’ai essayé un itinéraire

url: "Download/{fileName}"

mais il a échoué avec tout ce qui avait un. en elle.

Je suis passé à

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

Maintenant, je peux mettre localhost:xxxxx/File1.doc/Download et cela fonctionne bien.

Mes assistants dans la vue l'ont aussi remarqué

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

cela crée également un lien vers le format localhost:xxxxx/File1.doc/Download.

Peut-être pourriez-vous mettre un mot inutile comme "/ view" ou une action à la fin de votre itinéraire afin que votre propriété puisse se terminer par un / final, quelque chose comme /mike.smith/view

1
jonduncan05

C'est aussi simple que de changer path = "." to path = "". Supprimez simplement le point dans le chemin pour ExensionlessUrlHandler-Integrated-4.0 dans web.config.

Voici un bel article https://weblog.west-wind.com/posts/2015/Nov/13/Serving-URLs-with-File-Extensions-in-an-ASPNET-MVC-Application

1
Jonny

Ajoutez une règle de réécriture d'URL à l'archive Web.config. Le module RL Rewrite est déjà installé dans IIS. Utilisez la règle de réécriture suivante comme source d’inspiration.

<?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
Amadeus Sánchez

En outre, vérifiez que les mappages de vos gestionnaires sont dans l’ordre. Nous avons eu un fichier .ashx avec un fichier .svc (par exemple, /foo.asmx/bar.svc/path) dans le chemin qui le suit. Le mappage .svc était d'abord ainsi 404 pour le chemin d'accès .svc qui correspondait avant le .asmx. Je n'ai pas trop réfléchi, mais peut-être que l'URL encodant le chemin prendrait soin de cela.

0
stuartm9999

J'ai pu résoudre ma version particulière de ce problème (je devais faire en sorte que /customer.html mette le chemin de/client, les barres obliques non autorisées non autorisées) en utilisant la solution à l'adresse https://stackoverflow.com/ a/13082446/1454265 et en remplaçant path = "*. html".

0
user1454265

En tant que solution, vous pourriez également envisager de coder dans un format ne contenant pas le symbole., en base64.

Dans js devrait être ajouté

btoa(parameter); 

Dans le contrôleur

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