Маршрут по умолчанию в MVC {controller}/{action}/{id}
по большей части весьма полезен, так как может установить значение по умолчанию, если входящий URL-адрес не содержит параметр, но есть также способ указать действие по умолчанию для случая, когдадействие не существует на контроллере?
Чего я хочу добиться, так это иметь возможность иметь контроллеры с несколькими конкретными действиями, а затем собственный ловушку, которая использует URL для получения контента из базовой CMS.
Например, контроллер продуктов будет выглядеть примерно так:
public class ProductsController: Controller{
public ActionResult ProductInfo(int id){...}
public ActionResult AddProduct(){...}
public ActionResult ContentFromCms(string url){...}
}
Где маршрут по умолчанию будет обрабатывать /Products/ProductInfo/54
и т. Д., А URL запроса /Products/Suppliers/Acme
будет возвращать ContentFromCms("Suppliers/Acme");
(отправка URL какпараметр был бы лучше, но не нужен, и метод без параметров, в котором я получаю его из запроса, будет в порядке).
В настоящее время я могу придумать два возможных способа достижения этой цели:
Создатьновое ограничение, которое отражает над контроллером, чтобы увидеть, есть ли у него действие с заданным именем, и использовать его в маршруте {controller}/{action}/{id}
, что позволяетчтобы иметь более общий вызов, такой как {controller}/{*url}
.
Override HandleUnknownAction
на контроллере.
Первый подход выглядит так, как будто это был бы довольно окольный способ проверки этого, в то время как дляво-вторых, я недостаточно хорошо знаком с внутренностями MVC и Routing, чтобы знать, как действовать.
Обновление
Ответов не было, но я думал, что будуоставьте мое решение, если кто-нибудь найдет это в будущем, или чтобы люди предложили улучшения / лучшие способы.
Для контроллеров, которым я хотел иметь свой собственный вызов, я дал им интерфейс
interface IHasDefaultController
{
public string DefaultRouteName { get; }
System.Web.Mvc.ActionResult DefaultAction();
}
Iзатем получается из ControllerActionInvoker и переопределяет FindAction.Затем вызывается базовый FindAction, если базовый возвращает ноль, и контроллер снова реализует интерфейс, который я вызываю FindAction, с именем действия по умолчанию.
protected override ActionDescriptor FindAction(ControllerContext controllerContext, ControllerDescriptor controllerDescriptor, string actionName)
{
ActionDescriptor foundAction = base.FindAction(controllerContext, controllerDescriptor, actionName);
if (foundAction == null && controllerDescriptor.ControllerType.GetInterface("Kingsweb.Controllers.IWikiController") != null)
{
foundAction = base.FindAction(controllerContext, controllerDescriptor, "WikiPage");
}
return foundAction;
}
Поскольку я также хочу параметры из маршрутизации, я также заменяю RouteData в начале действия Action по умолчанию на контроллере
ControllerContext.RouteData = Url.RouteCollection[DefaultRouteName].GetRouteData(HttpContext);