Установить обработчик маршрута 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 для деталей.

Другие вопросы по тегам