I have a class that implements both IHttpHandler and IRouteHandler:

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

In the Application_Start method I try to register my handler with route:

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

Everything is cool until I call with this kind Url:
- http://localhost:63428/dav/asdadsa
- http://localhost:63428/dav/asdadsa/asdasd
- http://localhost:63428/dav/asdadsa/a%20%20sdasd (with space in the url)
But if I try with theese:
- http://localhost:63428/dav/asdadsa.docx
- http://localhost:63428/dav/asdads/a.docx
My handler not called and the server return with 404. I thought that the wildcard will match every url which start with dav/.
Any idea how to achive that the urls with extensions also match to my route?

UPDATE:
I found this page.
It's set from config, not from code behind but don't have to set the runAllManagedModulesForAllRequests settings and unfortunately don't get the route values so clean that in my original example.
Maybe somebody will be intrested if come to this question for answers.

有帮助吗?

解决方案

If you add the following configuration to your web.config file then your routing will include files as well.

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

One different solution is to add <modules runAllManagedModulesForAllRequests="true"> but that gives an overhead in that all your registered HTTP modules run on every request, not just managed requests (e.g. .aspx). This means modules will run on every .jpg .gif .css .html .pdf etc.

You can read more here about the different routing settings.

Just remember, if you're adding your special routing to the existing routing you have to add your routing first or it won't be processed, as in this example.

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

One problem with this approach is that the first route definition confuses Html helpers in your system so you won't any longer get nice routes like localhost/home/index but instead localhost/dav?action=index&controller=home. The solution to this is to restrict the first route to only be valid on incoming route requests. This can be done by creating a RouteConstraint and add it to the route definition in a 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;
    }
}

You can then redefine your route definition in this way:

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

After this your default routes should be back to normal again.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top