從零開始搭建.NET Core 2.0 API(學習筆記一)app
1、 VS 2017 新建一個項目 選擇ASP.NET Core Web應用程序,再選擇Web API,選擇ASP.NET Core 2.0版本ide
2、 添加API幫助頁面 API項目添加 NuGet NSwag.AspNetCore 引用, 而後在添加NSwag設置函數
運行項目 http://localhost:prot/swagger 便可打開幫助頁。性能
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseBrowserLink(); } else { app.UseExceptionHandler("/Home/Error"); } app.UseStaticFiles(); app.UseSwaggerUi(typeof(Startup).GetTypeInfo().Assembly, settings => { settings.GeneratorSettings.DefaultPropertyNameHandling = PropertyNameHandling.CamelCase; }); app.UseMvc(route => { route.MapRoute(name: "default", template: "{controller=Home}/{action=Get}/{id?}"); }); }
3、 Startup 類ConfigureServices方法中,添加配置中心初始化;配置中心統一管理配置,便於維護學習
public IServiceProvider ConfigureServices(IServiceCollection services) { ConfigHelper.Init(Configuration["ConfigZookeeperAddress"], Configuration["ConfigNodePath"]); services.AddSingleton<ILogWrite, LogWrite>(); services.AddMvc(options => { options.Filters.Add<AuthorizationFilter>(); options.Filters.Add<ExceptionFilter>(); options.Filters.Add<PerformanceLogFilter>(); }); var builder = new ContainerBuilder();//實例化 AutoFac 容器 builder.Populate(services); // TODO: 這裏添加其餘須要注入類的註冊 ApplicationContainer = builder.Build(); return new AutofacServiceProvider(ApplicationContainer); }
4、添加一個基礎設置項目,添加一個日誌接口 ILogWrite,一個記錄日誌實現類 LogWrite 在Startup 類ConfigureServices方法中添加日誌 Iocui
由於日誌攔截器和異常攔截器會用到日誌記錄須要注入 因此日誌在AddMvc()前面添加,Autofac配置不能在 AddMvc前面,因此這裏用.NET Core的Ioc容器,後面Autofac會接管容器。this
services.AddSingleton<ILogWrite, LogWrite>();
5、filter 添加三個類分別是spa
a AuthorizationFilter 權限過濾器pwa
b ExceptionFilter 異常過濾器日誌
c PerformanceLogFilter 性能日誌過濾器
ExceptionFilter 、PerformanceLogFilter 分別定義構造函數,注入日誌依賴。
public ExceptionFilter(ILogWrite logWrite) { _logWrite = logWrite; } public PerformanceLogFilter(ILogWrite logWrite) { _logWrite = logWrite; }
過濾器必須添加在 Startup類ConfigureServices的services.AddMvc()中
services.AddMvc(options => { options.Filters.Add<AuthorizationFilter>(); options.Filters.Add<ExceptionFilter>(); options.Filters.Add<PerformanceLogFilter>(); });
6、Action參數讀取,爲了在異常過濾器、性能日誌過濾器中,讀取參數須要在權限過濾器中添加下面兩行代碼
public class AuthorizationFilter : IAuthorizationFilter { public void OnAuthorization(AuthorizationFilterContext context) { HttpRequest request = context.HttpContext.Request; request.EnableRewind(); request.Body.Position = 0; } }
7、性能日誌過濾器 PerformanceLogFilter 繼承 IActionFilter,實現兩個接口
OnActionExecuting 在調用操做方法以前發生
OnActionExecuted 在調用操做方法以後發生
a 在方法 OnActionExecuting中 實例化一個 Stopwatch 用於記錄方法開支執行時間
把Stopwatch 實力加入 HttpContext.Items 中,便於在 OnActionExecuted 獲取。
b 讀取Action請求參數, 放入 HttpContext.Items 中, 不知道爲何OnActionExecuted 去不到參數
/// <summary> /// 在調用操做方法以前發生。 /// </summary> /// <param name="context"></param> public void OnActionExecuting(ActionExecutingContext context) {
// if (SkipLogging(context)) return; var watch = new Stopwatch(); context.HttpContext.Items[ConfigHelper.HttpRequestStopWatcher] = watch; var paramenters = context.ActionArguments.Count==0?string.Empty:context.ActionArguments.Serialize(); context.HttpContext.Items[ConfigHelper.FilterActionArguments] = paramenters; watch.Start(); }
OnActionExecuting 中增長了性能日誌開關,若是關閉直接返回,不建立Stopwatch,
在OnActionExecuted中回去到的Stopwatch是null 則直接返回(也能夠用性能日誌開關作判斷),不處理後續。
若是Controll、Action添加了NoLog特性,則不記錄性能日誌
private static bool SkipLogging(ActionExecutingContext actionContext) { if (!ConfigHelper.IsPerformanceLog) return true; return actionContext.ActionDescriptor.GetType().GetCustomAttributes(typeof(NoLogAttribute), false).Any() || actionContext.Controller.GetType().GetCustomAttributes(typeof(NoLogAttribute), false).Any(); }
/// <summary> /// 忽略性能日誌記錄特性 /// </summary> [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true)] public class NoLogAttribute : Attribute { }
8、異常過濾器
/// <summary> /// 異常攔截器 /// </summary> public class ExceptionFilter : IExceptionFilter { ILogWrite _logWrite; public ExceptionFilter(ILogWrite logWrite) { _logWrite = logWrite; } /// <summary> /// /// </summary> /// <param name="actionExecutedContext"></param> /// <param name="cancellationToken"></param> /// <returns></returns> public void OnException(ExceptionContext context) { BizResult<bool> biz; var paramenters = context.HttpContext.Items[ConfigHelper.FilterActionArguments].ToString(); try { biz = new BizResult<bool>(false, (int)B2CBizCode.Exception, context.Exception.Message); if (context.Exception.InnerException != null) biz.SysMessage += ":" + context.Exception.InnerException.Message; if (ConfigHelper.IsPerformanceLog) { var watch = context.HttpContext.Items[ConfigHelper.HttpRequestStopWatcher] as Stopwatch; watch?.Stop(); var name = context.ActionDescriptor.GetType().GetProperty("ActionName").GetValue(context.ActionDescriptor).ToString(); _logWrite.InfoAsync(new { CreateTime = DateTime.Now, Method = name, TimeSpan = watch.Elapsed, IsSuccess = false, Content = paramenters, Code = ((B2CBizCode)biz.BusinessCode).ToString(), Message = biz.BusinessMessage }.Serialize()); } } catch (Exception ex) { biz = new BizResult<bool>(false, (int)B2CBizCode.Exception, ex.Message); } context.Result = new ApplicationErrorResult(biz); _logWrite?.ErrorAsync($"連接訪問出錯:{context.HttpContext.Request.Path}", context.HttpContext.Request.Method, this.GetType().Name, context.Exception, paramenters); return; } } public class ApplicationErrorResult : ObjectResult { public ApplicationErrorResult(object value) : base(value) { StatusCode = (int)HttpStatusCode.InternalServerError; } }
九 、添加Autofac,Autofac比.NET Core自帶的 Ioc更好用。 NuGetAPI 項目中添加Autofac.Configuration、Autofac.Extensions.DependencyInjection 兩個引用 而後 ConfigureServices方法中添加Ioc容器
public IServiceProvider ConfigureServices(IServiceCollection services) { ConfigHelper.Init(Configuration["ConfigZookeeperAddress"], Configuration["ConfigNodePath"]); services.AddSingleton<ILogWrite, LogWrite>(); services.AddMvc(options => { options.Filters.Add<AuthorizationFilter>(); options.Filters.Add<ExceptionFilter>(); options.Filters.Add<PerformanceLogFilter>(); }); var builder = new ContainerBuilder();//實例化 AutoFac 容器 builder.Populate(services); // TODO: 這裏添加其餘須要注入類的註冊 ApplicationContainer = builder.Build(); return new AutofacServiceProvider(ApplicationContainer); }
至此.NET Core API的 攔截器、配置管理、日誌、Ioc 設置已完成。
public IServiceProvider ConfigureServices(IServiceCollection services) { ConfigHelper.Init(Configuration["ConfigZookeeperAddress"], Configuration["ConfigNodePath"]); services.AddSingleton<ILogWrite, LogWrite>(); services.AddMvc(options => { options.Filters.Add<AuthorizationFilter>(); options.Filters.Add<ExceptionFilter>(); options.Filters.Add<PerformanceLogFilter>(); }); var builder = new ContainerBuilder();//實例化 AutoFac 容器 builder.Populate(services); // TODO: 這裏添加其餘須要注入類的註冊 ApplicationContainer = builder.Build(); return new AutofacServiceProvider(ApplicationContainer); }