如何创建Controller这里就不说了,只写一些可能是高阶知识的内容
关于WebApi的官方介绍及示例 http://www.asp.net/web-api/
1.跨域
Asp.NET有专门的跨域扩展,需要通过nuget下载
然后webApiConfig中开启对CORS的支持
public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.EnableCors(); /* ... */ } }
最后是在想要支持跨域的Controller或Action上加上跨域支持特性 [EnableCors("*", "*", "*")]
上述代码只使用了特性的三个参数,先后是origins,headers,methods,用来限制来源和verb等相关信息。还可以通过设置SupportsCredentials,让凭据(Cookie)也可以发送到服务端
做了这些操作,就可以跨域获取数据了
2.生命周期
这里有一片关于WebApi生命周期的图文,相当不错 WEB API 2 HTTP消息生命周期
3.自动生成文档
有了Api自然就要有Api文档。
一般我们都是需要手动添加的,但是微软的WebApi提供自动生成WebApi文档功能 官方示例
如果创建的是MVC4以上的项目,帮助模板不需要用户自己创建,自动就会生成 路径是 /Areas/HelpPage
该帮助模块不仅可以通过IApiExplorer动态获取到所有WebApi(集成自ApiController的类)的相关信息:输入输出的数据注释、类型信息,而且还提供了不错的前端模板.
按照Controller分组显示Action列表
点击某个Action可以查看其详细信息,包括方法的Summary、字段介绍、返回数据的格式示例(根据返回数据类型动态生成)
HelpPages不仅可以随着新建项目自动生成,也可以手动添加到已存在的项目。
- 通过NuGet添加 Microsoft.AspNet.WebApi.HelpPage 到目标项目
- 将HelpPage区域注册到应用程序域
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); // ... }
- 找到文件 /Areas/HelpPage/App_Start/HelpPageConfig.cs ,并取消下面这句代码的注释(默认这行代码是被注释掉的)
config.SetDocumentationProvider(new XmlDocumentationProvider(HttpContext.Current.Server.MapPath("~/App_Data/XmlDocument.xml")));
- 打开该项目的属性窗口-》生成-》输出;将【XML文档文件】选中,输入框中填写 App_Data/XmlDocument.xml
注:除了用微软自带的HelpPage做自动文档生成,还可以选择强大的Swagger: Github,DEMO,http://blog.csdn.net/huwei2003/article/details/50501977
4.路由
4.1 路由模板
路由操作有三个阶段
- 根据Uri查找匹配的路由模板
- 查找Controller
- 查找Action
我们编写的路由存放在WebApiConfig.cs文件中,基本是这样子的
routes.MapHttpRoute( name: "API Default", routeTemplate: "api/{controller}/{area}/{id}", defaults: new { id = RouteParameter.Optional,area="China" }, constraints:new {id = @"d+"} );
4.2 默认选项
其中 defaults: new { id = RouteParameter.Optional ,area="China"} 的作用
- 将id设为可选项,api/users/china/1 与 api/users/china 都匹配路由模板
- 为area设定默认值 即 api/users 等效于 api/users/area
此外还可以通过 constraints 为路由设定约束,例子中的条件是只有数字才会被匹配
当某个路由被匹配到了之后,就开始查找Controller和Action,
- 查找Controller:Web API 会添加"Controller" 到 {controller} 匹配的内容后面,如controller是user 则会寻找UserController.
- 查找Action:Web API会根据优先级进行查询,依次是 ①HTTP method;②以 HTTP method 开头的action.例如一个GET请求, Web API 会查找类似于 "GetContact" ,"GetAllContacts"的action. 这个转换只适用于 GET, POST, PUT, DELETE. 通过特性还可以支持其他 HTTP methods.
- 其他路由模板中的占位符变量, 例如 {id}会映射到Action方法中的参数.
4.3 路由字典
如果框架找到一个能够匹配URI的路由,会创建一个包含每一个占位符的字典。字典的键是占位符名称,
字典的值来源于URI匹配的路径或者模板中设置的默认值,然后字典会被存到IHttpRouteData对象中
4.4 选择Controller
控制器的选择是由IHttpControllerSelector.SelectController处理的。这个方法要输入一个HttpRequestMessage实例并返回一个HttpControllerDescriptor对象。具体的默认实现类是DefaultHttpControllerSelector,算法也比较简单:
- 在路由字典中查找键"controller"
- 在找到的值后面追加字符串“Controller”,以此获取控制器的类名
- 根据这个类名查找WebApi的控制器
- 如果没有匹配的类型,或者匹配到多个,则框架会向客户端返回错误
在第三步 DefaultHttpControllerSelector 使用IHttpControllerTypeResolver 接口来获取WebApi控制器的类型列表。IHttpControllerTypeResolver的默认实现会返回所有实现了IHttpController接口的公共类,并且不是虚类,类名以"Controller"为后缀。
4.5 选择Action
查找到Controller之后,框架通过调用IHttpActionSelector.SelectAction方法选择action(输入HttpControllerContext,返回HttpActionDescriptor)。
这个操作的默认实现是由类ApiControllerActionSelector提供,大体逻辑:
- 请求的HttpMethod
- 如果有的话,获取路由模板中的占位符"{action}"
- 控制器下action的参数
先了解一些关于action的事情
①controller类里面哪些方法会被认为是action?
当查找action时,框架只会筛选公共方法,并且还要排除掉特殊名称的方法(contructors,events,operator,overloads..),所在Controller要继承自ApiController类。
②关于Http Method
-
我们可以通过特性来制定action支持的Http Method:AcceptVerbs, HttpDelete, HttpGet, HttpHead, HttpOptions, HttpPatch,HttpPost, HttpPut.
- 如果没有指定HttpMethod特性,并且action方法名以"Get","Post","Put","Delete","Head","Option","Patch"开头,那么按照约定这个action这支持该Http method
- *如果没有符合上面两条,那么这个方法支持POST
③参数绑定 即WebApi通过请求为action方法的参数创建一个值;以下是参数绑定的默认规则:
- 简单类型(所有.NET的基本类型,DateTime,Decimal,Guid,String,TimeSpan)会从URI获取
- 复合类型从请求体(Request Body)获取,每一个action最多能从请求体获取一个参数
4.6 扩展点
Web API提供了路由过程中的一部分扩展点.
接口 | 作用 |
---|---|
IHttpControllerSelector | 选择 controller. |
IHttpControllerTypeResolver | 获取controller类型列表. DefaultHttpControllerSelector 从该列表中选择controller类型 |
IAssembliesResolver | 获取项目程序集列表. IHttpControllerTypeResolver通过该列表查找controller 类型. |
IHttpControllerActivator | 创建一个新的 controller 实例. |
IHttpActionSelector | 选择 action. |
IHttpActionInvoker | 调用 action. |
如果自己实现了上述某个接口的话,可以使用HttpConfiguration对象的Services集合.(Global.asax.cs)
var config = GlobalConfiguration.Configuration; config.Services.Replace(typeof(IHttpControllerSelector), new MyControllerSelector(config));
翻译: