Url.Action возвращает неправильный URL-адрес для действия webapi с помощью Route attrubute - PullRequest
0 голосов
/ 30 декабря 2018

У меня проблема с поведением Url.Action ();

У меня есть webapi, где все контроллеры требуют явного атрибута префикса маршрута, а все действия требуют атрибута маршрута.

Iзарегистрировать мои маршруты в WebApiConfig.cs

 var constraintResolver = new DefaultInlineConstraintResolver()
            {
                ConstraintMap =
                {
                    ["apiVersion"] = typeof( ApiVersionRouteConstraint )
                }
            };
            config.MapHttpAttributeRoutes(constraintResolver);

В настоящее время я закомментировал строку ниже, но (потому что) это не изменило неправильное поведение:

  //config.Routes.MapHttpRoute(name: "DefaultApi", 
 //routeTemplate: "api/v{version:apiVersion}/{controller}/{action}/{id}", defaults: new {id = RouteParameter.Optional});

Мой контроллер выглядитследующим образом:

 [RoutePrefix("api/v{version:apiVersion}/programs")]
 public class ProgramsController : ApiController
 {
    [HttpGet, Route("{telemetryKey}/versions/latest")]
    public async Task<LatestVersionResponse> GetLatestVersionInfo(Guid telemetryKey)
    {
        // serious business logic
    }

 }

Я ожидаю, что '@Url.Action("GetLatestVersionInfo", "Programs", new { telemetryKey = Guid.Parse("43808405-afca-4abb-a92a-519489d62290") })'

должен вернуть /api/v1/programs/43808405-afca-4abb-a92a-519489d62290/versions/latest

однако вместо этого я получу /Programs/GetLatestVersionInfo?telemetryKey=43808405-afca-4abb-a92a-519489d62290.Итак, мой префикс и атрибуты маршрута игнорируются.

Swagger правильно обнаруживает мои маршруты, и я могу проверить, что запросы на ожидаемые маршруты работают нормально - только Url.Action () сбит с толку.

enter image description here

Что может быть не так ...?

Ответы [ 2 ]

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

Что ж, похоже, было несколько неправильных вещей.

Неправильный помощник: Я должен использовать Url.HttpRouteUrl для генерации ссылок API из вида бритвы (Url.Linkдля генерации ссылки из контроллеров API)

Конфликт с aspnet-api-versioning библиотека По какой-то причине (возможно, ошибка?) префикс, который я имею на контроллере (переменная apiVersion)) нарушает механизм вспомогательного URL-адреса.

На данный момент я отказался от библиотеки aspnet-api-versioning, но создал проблему в их репозитории github, на случай, если это ошибка.

Поскольку яя действительно ненавижу идею создания и обслуживания магических строк, поэтому я выбрал следующий подход - у каждого контроллера есть открытый статический класс, который содержит значения const для имен маршрутов:

[RoutePrefix("api/v1/developers")]
public class DevelopersController : ApiController
{
    [HttpGet, Route("{developerId}/programs", Name = Routes.GetPrograms)]
    public async Task<IEnumerable<Program>> GetPrograms(Guid developerId){}

    public static class Routes
    {
        public const string GetPrograms = nameof(DevelopersController) +"."+ nameof(DevelopersController.GetPrograms);
    }
}

Теперь это можно использовать изконтроллер бритвы простым и относительно безопасным способом:

@Url.HttpRouteUrl(DevelopersController.Routes.GetPrograms, new { developerId = /* uniquest of guids */})

Чуть лучше, чем волшебные струны.Я также добавил несколько модульных тестов для контроллеров, где я проверяю, что каждый маршрут является уникальным и правильным, и что класс маршрутов содержит маршруты только для действия, которое он содержит.

0 голосов
/ 31 декабря 2018

Попробуйте следующее:

Назовите свой маршрут:

[HttpGet, Route("{telemetryKey}/versions/latest", Name="LatestVersionInfoRoute")]
    public async Task<LatestVersionResponse> GetLatestVersionInfo(Guid telemetryKey)
    {
        // serious business logic
    }

Используйте метод Url.Link:

@Url.Link("LatestVersionInfoRoute", new { telemetryKey = Guid.Parse("43808405-afca-4abb-a92a-519489d62290") })
...