使Web API支持二级实体操作,兼对RESTFul风格API设计的疑惑。
最近一直在纠结应该创建RESTFul风格的API还是以前那种函数调用风格的API。如果创建RESTFul风格的API,又有很多设计问题有待理清,这暂且不论,在用Web API创建RESTFul风格的API的时候,对于二级实体操作又该如何设计API接口呢?比如一个Client实体,它有很多属于它的Order实体,而每个Order实体又有很多Product实体,API接口如何设计才能更好的体现这种关系和操作呢?如果大家对此有想法,欢迎留言为我解惑。
我目前尝试设计和实现一种层次性的API接口,我不确定这是否是最佳的做法,调用的时候看起来是这样的:
Route看起来是这样的:
/api/{controller}/{id}/{subController1}/{subID1}/{subController2}/{subID2}
当然,需要的话,可以继续往后追加subController3,4,5,6...
而Controller应该看起来是什么样子的呢?我的做法是,分别为Client、Order和Product建立Controller:
ClientsController
ClientsOrdersController
ClientsOrdersProductsConroller
这样我可以将以上3个Controller的名字映射到{controller}、{subController1}、{subController2},抽象一点说,就是Controller名字的每一部分对应映射中的一个{controller}/{subcontrollerX}.
剩下的一个问题就是如何让MVC引擎能将这个路由映射到正确的Controller上。我们都知道(其实我们不都知道,包括在研究这个问题之前的我),MVC引擎根据路由找Controller的操作之一要靠IHttpControllerSelector接口,默认情况下具体干活的就是DefaultHttpControllerSelector类,我要做的就是继承这个类,然后从路由数据中查看那些subController参数是否被映射上的具体数据,如果没有,就调用默认行为,如果有,就把所有的controller参数的值拼接成真正的controller名字返回,代码如下:
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Web.Http;
5 using System.Web.Http.Dispatcher;
6 using System.Net.Http;
7 using System.Web.Http.Routing;
8
9 namespace Ricky
10 {
11 public class HttpControllerSelectorEx : DefaultHttpControllerSelector
12 {
13 private HttpConfiguration _HttpCfg;
14
15 public HttpControllerSelectorEx(HttpConfiguration cfg)
16 : base (cfg)
17 {
18 _HttpCfg = cfg;
19 }
20
21 public override string GetControllerName(HttpRequestMessage request)
22 {
23 string name = base .GetControllerName(request);
24 IHttpRouteData routeData = request.GetRouteData();
25 IEnumerable<KeyValuePair< string , object >> subControllers = routeData.Values
26 .Where(d => d.Key.StartsWith( " subController " , StringComparison.CurrentCultureIgnoreCase));
27 if (subControllers.Count() == 0 )
28 return name;
29
30 List< string > names = new List< string >( 1 + subControllers.Count());
31 names.Add(name);
32 foreach (KeyValuePair< string , object > subController in subControllers)
33 {
34 names.Add(subController.Value.ToString());
35 }
36
37 return string .Join( "" , names);
38 }
39 }
40 }
完成之后需要用我们的controller selector替换系统的默认设置。这在Global.asax.cs的Application_Start方法中做:
1 GlobalConfiguration.Configuration.Services.Replace( typeof (IHttpControllerSelector) 2 , new Ricky.HttpControllerSelectorEx(GlobalConfiguration.Configuration));
最后,我们修改一下路由设置:
1 public static void Register(HttpConfiguration config)
2 {
3 config.Routes.MapHttpRoute(
4 name: " DefaultApiWithSubControllers " ,
5 routeTemplate: " api/{controller}/{id}/{subController}/{subID}/{subController2}/{subID2} " ,
6 defaults: new
7 {
8 id = RouteParameter.Optional,
9 subController = RouteParameter.Optional,
10 subID = RouteParameter.Optional,
11 subController2 = RouteParameter.Optional,
12 subID2 = RouteParameter.Optional
13 }
14 );
15
16 // config.Routes.MapHttpRoute(
17 // name: "DefaultApi",
18 // routeTemplate: "api/{controller}/{id}",
19 // defaults: new { id = RouteParameter.Optional }
20 // );
21 }
由于我们的路由设置其实是扩展默认设置的,因此可以注释掉原来的默认设置。
理解的越多,需要记忆的就越少
分类: ASP.NET
作者: Leo_wl
出处: http://HdhCmsTestcnblogs测试数据/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息查看更多关于使Web API支持二级实体操作,兼对RESTFul风格API设计的疑惑。的详细内容...