Как в Web Api указать два отдельных маршрута к одному контроллеру с двумя методами получения без использования атрибутов?

У меня есть контроллер учетной записи с двумя методами Get, один из которых получает все учетные записи и не принимает никаких входных данных, а другой принимает Id int и возвращает эту конкретную учетную запись.

Ограничения проекта заключаются в том, что у нас не может быть id в качестве необязательного параметра на маршруте по умолчанию, вместо этого нам нужен доступ к get-one-account и get-all-accounts через разные маршруты, и мы не можем использовать маршрутизацию атрибутов. Итак, наша конфигурация маршрута в настоящее время выглядит так:

config.Routes.MapHttpRoute("AccountWithId", "api/account/{id}", new { action = "Get", id = RouteParameter.Optional }
                , new { httpMethod = new HttpMethodConstraint(HttpMethod.Get), id = @"\d+" });

config.Routes.MapHttpRoute("Default", "api/{controller}");

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

public IHttpActionResult Get()
        {
            IList<AccountDto> users = m_service.Get();

            return Ok(users);
        }

        public IHttpActionResult Get(int accountId)
        {
            AccountDto user = m_service.Get(accountId);

            return Ok(user);
        }

Но когда я вызываю Get с параметром id в своем тесте через свой собственный маршрут и отлаживаю, как показано ниже, он по-прежнему использует метод Get, который не принимает параметр id и возвращает все.

var url = "http://test/api/account/" + accountId;

var response = await m_server.HttpClient.GetAsync(url);

Есть идеи, почему?


person RSid    schedule 11.12.2014    source источник
comment
Если accountId является необязательным, Get(int accountId) будет скрыт перегрузкой Get(). Таким образом, вы не можете сделать accountId необязательным.   -  person Win    schedule 11.12.2014
comment
Очевидно, что когда значение является необязательным, оно всегда попадает в один и тот же маршрут, потому что, если он указан или нет, он является необязательным, поэтому нет проблем с тем, что маршрут всегда будет предшествующим и будет скрыт перегрузкой get   -  person Tushar    schedule 11.12.2014
comment
@Win Имеет смысл, но нет параметра RouteParameter.Required, и он точно так же не работает с удалением этого параметра. Я следовал совету в этом вопросе: stackoverflow.com/questions/9499794/   -  person RSid    schedule 11.12.2014


Ответы (1)


Здесь я вижу ряд проблем.

В вашем первом маршруте не указан контроллер по умолчанию, и я удивлен, что вы не получили 404 при отправке идентификатора учетной записи.

Во-вторых, если параметр id является необязательным, регулярное выражение должно быть \d*, а не \d+.

В-третьих, имена параметров в ваших действиях должны совпадать с вашими параметрами маршрутизации, поэтому accountId следует изменить на id.

Попробуйте это для маршрутизации:

config.Routes.MapHttpRoute("AccountWithId",
    "api/account/{id}",
    new { controller = "Account", action = "Get", id = RouteParameter.Optional },
    new { httpMethod = new HttpMethodConstraint(HttpMethod.Get), id = @"\d*" }
);

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

а затем измените подписи действий на:

public IHttpActionResult Get()
{
    ...
}

public IHttpActionResult Get(int id)
{
    ...
}
person Jon Susiak    schedule 12.12.2014
comment
Хорошо поймал имя параметра и регулярное выражение, спасибо. Я должен был добавить к вопросу, что я пытался указать контроллер учетной записи, и это не решило проблему. Нет ли способа заставить это работать, вообще не имея «/ {id}» на маршруте по умолчанию? - person RSid; 12.12.2014
comment
Да, если вы хотите удалить параметр {id} в маршруте по умолчанию (defaultapi), он все равно должен работать в случаях, которые вы показали выше. Я проверил это, и он правильно маршрутизируется, поэтому, если у вас все еще есть проблемы, должна быть какая-то информация, которую нам не хватает. - person Jon Susiak; 12.12.2014