欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

【Web API系列教程】2.1 — ASP.NET Web API中的路由机制

程序员文章站 2022-04-14 10:16:00
这篇文章描述了asp.net web api如何将http请求发送(路由)到控制器。 备注:如果你对asp.net mvc很熟悉,你会发现web api路由和mvc路由非常相似。主要区别是web a...

这篇文章描述了asp.net web api如何将http请求发送(路由)到控制器。

备注:如果你对asp.net mvc很熟悉,你会发现web api路由和mvc路由非常相似。主要区别是web api使用http方法来选择动作(action),而不是uri路径。你也可以在web api中使用mvc风格的路由。这篇文章不需要asp.net mvc的任何知识。

路由表

在asp.net web api中,控制器是一个用于处理http请求的类。控制器中的公共方法被称为动作方法或简单动作。当web api框架收到请求时,它会将该请求路由到相应的动作中。

为了确定哪个动作该被执行,框架就会使用本节将讲解的路由表。visual studio的web api项目模板就创建了一个默认的路由表:

routes.maphttproute(
    name: "api default",
    routetemplate: "api/{controller}/{id}",
    defaults: new { id = routeparameter.optional }
);

这个路由被定义在app_start目录下的wepapiconfig.cs文件中。

【Web API系列教程】2.1 — ASP.NET 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”添加到{controller}变量上。 为了找到动作,web api会遍历http方法,然后查找一个其名字以http方法的名字开头的动作。例如,有一个get请求,web api会查找以“get….”开头的动作,比如”getcontact”或”getallcontacts”。这种方式仅仅适用于get、post、put和delete方法。你可以通过在你的控制器中使用属性来启用其他http方法。将晚些看到一个示例(超链接到本章的第三节…… 路由模板的其他占位符变量,比如{id},会被映射到动作的参数。

让我们来看一个示例。假定你定义了如下的控制器:

public class productscontroller : apicontroller
{
    public void getallproducts() { }
    public ienumerable getproductbyid(int id) { }
    public httpresponsemessage deleteproduct(int id){ }
}

这里是一些可能的http请求,以及相应的得到执行的动作:

http method uri path action parameter
get api/products getallproducts (none)
get api/products/4 getproductbyid 4
delete api/products/4 deleteproduct 4
post api/products (no match)  

注意uri的{id}字段,如果存在,它会被映射到动作的id参数中。在本例,控制器定义了两个get方法,其中一个包含id参数,而另一个不包含id参数。

同样的,注意到post请求会失败,因为控制器中并没有定义”post…”方法。

路由偏差(routing variations)

前一节描述了asp.net web api的基本路由机制。本节将开始描述一些变化。

http方法

除了使用这些http方法的命名约定,你也可以通过用httpget、httpput、httppost或httpdelete属性来赋予这些动作来具体地为每个动作设定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);
}

无动作(non-actions)

为了阻止一个方法被当作动作来执行,可以使用nonaction属性。这会框架指明该方法并非一个动作,即使是它可能匹配到路由规则。

// not an action method.
[nonaction]  
public string getprivatedata() { ... }