- A+
所属分类:.NET技术
一、什么是WebAPI?
1.1-什么是WebAPI?
WebAPI是一种用开发系统接口、设备接口API的技术,基于Http协议,请求和返回格式默认是Json格式。比WCF简单、更通用;比WebService更节省流量,更简洁。
1.2-WebAPI的特点?
- Action方法直接返回对象,专注于数据
- 更符合Restful的风格
- 有利于独立于IIS部署
- Action可以直接声明为async
二、什么是Restful?
2.1-传统的Http接口怎么设计?
2.2-Http设计之初"谓词语义"?
- GET:查询获取
- POST:添加
- Put:修改
- Delete:删除
2.3-Http设计之初"谓词语义"带来的好处是什么?
- 为不同的请求做不同的权限的控制;
- 不需要"Delete","AddNew"这样的Action名字,根据请求的类型就可以判断
- 返回报文的格式也确定,不用在约定返回状态码,充分利用Http状态码
- 有利于系统优化,浏览器可以自动缓存Get请求
- Get没有副作用,是幂等的,可以重试。
注意:返回结果尽量根据Http状态码返回。
三、简单的WebAPI(.NET Framework)
3.1-简单WebAPI和是使用异步方式调用
/// <summary> /// 需要继承自ApiController /// </summary> public class PersonController : ApiController { public string[] Get() { return new string[] { "西瓜程序猿", "Albert" }; } public string Get(int id) { return $"Haha:" + id; } public string Get(string name) { return name; } } }
3.2-WebAPI的参数
3.3-WebAPI的返回值
/// <summary> /// HttpResponseMessage类型 /// 返回报文头、内容等等信息(控制相应的内容) /// </summary> /// <returns></returns> [HttpGet] [Route("Test3")] public HttpResponseMessage Test3() { HttpResponseMessage msg = new HttpResponseMessage(); msg.Content =new StringContent( "报文体"); msg.Headers.Add("Haha", "这是请求头体"); msg.StatusCode = System.Net.HttpStatusCode.OK; msg.Headers.Age = TimeSpan.FromDays(3); return msg; }
3.4-通过自定义路由处理API多版本
3.5-通过ControllerSelector实现多版本(配置路由规则)
(1)创建2个版本控制器
(2)在【WebApiConfig】的Register中,添加1个路由规则,并替换IHttpControllerSelector
config.Routes.MapHttpRoute( name: "DefaultApiV1", routeTemplate: "api/v1/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); //添加一个路由规则 config.Routes.MapHttpRoute( name: "DefaultApiV2", routeTemplate: "api/v2/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); //替换 config.Services.Replace(typeof(IHttpControllerSelector), new VersionControllerSelector(config));
(3)VersionControllerSelector.cs代码如下:
namespace Demo { /// <summary> /// 用来控制API版本 /// 需要继承自DefaultHttpControllerSelector /// </summary> public class VersionControllerSelector : DefaultHttpControllerSelector { private readonly HttpConfiguration _config; private IDictionary<string, HttpControllerDescriptor> _ctlMapping; public VersionControllerSelector(HttpConfiguration config) : base(config) { this._config = config; } public override IDictionary<string, HttpControllerDescriptor> GetControllerMapping() { Dictionary<string, HttpControllerDescriptor> dict = new Dictionary<string, HttpControllerDescriptor>(); //加载所有程序集,然后遍历 foreach (var asm in _config.Services.GetAssembliesResolver().GetAssemblies()) { //获得程序集所有的类,并且该类不是抽象类,并且继承自ApiController var controllerTypes = asm.GetTypes().Where(u => u.IsAbstract == false && typeof(ApiController).IsAssignableFrom(u)); //遍历并生成名字 foreach (var ctrlType in controllerTypes) { string ctrolTypeNS = ctrlType.Namespace;//获取命名空间名称 var match = Regex.Match(ctrolTypeNS, @".v(d)");//获得需要的名称 if (!match.Success) { continue; } string verNum = match.Groups[1].Value;//拿到版本号1提取出来 string ctrlTypeName = ctrlType.Name;//拿到类名(PersonController) //拿到匹配的类型 var matchController = Regex.Match(ctrlTypeName, @"^(.+)Controller$"); if (!matchController.Success) { continue; } string ctrlName = matchController.Groups[1].Value;//得到合法的PersonController string key = ctrlName + "v" + verNum; dict[key] = new HttpControllerDescriptor(_config, ctrlName,ctrlType); } } _ctlMapping = dict; return dict; } public override HttpControllerDescriptor SelectController(HttpRequestMessage request) { //拿到controller string controller =(string)request.GetRouteData().Values["controller"]; if (_ctlMapping == null) { //调用之前的方法拿到,key/value _ctlMapping = GetControllerMapping(); } // /api/v1/person var matchVer = Regex.Match(request.RequestUri.PathAndQuery, @"/v(d+)/"); if (!matchVer.Success) { //我处理不了,让父类处理 return base.SelectController(request); } string verNum = matchVer.Groups[1].Value;//2 string key = controller + "v" + verNum; if (_ctlMapping.ContainsKey(key)) { return _ctlMapping[key]; } else { //我处理不了,让父类处理 return base.SelectController(request); } } } }
3.6-WebAPI中Filter-简单判断是否授权
(1)新建一个类。
(2)类的代码如下:
namespace Demo.Filter { public class MyAuthorFilter : IAuthorizationFilter { public bool AllowMultiple => true; public async Task<HttpResponseMessage> ExecuteAuthorizationFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation) { IEnumerable<string> userNames; if (!actionContext.Request.Headers.TryGetValues("UserName", out userNames)){ //返回未授权状态码 return new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized); }; string userName = userNames.First(); if (userName == "admin") { return await continuation(); } else { //返回未授权状态码 return new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized); } } } }
(3)在【WebApiConfig.cs】的Register方法进行注册自定义的Filter。
//注册自己写的Filter config.Filters.Add(new MyAuthorFilter());
3.7-WebAPI的异常处理
系统错误:
业务错误:
3.8-接口的安全性问题
3.9-JWT介绍
3.10-接口安全传输