ASP.NET Core Web API:通过方法名进行路由?

17

我记得在ASP.NET Web API中,仅需要使用HTTP命令作为Web API REST方法的前缀(例如GetList() => HTTP GETDelete() => HTTP DELETE),就可以将传入调用适当地路由到相应的方法。

我还记得,在ASP.NET Web API中,参数匹配会自动进行,因此即使是Get(int id)Get(int id, string name)也可以自动适当地路由,而不需要任何属性。

public class MyController
{
  public ActionResult Get(int id) => ...

  public ActionResult Get(int id, string name) => ...

  public ActionResult DeleteItem(int id) => ...
}

这一切不都可以在ASP.NET Web API Core中获得吗?


1
这段代码完整吗?我认为你忘记从ControllerBase继承了。 - Leonardo
4个回答

42

您只需要将路由信息添加到您的控制器顶部。

使用api、控制器和操作指定路由:

[Route("api/[controller]/[action]")]
[ApiController]
public class AvailableRoomsController : ControllerBase
{
...
}

5
注意:api是可选的,但似乎是表示API网址的一般约定。 - Tony Abrams
非常感谢您! - zitrusire2520

1
我们既不能进行操作重载,也不能将操作名称作为HTTP动词的前缀。在ASP.NET Core中,路由的工作方式与ASP.NET Web Api不同。
但是,您可以简单地组合这些操作,然后在内部进行分支,因为如果您将所有参数作为查询字符串发送,则所有参数都是可选的。
[HttpGet]
public ActionResult<string> Get(int id, string name)
{
  if(name == null){..}
  else{...}
}

或者您需要使用属性路由来指定每个API,如果您发送路由数据:

[HttpGet("{id}")]       
public ActionResult<string> Get(int id)
{
    return "value";
}


[HttpGet("{id}/{name}")]
public ActionResult<string> Get(int id, string name)
{
    return name;
}

请参考属性路由Web Api Core 2 区分 GET 请求


0

aspnetcore webapi控制器不支持通过命名约定本地推断http动词,但允许您创建自己的约定并实现此行为。

创建您自己的约定。

public class MyConvention : IApplicationModelConvention
{
    public void Apply(ApplicationModel application)
    {
        foreach(var controller in application.Controllers)
        {
            foreach(var action in controller.Actions)
            {
                if (action.ActionName.StartsWith("Post"))
                {
                    action.Selectors.First().ActionConstraints.Add(new HttpMethodActionConstraint(new[]{ "POST" }));
                }
            }
        }
    }
}

然后在程序/启动项中注册它:

builder.Services.AddControllers(configure => configure.Conventions.Insert(0, new MyConvention()));

-1

这对于Core 2是可用的,但我知道如何做的方式是这样的

[Route("api/[controller]")]
[ApiController]
public class AvailableRoomsController : ControllerBase
{
    private readonly ApplicationContext _context;

    public AvailableRoomsController(ApplicationContext context)
    {
        _context = context;
    }

    // GET: api/AvailableRooms
    [HttpGet]
    public async Task<ActionResult<IEnumerable<AvailableRoom>>> GetAvailableRooms()
    {
        return await _context.AvailableRooms.ToListAsync();
    }


    // POST: api/AvailableRooms
    [HttpPost]
    public async Task<ActionResult<AvailableRoom>> PostAvailableRoom(AvailableRoom availableRoom)
    {
        _context.AvailableRooms.Add(availableRoom);
        await _context.SaveChangesAsync();

        return CreatedAtAction("GetAvailableRoom", new { id = availableRoom.Id }, availableRoom);
    }

    [HttpPut] .... etc
}

现在根据您指定的REST操作类型和发送到"api/AvailableRooms"的模型类型,如果存在适当的操作,它将被选择。

Visual Studio 2019和我认为2017可以自动创建这样的控制器,如果您右键单击Controllers文件夹,然后选择Add->Controller,然后选择"使用Entity Framework的API控制器带有操作",并选择其中一个模型类。


在同一个控制器中进行多个Get / Post操作时,会出现问题。路由将变得混乱。 - Tony Abrams
我应该说路由可能会混乱 - 如果有相似参数和方法类型的不同调用(例如:2个带有相同参数的GET请求)。 - Tony Abrams
没错,这种类型的控制器是为了执行CRUD操作而设计的,应该处理与模型相关联的5个动作之一,即获取、发布、放置、删除和带有ID的获取。我通常将它们与某些数据表框架结合使用,并使用带有[Route("api/[action]")]装饰的API控制器来处理更复杂的调用。 - Elias K.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接