一、关于API的参数
a) Web API在WebApiConfig.cs中配置了路由模板,默认为"api/{controller}/{id}",这与MVC路由模板的区别在于没有{action},会根据请求方式来找到对应的方法,只要一个Action标注了[HttpGet],那么不管Action的名称如何,Get请求都会被路由到这个Action。
b)如果有GET请求为http:/***/api/Controller?user="u1"&pwd="p1",按照默认的路由配置,有效的GET方法可以是public string Login(string user, string pwd)。也可以使用[FromUri],但GET方法改为public string Login([FromUri]LoginModel model) ,将参数封装为Model并添加FromUri,FromUri只能标注一个参数,经试验也可以在使用FromUri的同时使用多个参数。
c)对于Post、Put请求,也可以像Get请求那样写在URI中,但参数比较多时最好封装起来,通过Request Body传递,同时在参数上标记[FromBody]。同样的这个标记也只能使用一次。对于POST方法public string Login2(int i,[FromBody]LoginModel model,string us) 来说,请求是在url中传递的i和us参数的顺序不限。
d)也可以模仿MVC的路由模板,配置为"api/{controller}/{action}/{id}",这样使用方式更加直观,但无法根据请求方式自动对应,且不符合REST风格。
二、WebAPI的多版本管理
有时在升级API的同时需要保留旧版本的API,不同的URL请求不同版本的API。这时可以将不同版本的API部署在不同的服务器或域名。或者放在同一个项目中,然后使用IHttpControllerSelector来区分不同的版本,代码如下:
public class VersionControllerSelector : DefaultHttpControllerSelector {
  private HttpConfiguration _config;
  public VersionControllerSelector(HttpConfiguration configuration) : base(configuration) {
    _config = configuration;
  }
  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(t => !t.IsAbstract && typeof(ApiController).IsAssignableFrom(t)).ToArray();
      foreach (var ctrlType in controllerTypes) {
        //从namespace中提取版本号
        var match = Regex.Match(ctrlType.Namespace, @"_8._1_WebAPI.Controllers.v(\d+)");
        if (match.Success) {
          string verNum = match.Groups[1].Value;
          string ctrlName = Regex.Match(ctrlType.Name, "(.+)Controller").Groups[1].Value;
          string key = ctrlName + "v" + verNum;
          dict[key] = new HttpControllerDescriptor(_config, ctrlName, ctrlType);
        }
      }
    }
    return dict;
  }

public override HttpControllerDescriptor SelectController(HttpRequestMessage request) {

var controllers = GetControllerMapping();
    //获取路由数据
    var routeData = request.GetRouteData();
    //从路由中获取当前Controller的名称
    var controllerName = (string)routeData.Values["controller"];
    //从url中获取版本号
    string verNum = Regex.Match(request.RequestUri.PathAndQuery, @"api/v(\d+)").Groups[1].Value;
    //从报文头获取版本号
    //string verNum = request.Headers.GetValues("ApiVersion").Single();
    string key = controllerName + "v" + verNum;
    return controllers.ContainsKey(key) ? controllers[key] : null;
  }
}

然后在WebApiConfig中配置两个路由模板:
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 }

最后将IHttpControllerSelector用写好的VersionControllerSelector替换就可以了
config.Services.Replace(typeof(IHttpControllerSelector), new VersionControllerSelector(config));

三、Filter
和MVC的Filter的写法基本类似,作用也一致,提供AOP功能。但人家直接按照异步形式写的。
a) IAuthorizationFilter的基本使用
public class MyAuthFilter : IAuthorizationFilter {
  public bool AllowMultiple => true;

public async Task<HttpResponseMessage> ExecuteAuthorizationFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation) {
    IEnumerable<string> values;
    if (actionContext.Request.Headers.TryGetValues("UserName", out values)) {
      var userName = values.FirstOrDefault();
      if (!userName.Equals("admin")) {
        return new HttpResponseMessage(HttpStatusCode.Unauthorized);
      }
    }
    else {
      return new HttpResponseMessage(HttpStatusCode.Unauthorized);
    }
    return await continuation();
  }
}
b) IExceptionFilter的基本使用
public class ExceptionFilter : IExceptionFilter {
  public bool AllowMultiple => false;

public async Task ExecuteExceptionFilterAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken) {
    using (StreamWriter writer = File.AppendText("d:/err.txt")) {
      await writer.WriteLineAsync(actionExecutedContext.Exception.ToString());
    }
  }
}

学习资料:如鹏网.net提高班http://www.rupeng.com/News/10/4603.shtml

