我在上面接受的答案中尝试了解决方案:使用 Canonicalize Pattern url 策略,然后还添加了一个自定义 IRouteHandler,然后返回一个自定义 IHttpHandler。它大部分起作用了。这是我发现的一个警告:
使用典型的{controller}/{action}/{id}默认路由,一个名为CatalogController的控制器,里面有一个action方法如下:
ActionResult QuickSelect(string id){ /*do some things, access the 'id' parameter*/ }
我注意到对“/catalog/quick-select/1234”的请求运行良好,但是对 /catalog/quick-select?id=1234 的请求是 500'ing,因为一旦由于 @ 调用了操作方法987654325@,id 参数在 action 方法中为空。
我不知道为什么会这样,但是这种行为就像 MVC 在模型绑定期间没有查看查询字符串中的值一样。因此,在接受的答案中,关于 ProcessRequest 实现的一些事情是搞砸了正常的模型绑定过程,或者至少是查询字符串值提供程序。
这是一个交易破坏者,所以我看了一下默认的 MVC IHttpHandler(耶开源!):http://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/MvcHandler.cs
我不会假装我已经完全理解了它,但很明显,它在实现ProcessRequest 时所做的比在接受的答案中所做的要多得多。
所以,如果我们真正需要做的就是从传入的路由数据中去除破折号,以便 MVC 可以找到我们的控制器/动作,为什么我们需要实现一个完整的臭名昭著的 IHttpHandler?我们没有!只需撕掉DashedRouteHandler 的GetHttpHandler 方法中的破折号,然后将requestContext 传递给开箱即用的MvcHandler,这样它就可以执行252 行魔术,而您的路由处理程序不必返回一个二流的 IHttpHandler。
tl:dr; - 这是我所做的:
public class DashedRouteHandler : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
requestContext.RouteData.Values["action"] = requestContext.RouteData.GetRequiredString("action").Replace("-", "");
requestContext.RouteData.Values["controller"] = requestContext.RouteData.GetRequiredString("controller").Replace("-", "");
return new MvcHandler(requestContext);
}
}