详解ASP.NET WEB API 之属性路由

时间:2022-09-13 14:53:05

以下为常规MVC路由

?
1
2
3
4
5
config.Routes.MapHttpRoute(
       name: "DefaultApi",
       routeTemplate: "api/{controller}/{id}",
       defaults: new { id = RouteParameter.Optional },
     );

如果我们要实现类似以下效果路由的话,使用常规公约路由比较麻烦。

?
1
2
order/Miles/三只松鼠干果/2袋
order/2017/1/13

如果使用属性路由的话就比较简单了。

新建WEB API项目的话,打开App_Start目录下的WebApiConfig.cs文件添加以下代码开启属性路由配置。

?
1
config.MapHttpAttributeRoutes();

属性路由也可以和公约路由混合使用,如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void Register(HttpConfiguration config)
   {
     // Web API 配置和服务
 
     // Web API 路由
     config.MapHttpAttributeRoutes();
 
     config.Routes.MapHttpRoute(
       name: "DefaultApi",
       routeTemplate: "api/{controller}/{id}",
       defaults: new { id = RouteParameter.Optional },
       constraints: new { id=@"\d+"}
     );
   }

在要使用属性路由的方法上打上特性标记,如下 :

?
1
[Route("order/{UserNickName}/{ProductName}/{count}")]

测试结果(URL经过了编码,不然会报400错误。)

详解ASP.NET WEB API 之属性路由

通常情况下,在同一个控制器中的所有路由以相同的前缀开头

?
1
2
3
[Route("api/books")]
[Route("api/books/{id:int}")]
[Route("api/books")]

这样很明显是比较麻烦的。所以我们用[RoutePrefix]属性来设置一个公共的前缀

详解ASP.NET WEB API 之属性路由

测试结果

详解ASP.NET WEB API 之属性路由

如果使用了[RoutePrefix]的话,某些比较特殊的api,我们可以使用波浪线来重写路由前缀,如下:

详解ASP.NET WEB API 之属性路由

测试结果(同一个类下)

详解ASP.NET WEB API 之属性路由

路由前缀中也可以包含参数,如下

详解ASP.NET WEB API 之属性路由

测试结果

详解ASP.NET WEB API 之属性路由

可以在路由中添加参数约束,如下

详解ASP.NET WEB API 之属性路由

测试结果

详解ASP.NET WEB API 之属性路由

如果参数不是Int类型,则不会匹配到该路由

以下都是一些会被支持到的约束

详解ASP.NET WEB API 之属性路由

可以使用多个约束,但是要用冒号分开

?
1
2
[Route("users/{id:int:length(1,3)}")]
public User GetUserById(int id) { ... }

结果

详解ASP.NET WEB API 之属性路由

如果不在范围内的话则匹配不到

详解ASP.NET WEB API 之属性路由

自定义路由约束,需要实现IHttpRouteConstraint接口,具体查看官方

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class NonZeroConstraint : IHttpRouteConstraint
{
  public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName,
    IDictionary<string, object> values, HttpRouteDirection routeDirection)
  {
    object value;
    if (values.TryGetValue(parameterName, out value) && value != null)
    {
      long longValue;
      if (value is long)
      {
        longValue = (long)value;
        return longValue != 0;
      }
 
      string valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
      if (Int64.TryParse(valueString, NumberStyles.Integer,
        CultureInfo.InvariantCulture, out longValue))
      {
        return longValue != 0;
      }
    }
    return false;
  }
}

注册约束

?
1
2
3
4
5
6
7
8
9
10
public static class WebApiConfig
{
  public static void Register(HttpConfiguration config)
  {
    var constraintResolver = new DefaultInlineConstraintResolver();
    constraintResolver.ConstraintMap.Add("nonzero", typeof(NonZeroConstraint));
 
    config.MapHttpAttributeRoutes(constraintResolver);
  }
}

使用约束

?
1
2
[Route("{id:nonzero}")]
public HttpResponseMessage GetNonZero(int id) { ... }

可选的URI参数和默认值

你可以通过添加一个问号标记路由参数使成为一个可选的URI参数。如果一个路由参数是可选的,你必须为这个方法参数定义一个默认值。

?
1
2
3
4
5
public class BooksController : ApiController
{
  [Route("api/books/locale/{lcid:int?}")]
  public IEnumerable<Book> GetBooksByLocale(int lcid = 1033) { ... }
}

或者在路由模版中定义默认值

?
1
2
3
4
5
public class BooksController : ApiController
{
  [Route("api/books/locale/{lcid=1033}")]
  public IEnumerable<Book> GetBooksByLocale(int lcid) { ... }
}

差不多写这么多常用的,剩余部分自己查看官网!希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:http://www.jianshu.com/p/4430cbc57a26#