从零开始搭建.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); }