[英]RESTful API endpoint naming
I'm working on a asp.net core 2.2 backend exposing a RESTful API. 我正在开发一个asp.net核心2.2后端暴露RESTful API。
The current implementation works fine (additional code removed for clarity): 当前实现工作正常(为清晰起见,删除了其他代码):
namespace Sppd.TeamTuner.Controllers
{
[Authorize]
[ApiController]
[Route("[controller]")]
public class UsersController : ControllerBase
{
private readonly ITeamTunerUserService _userService;
private readonly ITokenProvider _tokenProvider;
private readonly IAuthorizationService _authorizationService;
private readonly IMapper _mapper;
public UsersController(ITeamTunerUserService userService, ITokenProvider tokenProvider, IAuthorizationService authorizationService, IMapper mapper)
{
_userService = userService;
_tokenProvider = tokenProvider;
_authorizationService = authorizationService;
_mapper = mapper;
}
[HttpGet]
public async Task<IActionResult> GetByUserId(Guid userId)
{
// TODO: secure this call
var user = _userService.GetByIdAsync(userId);
return Ok(_mapper.Map<UserDto>(await user));
}
}
}
The single API method works fine with URL https://localhost:5001/Users?userId=4AF29C4A-282A-4FB8-8691-9D44398A97F2 单个API方法适用于URL https:// localhost:5001 / Users?userId = 4AF29C4A-282A-4FB8-8691-9D44398A97F2
Now I would like to add a second method: 现在我想添加第二种方法:
[HttpGet]
public async Task<IActionResult> GetByTeamId(Guid teamId)
{
// TODO: secure this call
var users = _userService.GetByTeamIdAsync(teamId);
return Ok(_mapper.Map<IEnumerable<UserDto>>(await users));
}
Which would result in URL https://localhost:5001/Users?teamId=4AF29C4A-282A-4FB8-8691-9D44398A97F2 (note that parameter is teamId instead of userId compared to first call). 这将导致URL https:// localhost:5001 / Users?teamId = 4AF29C4A-282A-4FB8-8691-9D44398A97F2 (请注意,与第一次调用相比,参数是teamId而不是userId)。
When testing with SwaggerUI, the page doesn't load and following exception is being shown: 使用SwaggerUI进行测试时,页面不会加载并显示以下异常:
An unhandled exception has occurred while executing the request.
System.NotSupportedException: HTTP method "GET" & path "Users" overloaded by actions - Sppd.TeamTuner.Controllers.UsersController.GetByUserId (Sppd.TeamTuner),Sppd.TeamTuner.Controllers.UsersController.GetByTeamId (Sppd.TeamTuner). Actions require unique method/path combination for Swagger 2.0. Use ConflictingActionsResolver as a workaround
at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.CreatePathItem(IEnumerable`1 apiDescriptions, ISchemaRegistry schemaRegistry)
at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.CreatePathItems(IEnumerable`1 apiDescriptions, ISchemaRegistry schemaRegistry)
at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GetSwagger(String documentName, String host, String basePath, String[] schemes)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.MigrationsEndPointMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.Invoke(HttpContext httpContext)
at Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.Invoke(HttpContext httpContext)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
Questions: 问题:
- Is this a SwaggerUI issue? - 这是一个SwaggerUI问题吗? Meaning would the controller work otherwise?
否则控制器会起作用吗?
- Should the Users or the Teams controller expose the method to get all team users? - 用户或团队控制器是否应公开该方法以获取所有团队用户? We query by team id and return users.
我们按团队ID查询并返回用户。
- If it remains in the Users controller, what's the 'best' way to have unique endpoints? - 如果它仍然在用户控制器中,那么拥有唯一端点的“最佳”方式是什么?
you need to provide action name in your url.which is unique path
像这样https:// localhost:5001 / Users / GetByTeamId?teamId = 4AF29C4A-282A-4FB8-8691-9D44398A97F2
you can give Attribute Routing
a try, here's what I mean 你可以试试
Attribute Routing
,这就是我的意思
[HttpGet("/{userId}")]
public async Task<IActionResult> GetByUserId(Guid userId)
[HttpGet("/{teamId}")]
public async Task<IActionResult> GetByTeamId(Guid teamId)
[HttpGet("/{teamId}")]
defines a new route
with param teamId
[HttpGet("/{teamId}")]
使用param teamId
定义一个新route
I would put it in Teams
controller and receive it by using route like /teams/1/users
- where 1 is team id. 我会把它放在
Teams
控制器中并通过使用/teams/1/users
这样的路由接收它 - 其中1是团队ID。 This is more "rest" :). 这更“休息”:)。 You will need to annotate your Teams controller action with
[Route("{teamId}/users")].
您需要使用
[Route("{teamId}/users")].
注释您的团队控制器操作[Route("{teamId}/users")].
However, if you want to keep it in the Users controller then annotate teams action with [Route("some-action-name/{teamId}")]
and access it by using users/some-action-name/{teamId}
但是,如果要将其保留在Users控制器中,则使用
[Route("some-action-name/{teamId}")]
注释团队操作,并使用users/some-action-name/{teamId}
访问它
Try to add action to your route attribute , don't forgot to add action name to your url 尝试向您的路线属性添加操作,不要忘记将动作名称添加到您的网址
namespace Sppd.TeamTuner.Controllers
{
[Authorize]
[ApiController]
[Route("[controller]/[Action]")]
public class UsersController : ControllerBase
{
private readonly ITeamTunerUserService _userService;
private readonly ITokenProvider _tokenProvider;
private readonly IAuthorizationService _authorizationService;
private readonly IMapper _mapper;
public UsersController(ITeamTunerUserService userService, ITokenProvider tokenProvider, IAuthorizationService authorizationService, IMapper mapper)
{
_userService = userService;
_tokenProvider = tokenProvider;
_authorizationService = authorizationService;
_mapper = mapper;
}
[HttpGet]
public async Task<IActionResult> GetByUserId(Guid userId)
{
// TODO: secure this call
var user = _userService.GetByIdAsync(userId);
return Ok(_mapper.Map<UserDto>(await user));
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.