从零开始搭建.NET Core 2.0 API(学习笔记一)

匿名 (未验证) 提交于 2019-12-02 22:06:11

一、 VS 2017 新建一个项目 选择ASP.NET Core Web应用程序,再选择Web API,选择ASP.NET Core 2.0版本

运行项目 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?}"); });  }

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 用于记录方法开支执行时间

  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 设置已完成。





标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!