Тестирование запроса GET, который принимает объект как параметр (Asp.NET WebApi Controller)

Мне назначили разработку контроллера WebAPI для приложения (с которым я никогда не работал). Все прошло отлично, у него были базовые запросы, такие как GetAllUsers (int id) только для тестирования - сама конфигурация в порядке.

Теперь вот вопрос. У меня есть метод GetAllItems(Carrier carrier) где Carrier - класс с рядом различных параметров. Поскольку у нас уже есть несколько экземпляров Carrier в базе данных для тестирования, то, что я пытался, запрашивал базу данных, выбирая экземпляр Carrier на основе атрибута ID (GUID), но без результата.

Есть ли способ проверить запросы GET, когда входной параметр является объектом, а не одним значением (например, int ID, например) вручную, с помощью тестового метода или тестового входного параметра какого-либо типа?

EDIT: Спасибо всем за отзыв, решение моей проблемы было намного проще исправить, чем я ожидал. Я бы очень хотел всех вас переубедить, хотя, к сожалению, моя репутация слишком мала, чтобы сделать это (я новичок в stackoverflow), поэтому мне придется вернуться к этому в какой-то момент в ближайшем будущем. Приветствия:)

Ответ 1

Насколько я понимаю ваш вопрос, вы хотите иметь возможность передавать свойства Carrier непосредственно в URL-адресе, а не в теле запроса.

Пример:

[GET] http://localhost/entities?id=000000000000000

Вы используете этот метод контроллера

GetAllItems(Carrier carrier)

У несущей есть свойство Id (Guid):

class Carrier {
    public Guid Id { get; set; }
    public string Name { get; set; }
}

Перевозчик представляет собой сложный объект с точки зрения привязки модели WebApi.

Поведение по умолчанию для привязки к модели:

По умолчанию Web API использует следующие правила для привязки параметров: Если параметр является "простым" типом, Web API пытается получить значение из URI. Простые типы включают в себя примитивные типы .NET(int, bool, double и т.д.), А также TimeSpan, DateTime, Guid, decimal и string, а также любой тип с конвертером типов, который может конвертировать из строки. (Подробнее о преобразователях типов позже). Для сложных типов Web API пытается прочитать значение из тела сообщения с использованием форматера медиа-типа.

см. ниже: http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api

Ожидание привязки модели к сложному объекту в URL-адресе не является поведением WebApi по умолчанию.

Если вы хотите, чтобы ваш метод контроллера моделировал привязку сложного объекта от URL-адреса, вы должны сообщить ему.

GetAllItems([FromUri] Carrier carrier)

С помощью индикатора привязки FromUri вы можете использовать привязку сложной модели из URL

Теперь вы можете добавить еще больше свойств в URL:

[GET] http://localhost/entities?id=000000000000000&name=ABC

GetAllItems получит объект Carrier, заполненный: carrier.Id = 0000-00000000000-000; carrier.Name = "ABC"

Ответ 2

У вас есть проблема маршрутизации здесь, а также несколько заблуждений.

Маршрут по умолчанию для WebApi:

routes.MapHttpRoute(
            name: "Default",
            routeTemplate: "{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

Это вместе с некоторыми соглашениями:

  • GetX отображает методы GET.
  • ВставкаX отображает методы POST.
  • UpdateX отображает методы PUT.
  • DeleteX отображает методы DELETE.

Если ваше соглашение об именах не совпадает с соглашениями WepApi, вам необходимо указать метод, имя действия и т.д.

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

Например:

public IEnumerable<Carrier> GetAll(){
   //this will get called when using the route: /api/carriers/
}

public IEnumerable<Carrier> Get(string id){
   //this will be called when using the route: /api/carriers/1
   //where 1 is the carrier id
}

Будет работать в CarrierController, поскольку оба они совпадают с соглашениями и маршрутом.

Теперь, если вам нужен метод, который возвращает ВСЕ элементы для носителя, вам понадобится этот метод:

[ActionName("getItems")]
public IEnumerable<Item> GetAllItems(string id){
   //where id is the carrierid       
   var carrierId = id;
   //because you are specifying the ActionName to getItems this will match the following route: 
   // /api/carriers/getItems/1
}

Другой вариант - создать элемент ItemsController и добавить действие, которое возвращает список элементов на основе carrierId, это, вероятно, лучше, концептуально, но принцип маршрутизации одинаков.