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