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

(编辑:jimmy 日期: 2024/10/15 浏览:2)

以下为常规MVC路由

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

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

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

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

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

 config.MapHttpAttributeRoutes();

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

 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+"}
      );
    }

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

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

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

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

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

  [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 之属性路由

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

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

结果

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

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

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

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

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;
  }
}

注册约束

public static class WebApiConfig
{
  public static void Register(HttpConfiguration config)
  {
    var constraintResolver = new DefaultInlineConstraintResolver();
    constraintResolver.ConstraintMap.Add("nonzero", typeof(NonZeroConstraint));

    config.MapHttpAttributeRoutes(constraintResolver);
  }
}

使用约束

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

可选的URI参数和默认值

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

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

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

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

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

一句话新闻

一文看懂荣耀MagicBook Pro 16
荣耀猎人回归!七大亮点看懂不只是轻薄本,更是游戏本的MagicBook Pro 16.
人们对于笔记本电脑有一个固有印象:要么轻薄但性能一般,要么性能强劲但笨重臃肿。然而,今年荣耀新推出的MagicBook Pro 16刷新了人们的认知——发布会上,荣耀宣布猎人游戏本正式回归,称其继承了荣耀 HUNTER 基因,并自信地为其打出“轻薄本,更是游戏本”的口号。
众所周知,寻求轻薄本的用户普遍更看重便携性、外观造型、静谧性和打字办公等用机体验,而寻求游戏本的用户则普遍更看重硬件配置、性能释放等硬核指标。把两个看似难以相干的产品融合到一起,我们不禁对它产生了强烈的好奇:作为代表荣耀猎人游戏本的跨界新物种,它究竟做了哪些平衡以兼顾不同人群的各类需求呢?