首页 > 解决方案 > Asp.Core 2.1 [ApiController] 属性

问题描述

我有一段时间没有写 api(上次是在 asp.core 2.0 中)所以今天决定在 .core 2.1 版本中创建一个新的,不幸的是发现我的操作不像以前在以前的版本中那样工作。

几个小时后,我发现了这个问题的原因,[Route("api/[controller]")]并且因为[ApiController]没有它就无法工作,所以我对它们都发表了评论,并且每件事都很好。**那么任何人都可以解释我应该怎么做才能使此代码与'[ApiController]' unconnebt 和相同的操作 URL 调用一起工作?

   //[Route("api/[controller]")]
   //[ApiController]
    public class TestController : ControllerBase
    {
        [HttpGet("api/[controller]")]
        public string A1()
        {
            return "A1()";
        }

        [HttpGet]
        public string A2(int id)
        {
            return $"A2(int {id})";
        }

        [HttpGet]
        public string A3(string p1,string p2)
        {
            return $"A3(string {p1},string {p2})";
        }
        [Route("api/[controller]/A4/{id}")]
        [HttpGet]
        public string A4(int id)
        {
            return $"A4(int {id})";
        }
        [HttpGet("api/[controller]/A5/{id}")]
        public string A5(int id)
        {
            return $"A5(int {id})";
        }
    }

` 启动.css

   public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{……///code
      app.UseMvc(routes =>
                {
                    routes.MapRoute(
                        name: "default",
                        template: "api/{controller=Home}/{action=Index}/{id?}");
                });
    }
  1. https://localhost:5001/api/Test
  2. https://localhost:5001/api/Test/A2?id=1
  3. https://localhost:5001/api/Test/A2/1
  4. https://localhost:5001/api/Test/A3?p1=test&p2=test
  5. https://localhost:5001/api/Test/A4/1
  6. https://localhost:5001/api/Test/a5/1

Test1:我根据@chris-pratt 的回答进行了更改

   [Route("api/[controller]")]
    [ApiController]
    public class TestController : ControllerBase
    {
        [HttpGet("")]
        public string A1()
        {
            return "A1()";
        }

        [HttpGet("A2")]
        [HttpGet("A2/{id}")]
        public string A2([FromQuery]int id)
        {
            return $"A2(int {id})";
        }

        [HttpGet("A3")]
        public string A3([FromQuery]string p1, [FromQuery]string p2)
        {
            return $"A3(string {p1},string {p2})";
        }


        [HttpGet("A4")]
        public string A4([FromQuery]int id)
        {
            return $"A4(int {id})";
        }

        [HttpGet("A5")]
        public string A5([FromQuery]int id)
        {
            return $"A5(int {id})";
        }
    }

网址调用:

  1. 好的
  2. 好的
  3. id=0
  4. 好的
  5. 404
  6. 404

5&6现在是一样的

标签: asp.net-coreasp.net-core-webapiasp.net-core-2.1

解决方案


您的实际问题也不[Route("api/[controller]")]是。[ApiController]控制器类级别的[Route]属性为该控制器中的所有操作指定一个路由前缀。当你把它取下来时,你会回到 MVC 中的默认路由,/{controller}/{action}/{id?}.

同样重要的是要意识到使用属性路由会覆盖它所应用级别的默认路由。换句话说,如果您不应用Route到您的控制器,那么那里的操作将使用默认路由。如果您将Route属性或 HTTP 方法属性之一HttpGet应用于操作,那么只有该单个操作将使用自定义属性路由。但是,如果您确实将Route属性应用到控制器,则控制器中的所有操作都将使用属性路由,即使您没有显式应用属性也是如此。因此,为每个动作赋予其独特的路线非常重要。

您的第一个问题是您已将相同的路由应用于您应用于控制器的某些操作。最终结果是该动作的路线最终成为实际/api/test/api/test。您只需要指定前缀之后的路由部分,即[HttpGet("a1")]. 如果您希望它只是前缀,没有自己的额外路由段,那么您只需使用空路由,即[HttpGet("")]或只是[HttpGet]. 只需确保每个 HTTP 方法只执行一次。

现在与[ApiController]应用的不同之处在于,它会将默认绑定从 切换FromFormFromBody。但是,这仅适用于作为参数的引用类型,如类。像字符串这样的值类型将是未绑定的。显然,既然您想从查询字符串中获取这些内容,那么您应该添加[FromQuery]

    [HttpGet]
    public string A3([FromQuery]string p1, [FromQuery]string p2)

最后,您还有一堆重复的路线。正如我上面所概述的,不指定路由与在操作上指定空路由相同,这意味着您所拥有的只是控制器上设置的路由前缀。您需要确保每个操作都有其响应的唯一路由。例如,上面的方法实际上应该有类似的东西[HttpGet("a3")],然后会给你你想要的路线/api/test/a3?p1=test&p2=test


推荐阅读