如何获取Web API的请求与响应并将指定内容存入数据库
实现方案
你可以根据需要覆盖的接口范围选择以下任意一种方案:
方案1:仅当前接口需要存数据(最简方案)
你当前代码中已经生成了要返回的全部内容,不需要额外获取HttpResponseMessage,直接在返回前插入存库逻辑即可:
[HttpGet] [ResponseType(typeof(RsContractCustomer))] [Route("api/Contract/GetCustomerData/{cardModificationId}")] public async Task<IHttpActionResult> GetCustomerData([FromUri] int cardModificationId) { var customerData = await _bs.GetCustomer(cardModificationId); var jsonIgnoreNullValues = JsonConvert.SerializeObject(customerData, Newtonsoft.Json.Formatting.Indented, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); JObject jObject = JObject.Parse(jsonIgnoreNullValues); // ========== 新增:你的存库逻辑 ========== // 提取你需要保存的字段,比如请求参数、返回内容、响应状态码、请求时间等 var log = new ApiResponseLog { CardModificationId = cardModificationId, ResponseContent = jsonIgnoreNullValues, StatusCode = 200, CreateTime = DateTime.Now }; // 调用你的存库服务,建议用异步避免阻塞请求 await _dbContext.ApiResponseLogs.AddAsync(log); await _dbContext.SaveChangesAsync(); // ======================================== return Ok(jObject); }
方案2:需要获取完整HttpResponseMessage,或多个接口统一实现存库
如果需要拿到框架最终生成的完整响应报文(包含响应头、动态生成的状态码等),或者要给多个接口统一加存库逻辑,推荐用Action过滤器,不需要修改业务代码:
第一步:自定义响应日志过滤器
public class ApiResponseLogFilter : IAsyncActionFilter { private readonly YourDbContext _dbContext; public ApiResponseLogFilter(YourDbContext dbContext) { _dbContext = dbContext; } public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { // 先执行接口业务逻辑 var resultContext = await next(); // 把返回的IHttpActionResult转成HttpResponseMessage var response = resultContext.Result as IHttpActionResult; var httpResponse = await response.ExecuteAsync(CancellationToken.None); // 提取你需要保存的字段 var log = new ApiResponseLog { RequestPath = context.HttpContext.Request.Path.ToString(), StatusCode = (int)httpResponse.StatusCode, ResponseContent = await httpResponse.Content.ReadAsStringAsync(), // 也可以提取请求参数、响应头、用户信息等你需要的内容 CreateTime = DateTime.Now }; // 存库 await _dbContext.ApiResponseLogs.AddAsync(log); await _dbContext.SaveChangesAsync(); } }
第二步:注册过滤器
如果要全局生效,在WebApiConfig的Register方法里添加:
config.Filters.Add(new ApiResponseLogFilter(GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(YourDbContext)) as YourDbContext));
如果只需要给特定接口生效,直接在对应Action/Controller上贴特性:[TypeFilter(typeof(ApiResponseLogFilter))]
补充说明
如果存库逻辑耗时较高,不想影响接口响应速度,可以把要存的日志先写入内存队列,用后台任务异步消费存库,避免阻塞主请求流程。
内容的提问来源于stack exchange,提问作者kenzolek
相关产品推荐
相关产品推荐

