ASP.NET WebAPI中的路由
本文介绍ASP.NET Web API如何将HTTP请求路由到控制器
注意
如果您熟悉ASP.NET MVC,则Web API路由与MVC路由非常相似。主要区别在于Web API使用HTTP方法而不是URI路径来选择操作。还可以在Web API中使用MVC样式的路由。本文不假设任何ASP.NET MVC知识。
路由表:在ASP.NET Web API中,控制器是一个处理HTTP请求的类。控制器的公共方法称为操作方法或简单的操作。当Web API框架收到请求时,它会将请求路由到要确定调用的操作,框架使用路由表。Web API的Visual Studio项目模板创建了一个默认路由:
routes.MapHttpRoute(
name: "API Default",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
有关WebApiConfig类的详细信息,请参阅配置ASP.NET Web API。
如果您自托管Web API,则必须直接在HttpSelfHostConfiguration对象上设置路由表。有关更多信息,请参阅自托管Web API。
路由表中的每个条目都包含一个路由模板。Web API的默认路由模板是“api / {controller} / {id}”。在此模板中,“api”是文字路径段,{controller}和{id}是占位符变量。
当Web API框架收到HTTP请求时,它会尝试将URI与路由表中的某个路由模板进行匹配。如果没有路由匹配,则客户端收到404错误。例如,以下URI与默认路由匹配:
/ API /触点
/ API /联系人/ 1
/ API /产品/ gizmo1
但是,以下URI不匹配,因为它缺少“api”段:
/联系人/ 1
注意
在路由中使用“api”的原因是为了避免与ASP.NET MVC路由冲突。这样,你可以让“/ contacts”转到MVC控制器,“/ api / contacts”转到Web API控制器。当然,如果您不喜欢此约定,则可以更改默认路由表。
找到匹配的路由后,Web API将选择控制器和操作:
1、要查找控制器,Web API会将“Controller”添加到{controller}变量的值中。
2、要查找操作,Web API会查看HTTP方法,然后查找名称以该HTTP方法名称开头的操作。例如,对于GET请求,Web API会查找以“Get ...”开头的操作,例如“GetContact”或“GetAllContacts”。此约定仅适用于GET,POST,PUT和DELETE方法。您可以使用控制器上的属性启用其他HTTP方法。我们稍后会看到一个例子。
3、路径模板中的其他占位符变量(例如{id})将映射到操作参数。
来看一个例子。假设您定义以下控制器:
public class ProductsController : ApiController
{
public IEnumerable<Product> GetAllProducts() { }
public Product GetProductById(int id) { }
public HttpResponseMessage DeleteProduct(int id){ }
}
以下是一些可能的HTTP请求,以及为每个请求调用的操作:
HTTP方法 | URI路径 | 行动 | 参数 |
Get | API /产品 | GetAllProducts | (没有) |
Get | API /产品/ 4 | GetProductById | 4 |
Delete | API /产品/ 4 | DeleteProduct | 4 |
POST | API /产品 | (不匹配) |
|
请注意,URI 的{id}段(如果存在)将映射到操作的id参数。在此示例中,控制器定义了两个GET方法,一个具有id参数,另一个没有参数。
另请注意,POST请求将失败,因为控制器未定义“Post ...”方法。
路由变化
上一节描述了ASP.NET Web API的基本路由机制。本节介绍一些变体。
HTTP方法
可以通过使用HttpGet,HttpPut,HttpPost或HttpDelete属性修改操作方法,而不是使用HTTP方法的命名约定,而是显式指定操作的HTTP方法。
在以下示例中,FindProduct方法映射到GET请求:
public class ProductsController : ApiController
{
[HttpGet]
public Product FindProduct(id) {}
}
要允许多个HTTP方法执行操作,或允许除GET,PUT,POST和DELETE 之外的HTTP方法,请使用AcceptVerbs属性,该属性采用HTTP方法列表。
public class ProductsController : ApiController
{
[AcceptVerbs("GET", "HEAD")]
public Product FindProduct(id) { }
// WebDAV method
[AcceptVerbs("MKCOL")]
public void MakeCollection() { }
}
按操作名称路由
使用默认路由模板,Web API使用HTTP方法选择操作。但是,您也可以创建一个路径,其中操作名称包含在URI中:
routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
在此路由模板中,{action}参数在控制器上命名操作方法。使用此样式的路由,使用属性指定允许的HTTP方法。例如,假设您的控制器具有以下方法:
public class ProductsController : ApiController
{
[HttpGet]
public string Details(int id);
}
在这种情况下,对“api / products / details / 1”的GET请求将映射到Details方法。这种路由类型与ASP.NET MVC类似,可能适用于RPC样式的API。
您可以使用ActionName属性覆盖操作名称。在以下示例中,有两个操作映射到“api / products / thumbnail / id。一个支持GET,另一个支持POST:
public class ProductsController : ApiController
{
[HttpGet]
[ActionName("Thumbnail")]
public HttpResponseMessage GetThumbnailImage(int id);
[HttpPost]
[ActionName("Thumbnail")]
public void AddThumbnailImage(int id);
}
非操作
要防止将方法作为操作调用,请使用NonAction属性。这向框架发出信号,表明该方法不是动作,即使它与路由规则匹配。
// Not an action method.
[NonAction]
public string GetPrivateData() { ... }