使用路由属性时设置Web api路由处理程序 [英] set web api route handler when using route attributes

查看:78
本文介绍了使用路由属性时设置Web api路由处理程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个自定义的路由处理程序女巫,我想在不同的控制器上使用.现在,让我的控制器使用此路由处理程序的唯一方法是像这样设置它

  RouteTable.Routes.MapHttpRoute(名称:"CustomRouteHandler",routeTemplate:"/custom/{controller}/{action}",默认值:new {id = RouteParameter.Optional,action = RouteParameter.Optional}).RouteHandler = new CustomRouteHandler(); 

我真的很想使用这样的路由属性

  [HttpGet][Route(Name ="GetCart")]公共购物车Get(){返回_repository.Get();} 

但是当我使用路由属性时,似乎无法弄清楚如何确保使用自定义路由处理程序.最好只使用路由属性,因此,如果我可以使用"RouteHandler"之类的属性,并且在这里指向我的"CustomRouteHandler",那将是完美的.

我是否可以使用这样的属性,或者可以某种方式将MapHttpRoute中的所有内容都指向"/Custom",然后从此处使用route属性,并使所有控制器具有自定义处理程序?

另一个选择可能是使我自己的属性成为一个控制器或方法,以使用我的自定义路由处理程序?

我正在尝试为开发人员提供一种非常清晰的方法,以了解该控制器或方法正在使用自定义路由处理程序,如果新开发人员应添加其他控制器,则可以仅使用"/custom"或"/custom"之类的特殊路由.使用属性.

任何想法都非常受欢迎.谢谢.

解决方案

不幸的是,由于某些限制,在纯 AttributeRouting 中这是不可能的:

当心!由于与Web API WebHost框架的集成问题,以下功能将不起作用:

匹配路线,自定义路线处理程序,querystring参数约束,子域路由,本地化应用于入站/出站URL,以及小写,附加前缀,等生成的路线.这些功能都必须等待vNext的Web API.

所以您只有三个选择.

1)以经典方式在 WebApiConfig.cs 中进行路由:

  config.Routes.MapHttpRoute(名称:"GetData",routeTemplate:"api/yourawesomecontroller/data",默认值:new {controller ="YourAwesomeController",action = nameof(YourAwesomeController.GetData)},约束:new {httpMethod = new HttpMethodConstraint(HttpMethod.Get)},处理程序:new YourCustomMessageHandler(){InnerHandler = new HttpControllerDispatcher(config)}); 

2)您也可以为所有请求注册 YourCustomMessageHandler ,并在处理程序本身内部实现路由过滤:

  class YourCustomMessageHandler:DelegatingHandler{受保护的覆盖异步任务< HttpResponseMessage>SendAsync(HttpRequestMessage请求,CancellationToken cancelToken){如果(request.Method == HttpMethod.Get&request.RequestUri.PathAndQuery.StartsWith("/api/yourawesomecontroller/data"))//...对请求的自定义处理...var response =等待base.SendAsync(request,cancelToken);//...响应的自定义处理...返回响应;}} 

3)最后一个选项是自定义路由属性:

 公共类MyRouteAttribute:属性{公共字符串Url {get;私人套装;}公共MyRouteAttribute(字符串url){网址=网址;}} 

您需要用它来装饰动作方法.但是在这种情况下,您需要像这样在自定义引导程序中注册选项1)中的路由:

  foreach(allControllerTypes中的var controllerType){var属性= System.ComponentModel.TypeDescriptor.GetAttributes(controllerType);var urlAttribute =(MyRouteAttribute)属性[typeof(MyRouteAttribute)];var controllerName = controllerType.Name.Replace("Controller",");config.Routes.MapHttpRoute(名称:controllerName,routeTemplate:urlAttribute.Url,处理程序:new YourCustomMessageHandler(){InnerHandler = new HttpControllerDispatcher(config)});} 

请注意,您必须显式指定 YourCustomMessageHandler InnerHandler ,以便将请求向下传递到其他处理程序和控制器的管道中.请参见Microsoft解释以获取详细信息.

I have a custom route handler witch i would like to use on different controllers. Right now the only way i get my controllers to use this route handler is to set it like this

RouteTable.Routes.MapHttpRoute(
    name: "CustomRouteHandler",
    routeTemplate: "/custom/{controller}/{action}",
    defaults: new { id = RouteParameter.Optional, action = RouteParameter.Optional }
    ).RouteHandler = new CustomRouteHandler();

I would really like to use route attributes like this

[HttpGet]
[Route(Name = "GetCart")]
public Cart Get()
{
    return _repository.Get();
}

But when i'm using route attributes and can't seem to figure out how to make sure i use the custom route handler. Preferable i would only use route attributes so if i could use a attribute like "RouteHandler" and here point to my "CustomRouteHandler" that would be perfect.

Is there a attribute i can use like this or could i in some way point everything in a MapHttpRoute into "/Custom" and then use route attributes from here and make all controllers have the custom handler?

Another option could maybe to make my own attribute that foreces a controller or method to use my custom route handler?

I'm trying to make a really crystal clear way for the developer to see that this controller or method is using a custom routehandler and if new developers should add another controller they could just use a special route like "/custom" or use a attribute.

Any ideas are very welcome. Thanks.

解决方案

Unfortunately, this is not possible in pure AttributeRouting due to some limitations:

Beware! Due to integration issues with the Web API WebHost framework, the following features will not work:

performance enhancements when matching routes, custom route handlers, querystring parameter constraints, subdomain routing, localization applied to inbound/outbound urls, and lowercasing, appending prefixes, etc to generated routes. These features all have to wait for vNext of the Web API.

So you have only three options.

1) Make routing in WebApiConfig.cs in classic way:

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) Also you may register YourCustomMessageHandler for all requests and implement route filtering inside handler itself:

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) The last option is a custom route attribute:

public class MyRouteAttribute : Attribute
{
    public string Url { get; private set; }

    public MyRouteAttribute (string url)
    {
        Url = url;
    }
}

which you need to decorate action methods with. But in this case you need to register routes like in option 1) in your custom bootstrapper like this:

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) }
    );
}

Note that you have to explicitly specify InnerHandler of YourCustomMessageHandler in order to pass requests down to pipeline to other handlers and controllers. See Microsoft explanation for details.

这篇关于使用路由属性时设置Web api路由处理程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