使Web API支持二级实体操作,兼对RESTFul风格API设计的疑惑。
2013-01-24 15:02
453 查看
最近一直在纠结应该创建RESTFul风格的API还是以前那种函数调用风格的API。如果创建RESTFul风格的API,又有很多设计问题有待理清,这暂且不论,在用Web API创建RESTFul风格的API的时候,对于二级实体操作又该如何设计API接口呢?比如一个Client实体,它有很多属于它的Order实体,而每个Order实体又有很多Product实体,API接口如何设计才能更好的体现这种关系和操作呢?如果大家对此有想法,欢迎留言为我解惑。
我目前尝试设计和实现一种层次性的API接口,我不确定这是否是最佳的做法,调用的时候看起来是这样的:
/api/Clients/123/Orders/456/Products/789
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名字返回,代码如下:
完成之后需要用我们的controller selector替换系统的默认设置。这在Global.asax.cs的Application_Start方法中做:
最后,我们修改一下路由设置:
由于我们的路由设置其实是扩展默认设置的,因此可以注释掉原来的默认设置。
我目前尝试设计和实现一种层次性的API接口,我不确定这是否是最佳的做法,调用的时候看起来是这样的:
/api/Clients/123/Orders/456/Products/789
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名字返回,代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Web.Http; using System.Web.Http.Dispatcher; using System.Net.Http; using System.Web.Http.Routing; namespace Ricky { public class HttpControllerSelectorEx : DefaultHttpControllerSelector { private HttpConfiguration _HttpCfg; public HttpControllerSelectorEx(HttpConfiguration cfg) : base(cfg) { _HttpCfg = cfg; } public override string GetControllerName(HttpRequestMessage request) { string name = base.GetControllerName(request); IHttpRouteData routeData = request.GetRouteData(); IEnumerable<KeyValuePair<string, object>> subControllers = routeData.Values .Where(d => d.Key.StartsWith("subController", StringComparison.CurrentCultureIgnoreCase)); if (subControllers.Count() == 0) return name; List<string> names = new List<string>(1 + subControllers.Count()); names.Add(name); foreach (KeyValuePair<string,object> subController in subControllers) { names.Add(subController.Value.ToString()); } return string.Join("", names); } } }
完成之后需要用我们的controller selector替换系统的默认设置。这在Global.asax.cs的Application_Start方法中做:
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerSelector) , new Ricky.HttpControllerSelectorEx(GlobalConfiguration.Configuration));
最后,我们修改一下路由设置:
public static void Register(HttpConfiguration config) { config.Routes.MapHttpRoute( name: "DefaultApiWithSubControllers", routeTemplate: "api/{controller}/{id}/{subController}/{subID}/{subController2}/{subID2}", defaults: new { id = RouteParameter.Optional, subController = RouteParameter.Optional, subID = RouteParameter.Optional, subController2 = RouteParameter.Optional, subID2 = RouteParameter.Optional } ); //config.Routes.MapHttpRoute( // name: "DefaultApi", // routeTemplate: "api/{controller}/{id}", // defaults: new { id = RouteParameter.Optional } //); }
由于我们的路由设置其实是扩展默认设置的,因此可以注释掉原来的默认设置。
相关文章推荐
- 使Web API支持二级实体操作,兼对RESTFul风格API设计的疑惑。
- Web API 入门系列 - RESTful API 设计指南
- RESTful API设计风格(1)
- 通俗易懂RESTful,如何设计RESTful风格API
- 【API设计风格—RESTful】:什么是RESTful(一)
- 【API设计风格—RESTful】:前端如何调用RESTful风格的API(三)
- 【API设计风格—RESTful】:番外篇:跨域问题(四)
- SSM用restful风格设计API
- restful 风格API 设计 403错误
- restful Api 风格契约设计器:Swagger-editor和swagger-ui的应用
- Restful风格API中用put还是post做新增操作有什么区别?
- 【API设计风格—RESTful】:什么是RESTful(一)
- RESTful 良好的API设计风格
- 【API设计风格—RESTful】:服务端如何编写RESTful风格的API(二)
- Restful风格API中用put还是post做新增操作有什么区别?
- flask, SQLAlchemy, sqlite3 实现 RESTful API 的 todo list, 同时支持form操作
- 移动互联网实战--Web Restful API设计和基础架构
- restful 风格api
- springmvc restful风格支持
- (ZZ)我所理解的RESTful Web API [设计篇]