C# 《Asp.Net Web Api 》-----路由机制 转

《Asp.Net Web Api 》-----路由机制
https://blog.csdn.net/zhoukun1008/article/details/52704651

    前言

   上一篇文章小编大体说了一下WebApi的简单应用程序,今天小编跟大家来讨论一下WebApi中的路由。如果你熟悉ASP.NET MVC,Web API路由与MVC路由十分类似。主要差别是Web API使用HTTP方法而不是URI路径来选择动作。你也可以在Web API中使用MVC风格的路由。

   1、路由表

   在ASP.NET Web API中,一个控制器是处理HTTP请求的一个类。控制器的public方法称为动作方法(action methods)或简称为动作(action)。当Web API框架接收到一个请求时,它将这个请求路由到一个动作。

   为了确定调用哪一个动作,框架使用了一个路由表(routing table)。Visual Studio中Web API的项目模板会创建一个默认路由,这条路由是在WebApiConfig.cs文件中定义的,该文件位于App_Start目录。

   

  1. public static void Register(HttpConfiguration config)
  2. {
  3. config.Routes.MapHttpRoute(
  4. name: "DefaultApi",
  5. routeTemplate: "api/{controller}/{id}",
  6. defaults: new { id = RouteParameter.Optional }
  7. );
  8. config.EnableSystemDiagnosticsTracing();
  9. }

   路由表中的每一个条目都包含一个路由模板(route template)。Web API的默认路由模板是“api/{controller}/{id}”。在这个模板中,“api”是一个文字式路径片段,而{controller}和{id}则是占位符变量。

   当Web API框架接收一个HTTP请求时,它会试图根据路由表中的一个路由模板来匹配其URI。如果无路由匹配,客户端会接收到一个404(未找到)错误。例如,以下URI与这个默认路由的匹配:

  • /api/contacts
  • /api/contacts/1
  • /api/products/gizmo1

   在路由中使用“api”的原因是为了避免与ASP.NET MVC的路由冲突。通过这种方式,可以用“/contacts”进入一个MVC控制器,而“/api/contacts”进入一个Web API控制器。当然,如果你不喜欢这种约定,可以修改这个默认路由表。

   一旦找到了匹配路由,Web API便会选择相应的控制和动作:为了找到控制器,Web API会把“控制器”加到{controller}变量的值(意即,把URI中的“控制器”作为{controller}变量的值)。为了找到动作,Web API会考查HTTP方法,然后寻找一个名称以HTTP方法名开头的动作。例如,对于一个GET请求,Web API会查找一个以“Get…”开头的动作,如“GetProduct”或“GetAllProduct”等。这种约定仅运用于GET、POST、PUT和DELETE方法。通过把注解属性运用于控制器,你可以启用其它HTTP方法。后面会看到一个例子。路由模板中的其它占位变量,如{id},被映射成动作参数。

   2、Demo    

  1. public class WebApiController : ApiController
  2. {
  3. /// <summary>
  4. /// 定义一个产品数据
  5. /// </summary>
  6. Product[] products = new Product[]
  7. {
  8. new Product { Id = 1, Name = "农夫山泉", Category = "water", Price = 2 },
  9. new Product { Id = 2, Name = "钢笔", Category = "study", Price = 3.75M },
  10. new Product { Id = 3, Name = "烤肠", Category = "food", Price = 1 },
  11. new Product { Id = 4, Name = "崂山矿泉水", Category = "water", Price = 2 },
  12. new Product { Id = 5, Name = "铅笔", Category = "study", Price = 3.75M },
  13. new Product { Id = 6, Name = "烤羊肉串", Category = "food", Price = 1 }
  14. };
  15. /// <summary>
  16. /// 得到所有的产品
  17. /// </summary>
  18. /// <returns></returns>
  19. public IEnumerable<Product> GetAllProducts()
  20. {
  21. return products;
  22. }
  23. /// <summary>
  24. /// 根据id查询产品
  25. /// </summary>
  26. /// <param name="id">产品id</param>
  27. /// <returns></returns>
  28. public Product GetProductById(int id)
  29. {
  30. var product = products.FirstOrDefault((p) => p.Id == id);
  31. if (product == null)
  32. {
  33. throw new HttpResponseException(HttpStatusCode.NotFound);
  34. }
  35. return product;
  36. }
  37. /// <summary>
  38. /// 根据产品种类查询产品
  39. /// </summary>
  40. /// <param name="category">产品种类</param>
  41. /// <returns></returns>
  42. public IEnumerable<Product> GetProductsByCategory(string category)
  43. {
  44. return products.Where(
  45. (p) => string.Equals(p.Category, category,
  46. StringComparison.OrdinalIgnoreCase));
  47. }
  48. /// <summary>
  49. /// 根据id删除
  50. /// </summary>
  51. /// <param name="id"></param>
  52. /// <returns></returns>
  53. public List<int> DeleteProductById(int id)
  54. {
  55. List<int> p = new List<int>();
  56. for (int i = 0; i < 6; i++)
  57. p.Add(i);
  58. p.Remove(id);
  59. if (p == null)
  60. {
  61. throw new HttpResponseException(HttpStatusCode.NotFound);
  62. }
  63. return p;
  64. }
  65. /// <summary>
  66. /// 根据id增加
  67. /// </summary>
  68. /// <param name="id"></param>
  69. /// <returns></returns>
  70. public List<int> PostProductById(int id)
  71. {
  72. List<int> p = new List<int>();
  73. for (int i = 0; i < id; i++)
  74. p.Add(i);
  75. if (p == null)
  76. {
  77. throw new HttpResponseException(HttpStatusCode.NotFound);
  78. }
  79. return p;
  80. }
  81. }

  我们启动程序后,可以继续使用Postman测试这几个方法。  

   其它的几个测试方法我省略。现在我们更改一下路由表,使其根据Controller 来确定访问哪个类,根据Action来确定访问哪个方法。    

  1. public static void Register(HttpConfiguration config)
  2. {
  3. config.Routes.MapHttpRoute(
  4. name: "DefaultApi",
  5. routeTemplate: "{controller}/{action}/{id}",
  6. defaults: new { id = RouteParameter.Optional }
  7. );
  8. config.EnableSystemDiagnosticsTracing();
  9. }

  对应的方法:  

  1. public class RouteDemoController : ApiController
  2. {
  3. Product[] products = new Product[]
  4. {
  5. new Product { Id = 1, Name = "农夫山泉", Category = "water", Price = 2 },
  6. new Product { Id = 2, Name = "钢笔", Category = "study", Price = 3.75M },
  7. new Product { Id = 3, Name = "烤肠", Category = "food", Price = 1 },
  8. new Product { Id = 4, Name = "崂山矿泉水", Category = "water", Price = 2 },
  9. new Product { Id = 5, Name = "铅笔", Category = "study", Price = 3.75M },
  10. new Product { Id = 6, Name = "烤羊肉串", Category = "food", Price = 1 }
  11. };
  12. /// <summary>
  13. /// 查询所有商品
  14. /// </summary>
  15. /// <returns></returns>
  16. [HttpGet]
  17. public IEnumerable<Product> QueryAllProducts()
  18. {
  19. return products;
  20. }
  21. /// <summary>
  22. /// 根据id查询商品
  23. /// </summary>
  24. /// <param name="id"></param>
  25. /// <returns></returns>
  26. [HttpGet]
  27. public Product QueryProductById(int id)
  28. {
  29. var product = products.FirstOrDefault((p) => p.Id == id);
  30. if (product == null)
  31. {
  32. throw new HttpResponseException(HttpStatusCode.NotFound);
  33. }
  34. return product;
  35. }
  36. /// <summary>
  37. /// 根据种类查询商品
  38. /// </summary>
  39. /// <param name="category"></param>
  40. /// <returns></returns>
  41. [HttpGet]
  42. public IEnumerable<Product> QueryProductsByCategory(string category)
  43. {
  44. return products.Where(
  45. (p) => string.Equals(p.Category, category,
  46. StringComparison.OrdinalIgnoreCase));
  47. }
  48. /// <summary>
  49. /// 此动作不让请求
  50. /// </summary>
  51. [NonAction]
  52. public void PrivateData()
  53. {
  54. }
  55. }

  测试效果如下 

    

    

  这就是更改过后的路由,有时候,我们还可以使用注解属性来代替Action的使用

  1. [HttpGet]
  2. [ActionName("Test")]
  3. public Product findProductById(int id)
  4. {
  5. var product = products.FirstOrDefault((p) => p.Id == id);
  6. if (product == null)
  7. {
  8. throw new HttpResponseException(HttpStatusCode.NotFound);
  9. }
  10. return product;
  11. }

  测试结果如下

    

  3、小结

  这就是小编了解到的WebApi的路由,其实WebApi和Mvc方法中的区别是,MVC中返回的是视图的名字,而WebApi是返回的是数据。WebApi与WCF相比,WebApi比WCF重量级要小,小编所在的项目组用的就是WebApi,我们将css、HTML、AngularJS,打包成apk后,让用户按上,我们可以直接在apk中调用WebApi的服务。好了,小编总结到这吧。

原文地址:https://www.cnblogs.com/sunny3158/p/11679725.html