Я попробовал решение в принятом ответе выше: используя стратегию URL шаблона Canonicalize Pattern, а затем добавив пользовательский 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, потому что как только метод действия был вызван в результате controller.Execute()
, id
параметр был нулевым внутри метода действия.
Я не знаю точно, почему это так, но поведение было таким, как если бы MVC не просматривал строку запроса для значений во время привязки модели.Таким образом, что-то в реализации ProcessRequest
в принятом ответе приводило к нарушению нормального процесса привязки модели или, по крайней мере, поставщика значения строки запроса.
Это прерыватель сделки, поэтому я взглянул на MVC по умолчаниюIHttpHandler (да, с открытым исходным кодом!): http://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/MvcHandler.cs
Я не буду притворяться, что я его уродил целиком, но ясно, что он делает ALOT больше в своей реализации ProcessRequest
, чем происходитв принятом ответе.
Итак, если все, что нам действительно нужно сделать, это убрать штрихи из наших входящих данных маршрута, чтобы MVC мог найти наши контроллеры / действия, зачем нам нужно реализовывать вонючий IHttpHandler?Мы не делаем!Просто вырвите штрихи в методе GetHttpHandler
из DashedRouteHandler
и передайте 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);
}
}