Web API的参数、多版本和Filter的更多相关文章

  1. asp.net web api [FromBody]参数

    Using jQuery to POST [FromBody] parameters to Web API 时间2013-04-04 00:28:17 Encosia原文 http://encosia ...

  2. ASP.NET Web API 通过参数控制返回类型(JSON|XML)

    一个很实用的技巧,可以在访问web api服务的时候指定返回数据的格式类型,比如 json 或者 xml. 因为 web api 默认返回的是XML格式,但是现在json 比较流行,同时网上也有其他的 ...

  3. Web Api 返回参数,实现统一标准化!

    string camelCaseObj = JsonConvert.SerializeObject(data, Newtonsoft.Json.Formatting.None, new JsonSer ...

  4. Web API系列(二)接口安全和参数校验

    以前简单介绍过web api 的设计,但是还是有很多朋友问我,如何合理的设计和实现web api.比如,接口安全,异常处理,统一数据返回等问题.所以有必要系统的总结总结 web api 的设计和实现. ...

  5. 基于.Net Framework 4.0 Web API开发(2):ASP.NET Web APIs 参数传递方式详解

    概述:  ASP.NET Web API 的好用使用过的都知道,没有复杂的配置文件,一个简单的ApiController加上需要的Action就能工作.调用API过程中参数的传递是必须的,本节就来谈谈 ...

  6. Html网页使用jQuery传递参数并获取Web API的数据

    昨天Insus.NET有开始学习Web API,<ASP.NET MVC的Web Api的实练>http://www.cnblogs.com/insus/p/4334316.html .其 ...

  7. 细说 Web API参数绑定和模型绑定

    今天跟大家分享下在Asp.NET Web API中Controller是如何解析从客户端传递过来的数据,然后赋值给Controller的参数的,也就是参数绑定和模型绑定. Web API参数绑定就是简 ...

  8. .NET Core WEB API中接口参数的模型绑定的理解

    在.NET Core WEB API中参数的模型绑定方式有以下表格中的几种: 微软官方文档说明地址:https://docs.microsoft.com/zh-cn/aspnet/core/web-a ...

  9. Web API(四):Web API参数绑定

    在这篇文章中,我们将学习Web API如何将HTTP请求数据绑定到一个操作方法的参数中. 操作方法在Web API控制器中可以有一个或多个不同类型的参数.它可以是基本数据类型或复杂类型.Web API ...

随机推荐

  1. 影响 POST 请求文件上传失败的几个环节的配置(php + nginx)

    写在前面 最近写一个 php 接口,接受上传的文件,发现文件只要超过 5m 以上就会无响应失败,最后发现是 shadowsocks 的 timeout 设置问题(我全程开了全局的 VPN),但一开始并 ...

  2. Caffe 使用记录(五):math_functions 分析

    本文转载自 Caffe源码(一):math_functions 分析 math_function 定义了caffe 中用到的一些矩阵操作和数值计算的一些函数,这里以float类型为例做简单的分析 1. ...

  3. numpy中pad函数的常用方法

    一.参数解释 ndarray = numpy.pad(array, pad_width, mode, **kwargs) array为要填补的数组 pad_width是在各维度的各个方向上想要填补的长 ...

  4. Shell脚本中实现自动补全功能

    对于Linuxer来说,自动补全是再熟悉不过的一个功能了.当你在命令行敲下部分的命令时,肯定会本能地按下Tab键补全完整的命令,当然除了命令补全之外,还有文件名补全. Bash-completion ...

  5. 关于jQuery的一些东西

    1.jQuery的选择器学习     基本选择器        id选择器            $("#id名") 返回的是存储了指定的HTML元素对象的数组        标签 ...

  6. Java:类与对象概念

      什么是类? 怎样定义一个类? 什么是对象,类和对象之间是什么关系,怎样创建一个对象? 对象引用和对象在内存中是如何分配的? 什么是类? 1. 类是具有相同的属性和功能的事物的抽象的集合,在面向对象 ...

  7. Docker容器绑定外部IP和端口

    Docker允许通过外部访问容器或者容器之间互联的方式来提供网络服务. 以下操作通过myfirstapp镜像模拟,如何制作myfirstapp镜像请点击此处. 1.外部访问容器容器启动之后,容器中可以 ...

  8. Http怎么处理长连接

    http协议中有和keep alive特性,这个在http1.1中有, 可以保持浏览器和服务器之间保持着长连接,http本身是无连接的协议, 通过tcp实现数据的传输,处理长连接要注意什么时候数据服务 ...

  9. Docker启动出现"No space left on device" 或者 docker日志太多导致磁盘占满问题

    机房有一台服务器上面部署了多个docker容器, 并且每个docker容器都往stderr中源源不断的输出日志,导致磁盘被占满了.Docker容器在启动/重启的时候会往/var/lib/docker中 ...

  10. Python sqlalchemy的基本使用

    示例代码 from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base fr ...