defaults: new { id = RouteParameter.Optional } 最后将IHttpCont

时间:2021-07-31 09:02:21

一、关于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.WordStr(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提高班

Web API的参数、多版本和Filter