URL中的点导致ASP.NET MVC和IIS出现404


303

我有一个项目,要求我的URL路径中有点。例如,我可能有一个网址,例如www.example.com/people/michael.phelps

带有点的URL会生成404。我的路由很好。如果我通过michaelphelps,但没有点号,则表示一切正常。如果添加点,则会出现404错误。该示例站点在带有IIS8 Express的Windows 7上运行。URLScan未运行。

我尝试将以下内容添加到我的web.config中:

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

不幸的是,这并没有改变。我刚刚收到404.0找不到错误。

这是一个MVC4项目,但我认为这无关紧要。我的路由工作正常,期望的参数在那里,直到它们包含一个点。

我需要配置什么才能在URL中加点?


93
不敢相信我花了这么多时间在这上面。如果添加斜杠,则URL可以正常工作。例如,www.example.com / people / michael.phelps /,但是如果没有斜杠,IIS会抛出404错误。
标记

15
标记-这是因为IIS认为没有结尾斜杠,所以它应该被找到。添加斜杠的效果是...这不是真实文件。此外,下面的配置选项告诉IIS,如果它不是文件,请尝试将其路由。
汤米

将项目更新为mvc 4 + asp.net 4.5之后,我遇到了同样的问题。
塔德玛亚(Tadeu Maia)2012年

解决方法是使用IIS Rewrite将斜杠添加到我的URL中。
标记

4
这对我不起作用。该网址可以与“。”配合使用。在网址中输入,但在结尾时会出现错误
Arcadian

Answers:


379

我通过编辑站点的HTTP处理程序来完成此工作。对于我的需求,这很好,可以解决我的问题。

我只是添加了一个新的HTTP处理程序以查找特定的路径条件。如果请求匹配,则将其正确发送到.NET进行处理。我对URLRewrite hack或启用RAMMFAR的解决方案非常满意。

例如,要让.NET处理URL www.example.com/people/michael.phelps,请将以下行添加到您站点的web.config中的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" />

编辑

还有其他帖子建议解决此问题的方法是RAMMFARRunAllManagedModulesForAllRequests。启用此选项将为所有请求启用所有托管模块。这意味着静态文件(例如图像,PDF和其他所有文件)在不需要时将由.NET处理。除非您有特殊情况,否则最好不要使用此选项。


3
这是基于此答案的完整示例stackoverflow.com/a/16607685/801189
VB

10
使用[path =“ *”]添加此文件后,对任何静态文件(例如.css,.js)的所有请求都会失败。我有一个自定义路由,用于处理看起来像“ domain / ABCDE.FGHIJ ”的网址。我所有的静态文件都在我的/ Content目录中。有没有办法从中排除整个目录?将RAMMFAR设置为true可以,但是我想避免这种开销。
lamarant 2013年

2
本地IIS可以使用斜杠开头,但是IIS8仅理解没有第一个斜杠的路由。
Pavel Voronin

2
我遇到的问题与@lamarant相同……它阻止了静态文件。你知道为什么吗?在这里使用MVC4。
eestein 2014年

3
它可以在MVC5中使用,但是如果在路径的开头加上斜杠,则仅当路径紧接在主机名之后(与应用程序文件夹无关)时才可以使用。例如,路径/ people / *适用于www.example.com/people/michael.phelps,但不适用于www.example.com/app/people/michael.phelps。AFAIK无法建立相对于应用程序的路径。
霍根

46

经过一番摸索后,我发现对我来说,relaxedUrlToFileSystemMapping根本不起作用,在我的情况下有效的是将RAMMFAR设置为true,这对于(.net 4.0 + mvc3)和(.net 4.5 + mvc4)也是有效的。

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

在设置RAMMFAR时要特别注意Hanselman发表有关RAMMFAR和性能的文章


5
设置RAMMFAR时要注意...如果我使用此<modules runAllManagedModulesForAllRequests =“ true”>
Shanker Paudel,2013年

1
在原始海报的情况下,由于他使用的是IIS7及更高版本,因此不需要。这是默认设置,设置RAMMFAR确实使您付出了高昂的代价。参见msdn.microsoft.com/en-us/library/…–
理查德(Richard)

尽管这很有用,但这还不足以让我停止在MVC5 / IIS7中返回404。
克里斯·莫斯基尼

只是重申一下。您要避免启用此选项
Strake

即使有可能,也不要在实时站点上执行此操作。
NickG

27

