Настройка ASP.NET Web Api Routing
У меня есть контроллеры WebApi, которые заканчиваются суффиксом "Api" в их именах (например: StudentsApiController, InstructorsApiController). Я делаю это, чтобы легко отличить контроллеры MVC от контроллеров WebApi. Я хочу, чтобы мои маршруты WebApi выглядели похожими на
http://localhost:50009/api/students/5
, а не http://localhost:50009/api/studentsapi/5
.
В настоящее время для этого я настраиваю маршруты, например
routes.MapHttpRoute(
name: "GetStudents",
routeTemplate: "api/students/{id}",
defaults: new { controller = "StudentsApi", id = RouteParameter.Optional });
routes.MapHttpRoute(
name: "GetInstructors",
routeTemplate: "api/instructors/{id}",
defaults: new { controller = "InstructorsApi", id = RouteParameter.Optional });
Это оказывается очень громоздким, поскольку я должен добавить маршрут для каждого метода в своих контроллерах. Я надеюсь, что должен быть простой способ настройки шаблонов маршрутов, который автоматически добавляет суффикс "api" имя контроллера во время обработки маршрутов.
Ответы
Ответ 1
Я думаю, что точка расширяемости, которую вы ищете, - это селектор контроллера. Вы можете создать класс, который выводится из DefaultHttpControllerSelector и переопределяет имя GetControllerName, чтобы вырезать часть "api". Затем вы можете зарегистрировать этот селектор контроллера в службах конфигурации службы.
Ответ 2
Следуя @Youssef Moussaoui направлении, я закончил тем, что написал следующий код, который решил проблему.
public class ApiControllerSelector : DefaultHttpControllerSelector
{
public ApiControllerSelector(HttpConfiguration configuration)
: base(configuration)
{
}
public override string GetControllerName(HttpRequestMessage request)
{
if (request == null)
throw new ArgumentNullException("request");
IHttpRouteData routeData = request.GetRouteData();
if (routeData == null)
return null;
// Look up controller in route data
object controllerName;
routeData.Values.TryGetValue("controller", out controllerName);
if (controllerName != null)
controllerName += "api";
return (string)controllerName;
}
}
И зарегистрируйте его в Global.asax как
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerSelector),
new ApiControllerSelector(GlobalConfiguration.Configuration));
Ответ 3
Теперь, когда ASP.NET Web API 2 отсутствует, существует гораздо менее громоздкий способ сделать более сложную маршрутизацию, как вы предложили, используя маршрутизацию атрибутов.
В верхней части вашего контроллера просто добавьте следующий атрибут:
[RoutePrefix("api/students")]
public class StudentsApiController : ApiController
{
...
}
И затем перед каждым методом API:
[Route("{id}"]
public HttpResponseMessage Get(int id)
{
...
}
Требуется немного настройки, но положительных результатов для этой маршрутизации много. Во-первых, вы можете поместить маршрутизацию с помощью контроллеров и методов, которые выполняют фактическую работу, поэтому вы никогда не будете искать вокруг, задаваясь вопросом, есть ли у вас правильный маршрут. Во-вторых, что более важно, гораздо проще выполнять более сложную маршрутизацию, например, иметь имя контроллера, отличное от имени маршрута (например, вы хотите), или иметь очень сложные шаблоны, чтобы соответствовать.
Ответ 4
После комментария Youssef к муругу-ответу будет выглядеть примерно так.
public class ApiControllerSelector : DefaultHttpControllerSelector
{
public ApiControllerSelector (HttpConfiguration configuration) : base(configuration) { }
public override string GetControllerName(HttpRequestMessage request)
{
return base.GetControllerName(request) + "api";
}
}