属性路由ASP Core 3.0

时间:2019-12-14 22:22:48

标签: asp.net-core attributerouting

如何使用属性路由指定到以下API端点的路由?

返回的产品对象具有一些属性以及“商店”和“制造商”字段,分别包含null或“商店”和“制造商”对象。


    [Route("api/[controller]")]
    [ApiController]
    public class ProductsController : ControllerBase {


        [HttpGet ("")]
        public async Task<ActionResult<IEnumerable<Product>>> Get(
            bool stores = false, int storeId = 0,
            bool manufacturers = false, int manufacturerId = 0
        ) {

            // Default - returns all Products 
            // stores = true will set Product.Store = to the store object
            // storeId = 1 will filter Products to those in Store 1
            // manufacturer = true will st Product.Manufacturer to a manufacturer object
            // manufacturerId = 1 will filter Product to those produced by manufacturer 1

            var products = await _ctx.GetProducts(
                stores, storeId, 
                manufacturers, manufacturerId
            );
            return products.ToList();
        }

我希望有一些可读的路径来访问和适当地设置参数。

  • [HttpGet ("")]

    • /api/Products返回带有Store和Manufacturer = null的对象。这是理想的。
    • ("")单独使用时并不需要,但是如果我添加其他路线,则是必需的。
  • [Route("{stores=false}/{storeId=0})]

    • /api/Products/true返回带有商店已填充且制造商= null的产品对象。很好
    • /api/Products/true/1在商店1上的过滤器也不错。
    • 但这是一个愚蠢的网址(是真的吗?-是产品,商店还是制造商?)
  • [Route("Stores/{storeId?})]

    • /api/Products/Stores/1使store = false,尽管在Store 1上进行了过滤,但不包括store对象。路径数据中没有“商店”。它在Request.Path中,但我不想去那里。
    • /api/Products/Stores?storeId=1不起作用。 Request.QueryString.Value =?storeId = 1,但不会绑定到我的storeId参数。

我可以继续描述我的其他实验,但是可以说,没有一个给我想要的结果。我认为我对属性路由有误解,但也许并不是为了执行我想做的事情。

我想我想看到的是用查询字符串(如

)修改单个网址
  • /api/Products?stores=true&manufacturerId=1获取具有制造商1或
  • 生产的具有商店信息的产品
  • /api/Products?storeId=1,stores=true,manufacturers=true获取有关商店1中产品的完整详细信息

或者,也可以

  • /api/Products/Stores/1获取具有商店1中商品的商店信息的商品
  • /api/Products/Stores/Manufacturers/1获取包含制造商1生产的项目的商店和制造商信息的项目

实际上,我愿意接受任何可读的URL架构。

谢谢!

1 个答案:

答案 0 :(得分:0)

我会重新设计您的API控制器。如果您为自己的操作指定一些有意义的名称而不是Get()

我还将创建一个服务,该服务具有提供所请求产品并替换_ctx

的逻辑
    // Default - returns all Products 
    [HttpGet ("")]
    public async Task<ActionResult<IEnumerable<Product>>> GetAllProducts()
    {
        var products = await _ctx.GetAllProducts();
        return products.ToList();
    }

    // stores = true will set Product.Store = to the store object
    // storeId = 1 will filter Products to those in Store 1
    [HttpGet ("Stores/{storeId?}")]
    public async Task<ActionResult<IEnumerable<Product>>> GetProductsByStore(int? storeId)
    {
        if (storeId.HasValue)
        {
            // get products by store id
            products = await _ctx.GetProductsByStoreId(storeId);
        }
        else
        {
             products = await _ctx.GetProductsByCurrentStore(); // just a suggestion I 
         have no idea what you mean by saying "..set Product.Store = to the store object"
        }

        return products.ToList();
    }

    // manufacturer = true will st Product.Manufacturer to a manufacturer object
    // manufacturerId = 1 will filter Product to those produced by manufacturer 1
    [HttpGet ("Manufacturers/{manufacturerId?}")]
    public async Task<ActionResult<IEnumerable<Product>>> GetProductsByManufacturer(int? manufacturerId)
    {
        if (manufacturerId.HasValue)
        {
            products = await _ctx.GetProductsByManufacturerId(manufacturerId);
        }
        else
        {
            products = await _ctx.GetProductsByManufacturer();
        }

        return products.ToList();
    }