具有相同路由前缀 ASP.NET Web Api 的多个控制器类型 [英] Multiple Controller Types with same Route prefix ASP.NET Web Api

查看:23
本文介绍了具有相同路由前缀 ASP.NET Web Api 的多个控制器类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以将 GET 和 POST 分成不同的 API 控制器类型并使用相同的路由前缀访问它们?

Is it possible to separate GETs and POSTs into separate API Controller types and accessing them using the same Route Prefix?

这是我的控制器:

[RoutePrefix("api/Books")]
public class BooksWriteController : EventStoreApiController
{
    [Route("")]
    public void Post([FromBody] CommandWrapper commandWrapper){...}
}

[RoutePrefix("api/Books")]
public class BooksReadController : MongoDbApiController
{
    [Route("")]
    public Book[] Get() {...}

    [Route("{id:int}")]
    public Book Get(int id) {...}
}

推荐答案

Web API (1.x-2.x) 不支持在不同控制器上具有相同路径的多个属性路由.结果是 404,因为所有路由都匹配多个控制器,此时 Web API 会认为结果不明确.

Web API (1.x-2.x) does not support multiple attribute routes with the same path on different controllers. The result is a 404, because all the route matches more than one controller and at that point Web API will consider the result ambiguous.

请注意,MVC Core 确实支持此场景注意:MVC Core 服务作为 MVC &网络 API.

Note that MVC Core does support this scenario note: MVC Core serves as both MVC & Web API.

如果您选择使用 Web API 2.11(或更新版本),您可以为每个控制器的 http 方法创建路由约束,并使用它代替内置的路由属性.下面的示例显示您可以使用 RoutePrefix 或直接使用 Routes(如 kmacdonald 的回答).

If you choose to use Web API 2.11 (or newer) you can create a route constraint for the http method per controller and use it instead of the built in Route Attribute. The sample below shows that you can use RoutePrefix or directly Routes (like kmacdonald's answer).

using System.Collections.Generic;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Routing;

public class BooksWriteController : ApiController
{
    [PostRoute("api/Books")]
    public void Post() { }
}

[RoutePrefix("api/books")]
public class BooksReadController : ApiController
{
    [GetRoute]
    public void Get() { }

    [GetRoute("{id:int}")]
    public void Get(int id) { }
}

这两个类简化了约束路由属性的使用

These two classes simplify the use of the constraint route attribute

class GetRouteAttribute : MethodConstraintedRouteAttribute
{
    public GetRouteAttribute(string template) : base(template ?? "", HttpMethod.Get) { }
}

class PostRouteAttribute : MethodConstraintedRouteAttribute
{
    public PostRouteAttribute(string template) : base(template ?? "", HttpMethod.Post) { }
}

这个类允许向生成的路由添加约束

This class allows adding constraints to the route generated

class MethodConstraintedRouteAttribute : RouteFactoryAttribute
{
    public MethodConstraintedRouteAttribute(string template, HttpMethod method)
        : base(template)
    {
        Method = method;
    }

    public HttpMethod Method
    {
        get;
        private set;
    }

    public override IDictionary<string, object> Constraints
    {
        get
        {
            var constraints = new HttpRouteValueDictionary();
            constraints.Add("method", new MethodConstraint(Method));
            return constraints;
        }
    }
}

这只是一个标准的路由约束,尼特:你可能想要缓存约束对象以减少分配.

This is just a standard route constraint, nit: you may want to cache the constraints object to reduce allocations.

class MethodConstraint : IHttpRouteConstraint
{
    public HttpMethod Method { get; private set; }

    public MethodConstraint(HttpMethod method)
    {
        Method = method;
    }

    public bool Match(HttpRequestMessage request,
                      IHttpRoute route,
                      string parameterName,
                      IDictionary<string, object> values,
                      HttpRouteDirection routeDirection)
    {
        return request.Method == Method;
    }
}

这篇关于具有相同路由前缀 ASP.NET Web Api 的多个控制器类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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