RESTful API для именования конечных точек - PullRequest
1 голос
/ 02 апреля 2019

Я работаю над ядром asp.net core 2.2, предоставляющим RESTful API.

Текущая реализация работает нормально (дополнительный код удален для ясности):

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));
        }
    }
}

Один метод API отлично работает с URL https://localhost:5001/Users?userId=4AF29C4A-282A-4FB8-8691-9D44398A97F2

Теперь я хотел бы добавить второй метод:

[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));
}

Что приведет к URL-адресу https://localhost:5001/Users?teamId=4AF29C4A-282A-4FB8-8691-9D44398A97F2 (обратите внимание, что параметр является идентификатором команды вместо идентификатора пользователя по сравнению с первым вызовом).

При тестировании с 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)

Вопросы:
- Это проблема с SwaggerUI? Значит, иначе контроллер будет работать?
- Должны ли пользователи или контроллер команд раскрыть метод, чтобы получить всех пользователей команды? Мы запрашиваем идентификатор команды и возвращаем пользователей.
- Если он остается в контроллере «Пользователи», каков «лучший» способ иметь уникальные конечные точки?

Ответы [ 4 ]

1 голос
/ 02 апреля 2019

Я бы поместил его в Teams контроллер и получил бы его, используя маршрут, подобный /teams/1/users - где 1 - идентификатор команды.Это больше "отдых" :).Вам нужно будет аннотировать действие контроллера Teams с помощью [Route("{teamId}/users")].

Однако, если вы хотите сохранить его в контроллере Users, аннотируйте действие команд с помощью [Route("some-action-name/{teamId}")] и получите доступ к нему с помощью users/some-action-name/{teamId}

1 голос
/ 02 апреля 2019

вы можете дать Attribute Routing попытку, вот что я имею в виду

[HttpGet("/{userId}")]
public async Task<IActionResult> GetByUserId(Guid userId)

[HttpGet("/{teamId}")]
public async Task<IActionResult> GetByTeamId(Guid teamId)

[HttpGet("/{teamId}")] определяет новый route с параметром teamId

1 голос
/ 02 апреля 2019
you need to provide action name in your url.which is unique path

нравится https://localhost:5001/Users/GetByTeamId?teamId=4AF29C4A-282A-4FB8-8691-9D44398A97F2

0 голосов
/ 02 апреля 2019

Попробуйте добавить действие в свой атрибут маршрута, не забудьте добавить имя действия в ваш 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));
    }
  }
} 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...