從零開始搭建.NET Core 2.0 API(學習筆記一) 一、 VS 2017 新建一個項目 選擇ASP.NET Core Web應用程式,再選擇Web API,選擇ASP.NET Core 2.0版本 二、 添加API幫助頁面 API項目添加 NuGet NSwag.AspNetCore 引用 ...
從零開始搭建.NET Core 2.0 API(學習筆記一)
一、 VS 2017 新建一個項目 選擇ASP.NET Core Web應用程式,再選擇Web API,選擇ASP.NET Core 2.0版本
二、 添加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?}"); }); }
三、 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); }
四、添加一個基礎設置項目,添加一個日誌介面 ILogWrite,一個記錄日誌實現類 LogWrite 在Startup 類ConfigureServices方法中添加日誌 Ioc
因為日誌攔截器和異常攔截器會用到日誌記錄需要註入 所以日誌在AddMvc()前面添加,Autofac配置不能在 AddMvc前面,所以這裡用.NET Core的Ioc容器,後面Autofac會接管容器。
services.AddSingleton<ILogWrite, LogWrite>();
五、filter 添加三個類分別是
a AuthorizationFilter 許可權過濾器
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>(); });
六、Action參數讀取,為了在異常過濾器、性能日誌過濾器中,讀取參數需要在許可權過濾器中添加下麵兩行代碼
public class AuthorizationFilter : IAuthorizationFilter { public void OnAuthorization(AuthorizationFilterContext context) { HttpRequest request = context.HttpContext.Request; request.EnableRewind(); request.Body.Position = 0; } }
七、性能日誌過濾器 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 { }
八、異常過濾器
/// <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); }