我相信您必须在web.config中设置属性relaxedUrlToFileSystemMapping。 Haack不久前写了一篇有关此的文章(还有其他一些SO帖子问同样的问题)

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

编辑 从下面的注释中,.NET / IIS的更高版本可能要求将此system.WebServer元素包含在元素中。

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

2
这是我在mvc3 + .net4.0上拥有的,并且工作得很漂亮,但是在mvc4 + .net4.5上不再工作了。
塔德玛亚(Tadeu Maia)2012年

4
我尝试了relaxedUrlToFileSystemMapping,但没有成功。我认为它不适用于最新版本的MVC。
2013年

这使我能够捕获URL /WEB-INF./web.xml并将其重定向到自定义错误页面,而我尝试的其他许多方法均无效。
考林·史塔林

3
有趣。鉴于它对您不起作用,我将以为这对我不起作用...鉴于我使用的是.NET4.5的MVC4。但是宾果游戏还是成功了。就我而言,我只是有一个带有句点“。”的URL。作为最后一个字符。我得到了404,但这已经解决了。
PandaWood

他有安全感吗?
Paesano2000 '19

23

我在所有不同的补救措施上都停留了很长时间,但无济于事。

我注意到,在包含点[。]的URL末尾添加正斜杠[/]时,它没有引发404错误,并且确实有效。

我终于使用IIS URL Rewrite之类的URL重写器解决了该问题,以观察特定的模式并附加训练斜线。

我的网址看起来像这样:/Contact/~firstname.lastname,所以我的模式很简单:/Contact/~(.*[^/])$

我是从Scott Forsyth那里得到这个想法的,请参见下面的链接:http : //weblogs.asp.net/owscott/handing-mvc-paths-with-dots-in-the-path


这对我有用(MVC5)。上面的其他建议没有用,也不需要,只是一个斜杠。我将按照@ jonduncan05的建议在此处更改路线。
markau

谢谢你,莱昂 为我节省了一天。不确定所有关于web.config的东西都是人们在这里谈论的,但是添加结尾/是我需要的答案。就我而言,我可以控制服务器端控制器以及调用它的javascript,因此我刚刚更新了JavaScript,瞧!
Frog Pr1nce

21

只需将此部分添加到Web.config中,对path / {* pathInfo}的所有请求都将由指定的处理程序处理,即使pathInfo中有点也是如此。(摘自ServiceStack MVC主机Web.config示例,此答案为https://stackoverflow.com/a/12151501/801189

这对于IIS 6和7均适用。您可以通过修改“添加”元素中的path =“ *”,将特定处理程序分配给“路由”之后的不同路径。

  <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
注意runAllManagedModulesForAllRequests(RAMMFAR)的性能后果。这将为每个请求启用所有托管模块。静态文件(例如图像)可以由IIS直接处理,但这会通过每个模块进行处理,从而增加了每个请求的开销。
标记

@分数。是的,但是我相信如果我们使用<location>部分而不在主<system.webServer>部分中设置runAllManagedModulesForAllRequests,这只会影响路由请求...。
VB

@VB我认为仅处理程序就足够了,除非系统上有与.NET应该处理的URL匹配的文件。由于某种原因,RAMMFAR在<location>级别上不起作用,但是处理程序解决方案可以。
webXL 2013年

当您不希望MVC处理对指定路由的请求并添加路由时,需要@webXL <location>。IgnoreRoute(“ route / {* pathInfo}”); 然后,IIS将查看位置部分<location path =“ route”>,并在location部分中使用指定的处理程序,但是它将完全绕过MVC的路由和其他MVC的管道步骤。在我的项目中,没有该设置,ServiceStack api就无法工作。
VB

为什么不简单地添加处理程序工作?就我而言,我必须将RAMMFAR与处理程序一起添加。在这里寻找一些好的解释。:)
Aditya Patil 2015年

6

MVC 5.0解决方法。

许多建议的答案似乎在MVC 5.0中不起作用。

由于上一节中的404点问题可以通过用斜杠结束该部分来解决,因此这是我使用的小技巧,干净而简单。

在您保留方便的占位符的同时:

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

添加一些jquery / javascript以完成工作:

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

请注意结尾的斜杠,它负责更改

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

进入

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

5

对于仅在一个网页上具有此功能的用户而言,超级简单的答案。编辑您的操作链接,并在其末尾加上+“ /”。

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

为我解决了!简洁大方!最令人恼火的是,在开发过程中Windows 10上不带'/'时就可以使用,但是对于Windows 2012似乎是必需的。
Wim 10 Brink

