Маршрутизация на основе имени параметра строки запроса
Я пытаюсь настроить маршрутизацию в проекте MVAP4 WebAPI.
Я хочу иметь возможность искать продукты на основе их имени или их типа:
/api/products?name=WidgetX
- возвращает все продукты с именем WidgetX
/api/products?type=gadget
- возвращает все продукты гаджета типа
Маршруты настроены следующим образом:
config.Routes.MapHttpRoute(
name: "Get by name",
routeTemplate: "api/products/{name}",
defaults: new { controller = "ProductSearchApi", action = "GetProductsByName", name = string.Empty }
);
config.Routes.MapHttpRoute(
name: "Get by type",
routeTemplate: "api/products/{type}",
defaults: new { controller = "ProductSearchApi", action = "GetProductsByType", type = string.Empty }
);
Проблема состоит в том, что имя параметра строки запроса, похоже, игнорируется, поэтому первый маршрут всегда используется, независимо от имени параметра строки запроса.
Как я могу изменить свой маршрут, чтобы все было правильно?
Ответы
Ответ 1
Вам нужен только один маршрут ниже, потому что строка запроса не используется в качестве параметров маршрутизации:
config.Routes.MapHttpRoute(
name: "Get Products",
routeTemplate: "api/products",
defaults: new { controller = "ProductSearchApi" }
);
И затем определите два метода, как показано ниже:
GetProductsByName(string name)
{}
GetProductsByType(string type)
{}
Механизм маршрутизации достаточно умен, чтобы направить URL-адрес на правильное действие, основанное на имени строки запроса, независимо от того, совпадают ли параметры ввода. Конечно, при всех методах с префиксом Get
Вам может потребоваться прочитать следующее:
http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-and-action-selection
Ответ 2
Вам не нужно включать параметры запроса в маршрут. Должна быть только одна простая карта маршрута для покрытия Http-методов на всех ваших ApiControllers:
routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
Единственный раз, когда вам нужно настроить маршруты, нужно, если вы хотите переместить параметр в фактический путь, который вы, кажется, не делаете. Тогда ваш метод GET
http для поиска по двум полям будет выглядеть следующим образом:
public IEnumerable<Product> Get(string name, string type){
//..your code will have to deal with nulls of each parameter
}
Если вы хотите явно искать по одному полю за раз, вам следует подумать об использовании разных контроллеров для разных целей. То есть, a SearchProductByTypeController
, который имеет единственный метод Get(string type)
. Тогда маршрут будет /api/SearchProductByTypeController? Type = gadget
Ответ 3
попробуйте изменить string.Empty
для RouteParameter.Optional
Ответ 4
Вы уверены, что контроллеры в порядке? Я имею в виду, имя params.
public string GetProductsByName(string name)
{
return "Requested name: " + name;
}
public string GetProductsByType(string type)
{
return "Requested type: " + type;
}