Routing in ASP.NET Web API(在 ASP.NET Web API 中路由)

本文介绍 ASP.NET Web API如何将 HTTP 请求路由到控制器。

注意

如果熟悉 ASP.NET MVC,Web API 路由与 MVC 路由非常相似。 main区别在于 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.cs 文件中定义,该文件位于 App_Start 目录中:

定义路由的解决方案资源管理器的图像。

有关 类的详细信息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/contacts
  • /api/contacts/1
  • /api/products/gizmo1

但是,以下 URI 不匹配,因为它缺少“api”段:

  • /contacts/1

注意

在路由中使用“api”的原因是为了避免与 ASP.NET MVC 路由冲突。 这样,就可以让“/contacts”转到 MVC 控制器,让“/api/contacts”转到 Web API 控制器。 当然,如果不喜欢此约定,可以更改默认路由表。

找到匹配的路由后,Web API 会选择控制器和操作:

  • 为了查找控制器,Web API 将“控制器”添加到 {controller} 变量的值。
  • 若要查找操作,Web API 会查找 HTTP 谓词,然后查找名称以 HTTP 谓词名称开头的操作。 例如,对于 GET 请求,Web API 查找前缀为“Get”的操作,例如“GetContact”或“GetAllContacts”。 此约定仅适用于 GET、POST、PUT、DELETE、HEAD、OPTIONS 和 PATCH 谓词。 可以使用控制器上的属性启用其他 HTTP 谓词。 稍后我们将看到一个示例。
  • 路由模板中的其他占位符变量(如 {id} )映射到操作参数。

接下来举例说明。 假设你定义了以下控制器:

public class ProductsController : ApiController
{
    public IEnumerable<Product> GetAllProducts() { }
    public Product GetProductById(int id) { }
    public HttpResponseMessage DeleteProduct(int id){ }
}

下面是一些可能的 HTTP 请求,以及为每个请求调用的操作:

HTTP 谓词 URI 路径 操作 参数
GET api/products GetAllProducts (none)
GET api/products/4 GetProductById 4
DELETE api/products/4 DeleteProduct 4
POST api/products (不匹配)

请注意,URI 的 {id} 段(如果存在)映射到操作的 id 参数。 在此示例中,控制器定义了两个 GET 方法,一个具有 id 参数,一个没有参数。

另请注意,POST 请求将失败,因为控制器未定义“Post...”方法。

路由变体

上一部分介绍了 ASP.NET Web API的基本路由机制。 本节介绍一些变体。

HTTP 谓词

可以通过使用以下属性之一修饰操作方法来显式指定操作的 HTTP 谓词,而不是对 HTTP 谓词使用命名约定:

  • [HttpGet]
  • [HttpPut]
  • [HttpPost]
  • [HttpDelete]
  • [HttpHead]
  • [HttpOptions]
  • [HttpPatch]

在以下示例中 FindProduct , 方法映射到 GET 请求:

public class ProductsController : ApiController
{
    [HttpGet]
    public Product FindProduct(id) {}
}

若要允许一个操作使用多个 HTTP 谓词,或允许 GET、PUT、POST、DELETE、HEAD、OPTIONS 和 PATCH 以外的 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() { ... }

深入阅读

本主题提供了路由的高级视图。 有关详细信息,请参阅 路由和操作选择,其中准确描述了框架如何将 URI 与路由匹配、选择控制器,然后选择要调用的操作。