.Net6 WebApi传入传出参数记录

前言:这个功能主要是用来记录WebApi的所有调用记录,会把所有的传入参数以及得到的结果保存下来,方便问题跟踪(跟前面写的Winform操作日志记录遥相呼应,对系统端到端实现完整记录)。

为了简单易用,这里主要采用中间件的方式来实现。同时考虑了某些情况下并不需要记录,所以加入了忽略某些Action的方法(比如一些需要不间断循环调用的接口),不过我是直接写到中间件里面了。可以考虑其他方式实现高可用性。

a677b01aec8e53b0f7d445a50968b4f4.png

  1. 首先创建一个中间件,并定义以下字段。其中ignoreActions就是不需要记录的一些函数名;_serviceScopeFactory是为了拿到依赖注入的对象实现数据存储的。

    public class WebApiLog
        {
            readonly RequestDelegate _next;
            readonly IServiceScopeFactory _serviceScopeFactory;
            readonly List<string> ignoreActions = new List<string>{
                "Index1","Default/Index2"
            };
            public WebApiLog(RequestDelegate next, IServiceScopeFactory serviceScopeFactory)
            {
                _next = next;
                _serviceScopeFactory = serviceScopeFactory;
            }
  1. 传入参数的记录,由于WebApi的传入类型可以是多样性的,如:FromForm、FromBody等,所以对context.Request进行了判断,并采用了不同的数据组合方式

    public async Task InvokeAsync(HttpContext context)
            {
    if (!ignoreActions.Exists(s=>context.Request.Path.ToString().Contains(s)))
                {
        //首先记录一些基本的参数,IP,Action,Time等
                    TApilog Apilog = new TApilog();
                    Apilog.Ip = Convert.ToString(context.Connection.RemoteIpAddress);
                    Apilog.Action = context.Request.Path;
                    Apilog.Intime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
                    using var scope = _serviceScopeFactory.CreateScope();
                    string token = context.Request.Headers["token"];
                    if (!string.IsNullOrEmpty(token))
                    {
                        var tokenService = scope.ServiceProvider.GetRequiredService<ITokenService>();
                        Apilog.Useraccount = tokenService.ParseToken(context)?.UserAccount;
                    }
           #region 传入参数解析
                    StringBuilder inarg = new StringBuilder();
                    if (context.Request.HasFormContentType)
                    {
                        foreach (var item in context.Request.Form)
                        {
                            inarg.AppendLine(item.Key + ":" + item.Value);
                        }
                    }
                    else if (context.Request.Query.Count > 0)
                    {
                        foreach (var item in context.Request.Query)
                        {
                            inarg.AppendLine(item.Key + ":" + item.Value);
                        }
                    }
                    else
                    {
                        context.Request.EnableBuffering();
                        StreamReader streamReader = new StreamReader(context.Request.Body);
                        inarg.AppendLine(await streamReader.ReadToEndAsync());
                        context.Request.Body.Seek(0, SeekOrigin.Begin);
                    }
                    Apilog.Input = inarg.ToString();
          #endregion
  1. 传出参数的记录

    #region 传出参数解析
                    var originalBodyStream = context.Response.Body;
                    using (var responseBody = new MemoryStream())
                    {
                        context.Response.Body = responseBody;
                        await _next(context);
                        Apilog.Output = await GetResponse(context.Response);
                        await responseBody.CopyToAsync(originalBodyStream);
                    }
                    #endregion
                    Apilog.Outtime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
                    var _tApilogServices = scope.ServiceProvider.GetRequiredService<ITApilogServices>();
                    try {await _tApilogServices.InsertAsync(Apilog); } catch { } }
                else
                {
                   await _next(context);
                }
    }
    public async Task<string> GetResponse(HttpResponse response)
            {
                response.Body.Seek(0, SeekOrigin.Begin);
                var text = await new StreamReader(response.Body).ReadToEndAsync();
                response.Body.Seek(0, SeekOrigin.Begin);
                return text;
            }
  1. 最后在Program文件中使用这个中间件

    //日志记录
    app.UseMiddleware<WebApiLog>();
  1. 结束。最后补充下,因为这里是记录到数据库的,所以字段长度在设计的时候要足够,同时因为这个表查询频率不高,可以不建任何索引(这个表空间的增长速度会非常快,所以个人认为没必要增加开销)

57354847208a11c45cbe6507d96d772a.png

-

技术群:添加小编微信并备注进群

小编微信:mm1552923   

公众号:dotNet编程大全    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值