【问题标题】:Why is the ASP.NET routing engine ignoring files?为什么 ASP.NET 路由引擎忽略文件?
【发布时间】:2013-09-01 15:18:46
【问题描述】:

我有一个实现IHttpHandlerIRouteHandler 的类:

  public class CustomHandler : IHttpHandler,IRouteHandler
  {
    public bool IsReusable
    {
      get { return false; }
    }

    public void ProcessRequest(HttpContext context)
    {
      context.Response.AddHeader("Content-Type", "text/plain");
      context.Response.Write("Hello World");
    }

    public IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
      return this;
    }
  }

在 Application_Start 方法中,我尝试使用路由注册我的处理程序:

Route route = new Route("dav/{*Pathinfo}", new CustomHandler());
RouteTable.Routes.Add(route);

在我用这种 URL 调用之前,一切都很酷:
- http://localhost:63428/dav/asdadsa
- http://localhost:63428/dav/asdadsa/asdasd
- http://localhost:63428/dav/asdadsa/a%20%20sdasd(网址中有空格)
但是,如果我尝试使用这些:
- http://localhost:63428/dav/asdadsa.docx
- http://localhost:63428/dav/asdads/a.docx
我的处理程序未调用,服务器返回 404。我认为通配符将匹配每个以 dav/ 开头的 url。
知道如何使带有扩展名的网址也与我的路线匹配吗?

更新:
我找到了这个page
它是从配置中设置的,而不是从后面的代码中设置的,但不必设置 runAllManagedModulesForAllRequests 设置,不幸的是,在我的原始示例中,路由值没有那么干净。
如果来这个问题寻求答案,也许有人会感兴趣。

【问题讨论】:

  • 不幸的是,该链接不能回答我的问题。第一种方法我想在 dav 段(解析和处理)之后处理整个 url。只有当我的网址末尾有扩展名时,我的 rount 才有效。

标签: asp.net asp.net-routing


【解决方案1】:

如果您将以下配置添加到您的 web.config 文件,那么您的路由也将包含文件。

<configuration>
  <system.webServer>
    <modules>
      <remove name="UrlRoutingModule-4.0" />
      <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="" />
      <!-- more -->
    </modules>
  </system.webServer>
</configuration>

另一种解决方案是添加&lt;modules runAllManagedModulesForAllRequests="true"&gt;,但这会产生开销,因为所有注册的 HTTP 模块都在每个请求上运行,而不仅仅是托管请求(例如 .aspx)。这意味着模块将在每个 .jpg .gif .css .html .pdf 等上运行。

您可以阅读更多关于不同路由设置的here

请记住,如果您要将特殊路由添加到现有路由,则必须先添加您的路由,否则它将不会被处理,如本例所示。

Route route = new Route("dav/{*Pathinfo}", new CustomHandler());
routes.Add(route);

routes.MapRoute(
  name: "Default",
  url: "{controller}/{action}/{id}",
  defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

这种方法的一个问题是,第一个路由定义会混淆系统中的 Html 助手,因此您不会再获得像 localhost/home/index 这样的好路由,而是localhost/dav?action=index&amp;controller=home。对此的解决方案是将第一条路由限制为仅对传入的路由请求有效。这可以通过创建RouteConstraint 并将其添加到RouteValueDictionary 中的路由定义来完成。

public class OnlyIncomingRequestConstraint : IRouteConstraint
{
    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        if (routeDirection == RouteDirection.IncomingRequest)
            return true;
        return false;
    }
}

然后您可以通过这种方式重新定义您的路由定义:

Route route = new Route("dav/{*Pathinfo}", new RouteValueDictionary(new { controller = new OnlyIncomingRequestConstraint() }), new CustomHandler());
routes.Add(route);

在此之后,您的默认路由应该会再次恢复正常。

【讨论】:

  • 首先它有效!不过我有点担心这个选项:msdn.microsoft.com/en-us/library/cc668201.ASPX#sectionToggle11 它独立于 ui,所以目前我的代码来自 webforms 应用程序。我不明白这一点:“当 runAllManagedModulesForAllRequests 为真时,mysite/myapp/home 之类的 URL 会转到 ASP.NET,即使 URL 上没有 .aspx、.mvc 或类似扩展名也是如此。”这个例子现在可以在没有设置的情况下工作。另一件事:“请注意,这会给请求增加一些开销。”最后。如何以编程方式设置?
  • 该引用仅表示所有路径都被发送到路由引擎。我已经稍微更新了我的示例,所以它不会增加额外的开销(好吧,反正不是那么多)......必须先做一些阅读。
  • 不能在开始时放置这种路由。它捕获所有 url 生成并提供这样的 url:localhost:50841/dav?action=Index&controller=Home
  • 检查答案底部的新更新。我想我解决了你的最后一个问题。
  • 很酷。即使我为文件生成 Url:@Url.RouteUrl("davReq",new { url = "a/b/c.doc" }) 唯一令人困惑的是永远不会调用 RouteConstraint。我在 Match 方法中设置了断点,我的代码从未停止过。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-13
  • 2012-04-30
  • 2022-08-16
  • 2014-07-10
  • 2014-02-12
  • 1970-01-01
相关资源
最近更新 更多