欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-03-12 10:22:13
从零开始搭建.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);        }