маршруты области web api 2
Я использую asp.net mvc 5 и web api 2. За то, что asp.net проект mvc 5 у меня все работает... но новый я пытаюсь добавить Web api 2 routes... когда я использую зоны.
У меня есть контроллер web api 2, работающий в корне проекта:
//this is working
namespace EtracsWeb.Controllers
{
public class TestController : ApiController
{
//localhost:port/api/test ...this is working
[HttpGet]
public HttpResponseMessage Get()
{
return new HttpResponseMessage()
{
Content = new StringContent("GET: Test message")
};
}
}
}
Поэтому я предполагаю, что мои Global.asax
, мои routeconfig.cs
и мои webapiconfig.cs
верны ... (не показанный)...
, но сейчас я пытаюсь сделать веб-API 2 в моей области работы...
Я прочитал все, что смог найти в интернете и похоже, так и должно быть. работа:
namespace EtracsWeb.Areas.WorkOrder
{
public class WorkOrderAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "WorkOrder";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.Routes.MapHttpRoute(
name: "AuditModel_Api",
routeTemplate: "WorkOrder/api/AuditModelApi/{id}",
defaults: new { id = RouteParameter.Optional }
);
//default
context.Routes.MapHttpRoute(
name: "WorkOrder_Api",
routeTemplate: "WorkOrder/api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
context.MapRoute(
"WorkOrder_default",
"WorkOrder/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
}
}
Мой код контроллера:
namespace EtracsWeb.Areas.WorkOrder.ApiControllers
{
public class AuditModelApiController : ApiController
{
IManufacturerStopOrderModelService auditModelService = new WorkOrder.Services.VWAuditModelService(UserSession.EtracsUserID, UserSession.ProgramID, UserSession.EtracsSessionID, UserSession.ConnectionString);
[HttpGet]
[Route("AuditModelApi")]
public HttpResponseMessage Get()
{
return new HttpResponseMessage()
{
Content = new StringContent("GET: Test message")
};
}
[Route("AuditModelApi/AuditModels")]
public IEnumerable<VwAuditModel1> GetAuditModels()
{
return auditModelService.GetModels();
}
public IHttpActionResult UpdateAuditMode()
{
//example of what can be returned ... NotFound, Ok ... look into uses...
VwAuditModel1 result = new VwAuditModel1();
return Ok(result);
return NotFound();
}
}
}
Я попробовал контроллер с именем атрибута и без него [Route]
...
и я не могу заставить ни того, ни другого работать...
Оба простых случая
public HttpResponseMessage Get()
И "реальный" случай
public IEnumerable<VwAuditModel1> GetAuditModels()
Верните тот же результат. Из браузера, используя
http://localhost:64167/WorkOrder/api/AuditModelApi
И
http://localhost:64167/WorkOrder/api/AuditModelApi/AuditModels
Я получаю следующее:
<Error>
<Message>
No HTTP resource was found that matches the request URI 'http://localhost:64167/WorkOrder/api/AuditModelApi/AuditModels'.
</Message>
<MessageDetail>
No route providing a controller name was found to match request URI 'http://localhost:64167/WorkOrder/api/AuditModelApi/AuditModels'
</MessageDetail>
</Error>
3 ответа:
Вам нужно получить экземпляр
HttpConfiguration
из объектаGlobalConfiguration
и вызвать методMapHttpAttributeRoutes()
из методаRegisterArea()
объектаAreaRegistration.cs
.public override void RegisterArea(AreaRegistrationContext context) { GlobalConfiguration.Configuration.MapHttpAttributeRoutes(); //... omitted code }
Наконец, вы должны в методе
WebApiConfig
удалитьconfig.MapHttpAttributes()
, или вы получите дубликат исключения.public static class WebApiConfig { public static void Register(HttpConfiguration config) { // Web API configuration and services config.EnableCors(); // Configure Web API to use only bearer token authentication. config.SuppressDefaultHostAuthentication(); config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType)); // Web API routes //config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); } }
Проблема с этим конкретным вызовом API заключается в том, что вы не указали контроллер для использования в вашем маршруте.
context.Routes.MapHttpRoute( name: "AuditModel_Api", routeTemplate: "WorkOrder/api/AuditModelApi/{id}", defaults: new { id = RouteParameter.Optional } );
Должно быть
context.Routes.MapHttpRoute( name: "AuditModel_Api", routeTemplate: "WorkOrder/api/AuditModelApi/{id}", defaults: new { controller = "AuditModelApi", id = RouteParameter.Optional } );
Постоянные сегменты в URL-адресе должны указывать, какой URL должен соответствовать, но вы все равно должны сказать ему, каковы значения маршрута, чтобы он мог добраться до контроллера и действия. Он не может знать, какой сегмент использовать в качестве имени контроллера, если вы не сделаете его сегментом
{controller}
.
Во-первых, вы должны зарегистрировать маршрут с областью, к которой он принадлежит, что только имеет смысл, поэтому внутри вашего класса
AreaNameAreaRegistration
Обязательно добавьтеusing System.Web.Http
, чтобы вы получили метод расширенияMapHttpRoute
, он не является частьюSystem.Web.Mvc
.Порядок выше немного не тот, что вызывает 404. Добавьте следующий маршрут:
context.Routes.MapHttpRoute( name: "AreaNameWebApi", routeTemplate: "api/AreaName/{controller}/{id}", defaults: new { id = RouteParameter.Optional } );
Если вы хотите получить фантазии и добавить имя области из свойства
AreaName
(Конечно, вы заботитесь о хорошей практике кодирования;)):context.Routes.MapHttpRoute( name: "AreaNameWebApi", routeTemplate: string.Concat("api/", AreaName, "/{controller}/{id}"), defaults: new { id = RouteParameter.Optional } );
Это исправит проблему 404. В модуле Web API по умолчанию он сначала сканирует "api", чтобы определить, где искать контроллер (иначе он будет запутан, это не магия), поэтому api должен быть первым при динамическом добавлении имени области и контроллера. Конечно, вы можете изменить этот порядок путем жесткого кодирования ваших маршрутов, но я не рекомендую этого делать, потому что вам нужно будет указать каждый маршрут и каждый контроллер в конфигурации маршрута или с помощью
RouteAttribute
.Плюс, с "api" сначала это сделает приятный стандартный вид URL для вас и ваших пользователей вместо того, чтобы иметь API повсюду. Вот некоторые примеры:
http://site/api/members/myAccount/update http://site/api/members/myAccount/get/12345 http://site/api/members/contacts/getByOwnerId/12345
Надеюсь, это поможет!
Зев