Установить обработчик маршрута web api при использовании атрибутов маршрута
У меня есть собственный обработчик маршрута, который я хотел бы использовать на разных контроллерах. Прямо сейчас единственный способ заставить мои контроллеры использовать этот обработчик маршрута - установить его так
RouteTable.Routes.MapHttpRoute(
name: "CustomRouteHandler",
routeTemplate: "/custom/{controller}/{action}",
defaults: new { id = RouteParameter.Optional, action = RouteParameter.Optional }
).RouteHandler = new CustomRouteHandler();
Я действительно хотел бы использовать атрибуты маршрута, как это
[HttpGet]
[Route(Name = "GetCart")]
public Cart Get()
{
return _repository.Get();
}
Но когда я использую атрибуты маршрута и не могу понять, как убедиться, что я использую собственный обработчик маршрута. Желательно, чтобы я использовал только атрибуты маршрута, поэтому, если бы я мог использовать такой атрибут, как "RouteHandler" и здесь указать на мой "CustomRouteHandler", это было бы идеально.
Есть ли атрибут, который я могу использовать таким образом, или я могу каким-то образом указать все в MapHttpRoute в "/Custom", а затем использовать атрибуты маршрута отсюда и сделать все контроллеры иметь собственный обработчик?
Может быть, другой вариант - сделать мой собственный атрибут, который предопределяет контроллер или метод для использования моего собственного обработчика маршрута?
Я пытаюсь сделать действительно кристально чистый способ для разработчика увидеть, что этот контроллер или метод использует собственный обработчик маршрутов, и если новые разработчики должны добавить другой контроллер, они могут просто использовать специальный маршрут, такой как "/custom" или использовать атрибут,
Любые идеи очень приветствуются. Благодарю.
1 ответ
К сожалению, это не возможно в чистом виде AttributeRouting
из-за некоторых ограничений:
Осторожно! Из-за проблем интеграции с платформой Web API WebHost следующие функции не будут работать:
повышение производительности при сопоставлении маршрутов, пользовательских обработчиков маршрутов, ограничений параметров строки запроса, маршрутизации поддоменов, локализации, применяемой к входящим / исходящим URL-адресам, и нижнему регистру, добавлению префиксов и т. д. к сгенерированным маршрутам. Все эти функции должны ждать vNext веб-API.
Таким образом, у вас есть только три варианта.
1) Сделать маршрутизацию в WebApiConfig.cs
классическим способом:
config.Routes.MapHttpRoute(
name: "GetData",
routeTemplate: "api/yourawesomecontroller/data",
defaults: new { controller = "YourAwesomeController", action = nameof(YourAwesomeController.GetData) },
constraints: new { httpMethod = new HttpMethodConstraint(HttpMethod.Get) },
handler: new YourCustomMessageHandler() { InnerHandler = new HttpControllerDispatcher(config) }
);
2) Также вы можете зарегистрироваться YourCustomMessageHandler
для всех запросов и реализации фильтрации маршрутов внутри самого обработчика:
class YourCustomMessageHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (request.Method == HttpMethod.Get &&
request.RequestUri.PathAndQuery.StartsWith("/api/yourawesomecontroller/data"))
// ... custom handling for request ...
var response = await base.SendAsync(request, cancellationToken);
// ... custom handling for response ...
return response;
}
}
3) Последний вариант - это пользовательский атрибут маршрута:
public class MyRouteAttribute : Attribute
{
public string Url { get; private set; }
public MyRouteAttribute (string url)
{
Url = url;
}
}
которым вы должны украсить методы действий. Но в этом случае вам нужно зарегистрировать маршруты, как в варианте 1), в свой собственный загрузчик, например:
foreach (var controllerType in allControllerTypes)
{
var attributes = System.ComponentModel.TypeDescriptor.GetAttributes(controllerType);
var urlAttribute = (MyRouteAttribute) attributes[typeof(MyRouteAttribute)];
var controllerName = controllerType.Name.Replace("Controller", "");
config.Routes.MapHttpRoute(
name: controllerName,
routeTemplate: urlAttribute.Url,
handler: new YourCustomMessageHandler() { InnerHandler = new HttpControllerDispatcher(config) }
);
}
Обратите внимание, что вы должны явно указать InnerHandler
из YourCustomMessageHandler
чтобы передавать запросы в конвейер другим обработчикам и контроллерам. См. Объяснение Microsoft для деталей.