Маршрутизация на основе имени параметра строки запроса

Я пытаюсь настроить маршрутизацию в своем проекте MVC4 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 }
);

Проблема в том, что имя параметра строки запроса, кажется, игнорируется, поэтому всегда используется первый маршрут, независимо от имени параметра строки запроса. Как я могу изменить свой маршрут, чтобы сделать его правильным?

4 ответа

Решение

Вам нужен только один маршрут ниже, потому что строка запроса не используется в качестве параметров маршрутизации:

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

Вам не нужно включать параметры вашего запроса в маршрут. Должна быть только одна простая карта маршрутов, чтобы покрыть методы 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
}

Если вы хотите явно выполнять поиск по одному полю за раз, тогда вам следует подумать об использовании разных контроллеров для разных целей. То есть SearchProductByTypeController который имеет один Get(string type) метод. Тогда маршрут будет /api/SearchProductByTypeController? Type=gadget

Попробуйте изменить string.Empty за RouteParameter.Optional

Вы уверены, что с контроллерами все в порядке? Я имею в виду название параметров.

    public string GetProductsByName(string name)
    {
        return "Requested name: " + name;
    }

    public string GetProductsByType(string type)
    {
        return "Requested type: " + type;
    }
Другие вопросы по тегам