使用 Web API 属性路由和 RoutePrefix
using Web API attribute routing and RoutePrefix
使用 web api 时,如果使用 [RoutePrefix()]
如何调用正确的路由方法
假设您有类似 "MyReallyLongNamedClassController" 的内容。默认路由为 http:...com/api/MyReallyLongNamedClass。然后应用程序通过名为 Get、Post、Put 等的方法运行(当然除非使用动词装饰器)。
如果我在我的控制器上放置了 [RoutePrefix("api/LongClass")]
的路由前缀装饰器,我怎么能让 web api 仍然使用这些方法的默认值?
意思是,我希望名为 "GetAll()" 的方法仍然映射到 "api/LongClass"(当使用 get header 时)并且 "PostThis(int id)" 仍然映射到 "api/LongClass/{id}"(当使用 post header 时)
您不必担心 RoutePrefix 属性在内部的工作方式。您可以使用 RoutePrefix 装饰您的控制器或操作,并可以根据您的设置调用操作。您必须在操作中使用 Route
属性才能使 [RoutePrefix]
正常工作。
例如,在下面的控制器中,对 url api/longclass/get
的所有 GET
请求将调用 GetAll
方法,对 POST
的所有请求将调用 api/longclass/post
将调用PostThis
[RoutePrefix("api/longclass")]
public class MyReallyLongNamedClass: ApiController
{
[Route("get")]
public string GetAll(int id)
{
return "result";
}
[Route("post")]
public string PostThis([FromBody] MyModel model)
{
var res= _repository.Save(model);
return res;
}
}
以下是我在无需使用注释修饰所有方法的情况下解决问题的方法。我把 RoutePrefix 放在了 class 级别,默认的 Route
[RoutePrefix("api/longclass")]
[Route("{id?}")]
public class MyReallyLongNamedClass: ApiController
{
public string GetAll(int id)
{
return "result";
}
public string PostThis([FromBody] MyModel model)
{
var res= _repository.Save(model);
return res;
}
}
另一种选择:如果您只想更改路由中的控制器名称,您可以创建自定义控制器选择器:
public class CustomControllerSelector : DefaultHttpControllerSelector
{
public CustomControllerSelector(HttpConfiguration configuration)
: base(configuration)
{ }
public override string GetControllerName(HttpRequestMessage request)
{
var name = base.GetControllerName(request);
// Interpret "LongClass" as "MyReallyLongNamedClass"
if (name == "LongClass")
name = "MyReallyLongNamedClass";
return name;
}
}
然后您可以在 WebApiConfig.Register
:
中注册控制器选择器
config.Services.Replace(typeof(IHttpControllerSelector), new CustomControllerSelector(config));
这样做的好处是您可以使用已经映射的路由(使用 HttpRouteCollection.MapHttpRoute()
定义)而不是使用属性路由。但是,如果您出于其他原因需要使用属性路由,那么您的解决方案可能会更好。
使用 web api 时,如果使用 [RoutePrefix()]
假设您有类似 "MyReallyLongNamedClassController" 的内容。默认路由为 http:...com/api/MyReallyLongNamedClass。然后应用程序通过名为 Get、Post、Put 等的方法运行(当然除非使用动词装饰器)。
如果我在我的控制器上放置了 [RoutePrefix("api/LongClass")]
的路由前缀装饰器,我怎么能让 web api 仍然使用这些方法的默认值?
意思是,我希望名为 "GetAll()" 的方法仍然映射到 "api/LongClass"(当使用 get header 时)并且 "PostThis(int id)" 仍然映射到 "api/LongClass/{id}"(当使用 post header 时)
您不必担心 RoutePrefix 属性在内部的工作方式。您可以使用 RoutePrefix 装饰您的控制器或操作,并可以根据您的设置调用操作。您必须在操作中使用 Route
属性才能使 [RoutePrefix]
正常工作。
例如,在下面的控制器中,对 url api/longclass/get
的所有 GET
请求将调用 GetAll
方法,对 POST
的所有请求将调用 api/longclass/post
将调用PostThis
[RoutePrefix("api/longclass")]
public class MyReallyLongNamedClass: ApiController
{
[Route("get")]
public string GetAll(int id)
{
return "result";
}
[Route("post")]
public string PostThis([FromBody] MyModel model)
{
var res= _repository.Save(model);
return res;
}
}
以下是我在无需使用注释修饰所有方法的情况下解决问题的方法。我把 RoutePrefix 放在了 class 级别,默认的 Route
[RoutePrefix("api/longclass")]
[Route("{id?}")]
public class MyReallyLongNamedClass: ApiController
{
public string GetAll(int id)
{
return "result";
}
public string PostThis([FromBody] MyModel model)
{
var res= _repository.Save(model);
return res;
}
}
另一种选择:如果您只想更改路由中的控制器名称,您可以创建自定义控制器选择器:
public class CustomControllerSelector : DefaultHttpControllerSelector
{
public CustomControllerSelector(HttpConfiguration configuration)
: base(configuration)
{ }
public override string GetControllerName(HttpRequestMessage request)
{
var name = base.GetControllerName(request);
// Interpret "LongClass" as "MyReallyLongNamedClass"
if (name == "LongClass")
name = "MyReallyLongNamedClass";
return name;
}
}
然后您可以在 WebApiConfig.Register
:
config.Services.Replace(typeof(IHttpControllerSelector), new CustomControllerSelector(config));
这样做的好处是您可以使用已经映射的路由(使用 HttpRouteCollection.MapHttpRoute()
定义)而不是使用属性路由。但是,如果您出于其他原因需要使用属性路由,那么您的解决方案可能会更好。