2

您可能需要考虑使用破折号而不是句点。

Pro ASP MVC 3 Framework中,他们建议制作友好的URL:

避免使用符号,代码和字符序列。如果要使用单词分隔符,请使用破折号(/ my-great-article)。下划线是不友好的,URL编码的空格是奇怪的(/ my + great + article)或令人作呕的(/ my%20great%20article)。

它还提到,URL应该易于阅读和更改。也许考虑使用破折号而不是点的原因也来自同一本书:

不要对HTML页面(.aspx或.mvc)使用文件扩展名,而要对特殊的文件类型(.jpg,.pdf,.zip等)使用扩展名。如果您适当地设置MIME类型,Web浏览器将不关心文件扩展名,但是人们仍然希望PDF文件以.pdf结尾。

因此,尽管人类仍然可以理解一个句点(尽管它不如破折号(IMO)可读,但根据句点之后的情况,它可能仍会有些混乱/误导。如果某人姓zip怎么办?然后,该URL将是/John.zip而不是/ John-zip,即使对于编写该应用程序的开发人员,也可能会产生误导。


可能是用户名或其他固有包含点的字段。也就是说,StackOverflow用.其用户网址中的破折号替换了所有标点符号(包括):P
jli 2012年

我遇到此问题是因为我拥有安全的文件检索服务,该服务显然在route参数中包含文件名...
FlavorScape 2013年

出于明显的原因而被否决:它不能回答问题。如果可以的话,我不会让句点出现在我的URL中。之所以出现它们,是因为生成了URL,并且该URL必须是人类可读的。
mg30rg

2

根据保持URI不带查询字符串的重要性,您也可以仅将带点的值作为查询字符串(而不是URI)的一部分传递。

例如www.example.com/people?name=michael.phelps可以工作,而无需更改任何设置或任何内容。

您将失去拥有干净的URI的优雅,但是此解决方案不需要更改或添加任何设置或处理程序。


1

可以更改您的URL结构吗?
对于我正在从事的工作,我尝试了一条路线

url: "Download/{fileName}"

但是它失败了,并带有任何错误。在里面。

我将路线切换到

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

现在我可以放 localhost:xxxxx/File1.doc/Download,并且效果很好。

我在视图中的助手也选择了它

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

链接到 localhost:xxxxx/File1.doc/Download格式。

也许您可以在路线的末尾添加不需要的字样(例如“ / view”或“ action”),以便您的财产可以以/诸如/mike.smith/view


1

就像更改path =“一样简单。” 到路径=“ ”。只需在web.config中删除ExensionlessUrlHandler-Integrated-4.0路径中的点即可。

这是一篇不错的文章https://weblog.west-wind.com/posts/2015/Nov/13/Serving-URLs-with-File-Extensions-in-an-ASPNET-MVC-Application


该链接使我找到了解决问题的最佳方法(该段包含一个“。”字符,但客户端不会以“ /”结尾)。通过具有在<system.webServer> web.config中的这一行的固定- <模块runAllManagedModulesForAllRequests = “真”/>
NickBeaugié

1

尝试了以上所有解决方案,但没有一个对我有用。起作用的是我卸载了.NET版本> 4.5,包括其所有多语言版本;最终,我一步一步地添加了较新的版本(仅英语)。现在我的系统上安装的版本是这样的:

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

在这一点上,它仍然有效。恐怕要安装4.6.2,因为它可能会使所有内容混乱。

因此,我只能推测4.6.2或所有这些非英语版本都弄乱了我的配置。



0

作为解决方案,也可以考虑将编码编码为不包含符号的格式.,例如base64。

在js中应该添加

btoa(parameter); 

在控制器中

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

0

将URL重写规则添加到Web.config存档中。您需要已经在IIS中安装了URL重写模块。使用以下重写规则作为您自己的灵感。

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

另外,(相关)检查处理程序映射的顺序。我们在其后的路径中有一个带有.svc(例如/foo.asmx/bar.svc/path)的.ashx。.svc映射首先是404,而.svc路径在.asmx之前匹配。Hav没想太多,但也许对路径进行URL编码会解决这个问题。


-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
这如何回答OP的问题?介意描述一下吗?
kayess

这不是解决方案,而是一种黑客,需要将文件扩展名放置到uri路径中(不加句点),例如“〜/ Image / jpg / cow”以检索文件“ / app_data / images / cow / jpg”- -不是这个家伙和其他所有人都发现需要的解决方案。
肖恩·威尔逊
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.