Тестирование запроса 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, это, вероятно, лучше, концептуально, но принцип маршрутизации одинаков.