Параметры Web.API MapHttpRoute
У меня проблемы с моей маршрутизацией Web.API. У меня есть следующие два маршрута:
config.Routes.MapHttpRoute(
name: "MethodOne",
routeTemplate: "api/{controller}/{action}/{id}/{type}",
defaults: new { id = RouteParameter.Optional, type = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "MethodTwo",
routeTemplate: "api/{controller}/{action}/{directory}/{report}",
defaults: new { directory = RouteParameter.Optional, report = RouteParameter.Optional }
);
И в моем контроллере эти два метода:
[HttpGet]
[ActionName("methodone")]
public string MethodOne(string id, string type)
{
return string.Empty;
}
[HttpGet]
[ActionName("methodtwo")]
public string MethodTwo(string directory, string report)
{
return string.Empty;
}
Эти два, казалось бы, не могут жить бок о бок. Если я прокомментирую маршрут MethodOne в WebApiConfig, работает метод MethodTwo. Метод Commenting MethodTwo позволяет MethodOne работать. Оставляя как uncommented, MethodOne работает, но не MethodTwo.
Я надеялся использовать один маршрут для обоих из них, тогда, похоже, им придется иметь одинаковые имена параметров. Кто пишет методы с именами общих параметров? Плохо. Я действительно не хочу, чтобы мои методы имели одинаковые имена параметров (например, p1, p2, p3), поэтому я решил создать маршрут только для нового метода. Но даже это не работает.
Я действительно скучаю по WebGet(UriTemplate="")
из отдыха WCF.
У меня есть один контроллер, который имеет много методов, некоторые с 1, 2, 3 или даже больше параметров. Я не могу поверить, что не могу использовать значащие имена параметров с помощью подхода MapHttpRoute.
Я могу полностью прокомментировать это и использовать WebGet()
... но до того, как я добрался туда, мне захотелось узнать, не хватает ли чего-то.
Ответы
Ответ 1
Причина, по которой вы видите эту проблему, состоит в том, что ваш первый маршрут будет соответствовать обоим запросам. Маркер идентификатора и типа в URL-адресе будет соответствовать обоим запросам, потому что, когда маршрут запускается, он попытается разобрать URL-адрес и сопоставить каждый сегмент с вашим URL-адресом.
Таким образом, ваш первый маршрут будет с удовольствием соответствовать обоим запросам следующим образом.
~/methodone/1/mytype => action = methodone, id = 1, and type = mytype
~/methodtwo/directory/report => action = methodtwo, id = directory, and type = report
Чтобы обойти это, вы должны использовать маршрут, например
config.Routes.MapHttpRoute(
name: "MethodOne",
routeTemplate: "api/{controller}/methodone/{id}/{type}",
defaults: new { id = RouteParameter.Optional, type = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "MethodTwo",
routeTemplate: "api/{controller}/methodtwo/{directory}/{report}",
defaults: new { directory = RouteParameter.Optional, report = RouteParameter.Optional }
);
Даже если вы используете WebGet, вам, возможно, придется сделать что-то похожее на двусмысленные те два метода, которые я считаю.
Ответ 2
Вы можете передать параметры в строке запроса, например /MethodTwo? directory = a & report = b, но если вы хотите, чтобы они отображались в пути, это выглядит хорошим кандидатом для маршрутизации на основе атрибутов, Здесь у Филиппа есть отличная статья:
http://www.strathweb.com/2012/05/attribute-based-routing-in-asp-net-web-api/
Ответ 3
Из http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-and-action-selection
Вы также можете предоставить ограничения, которые ограничивают использование сегмента URI сопоставить местозаполнитель:
: new {id = @ "\ d +" }//Только совпадения, если "id" - один или больше цифр.
Добавление этого ограничения в "MethodOne" (api/{controller}/{action}/{id}/{type}) будет означать, что числа будут соответствовать только, если {id} - это число, в противном случае оно будет соответствовать методу MethodTwo, ( "апи/{контроллер}/{действие}/{каталог}/{} отчет" ).