Web API的參數、多版本和Filter

1、關於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風格。
2、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;
  }html

  public override HttpControllerDescriptor SelectController(HttpRequestMessage request) {api

    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 }
      );app

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));async

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

  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());
    }
  }
}url


學習資料:如鵬網.net提升班http://www.rupeng.com/News/10/4603.shtmlspa

相關文章
相關標籤/搜索