记录web api的request以及response(即写log)
https://www.cnblogs.com/felixnet/p/5689501.html
https://blog.csdn.net/Vblegend_2013/article/details/83446229
https://stackoverflow.com/questions/27176329/web-api-request-content-empty
https://forums.asp.net/t/2127541.aspx?Get+Http+Raw+Request+and+Response 这个里面提到了DelegatingHandler
https://www.infoworld.com/article/3211590/how-to-log-request-and-response-metadata-in-aspnet-web-api.html 这个里面提到了DelegatingHandler
https://github.com/aspnet/AspNetWebStack/issues/150
综合上面几个链接,日志应该使用delegating handler里面处理。(ActionFilter里面,http request的content已经被读取过了,需要像第一个链接里面一样,先重置回去,再读,比较麻烦)
string requestMessage = requestContent.ReadAsStringAsync().Result; //request raw string responseMessage = response.ToString(); //response raw
自己写的版本
public class LogHandler : DelegatingHandler { private string _requestId; private readonly string _newLine = Environment.NewLine; protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { _requestId = DateTime.Now.Ticks.ToString(); var requestBody = request.Content.ReadAsStringAsync().Result; LogUtil.CreateLog(LogLevel.Message, $"{_requestId}{_newLine}{request.Method.Method} {request.RequestUri.AbsoluteUri} HTTP/{request.Version}{_newLine}{requestBody}"); var response = await base.SendAsync(request, cancellationToken); string responseBody = response.Content.ReadAsStringAsync().Result; LogUtil.CreateLog(LogLevel.Message, $"{_requestId}{_newLine}HTTP/{response.Version} {(int)response.StatusCode} {response.StatusCode}{_newLine}{responseBody}{_newLine}{_newLine}"); return response; } }
有ReadAsAsync扩展方法,自动进行类型的转换
var apiRequest = request.Content.ReadAsAsync<ApiRequest<dynamic>>().Result; OwinRequestScopeContext.Current.Items["CountryCode"] = apiRequest.Header.OpCo;
这个地方如果需要重复读取数据的话
https://stackoverflow.com/questions/26942514/multiple-calls-to-httpcontent-readasasync
If you want to read again and again, you would probably want to read as stream and seek to beginning every time you read the stream.
But then if you want to do what do you now but get the second read working, you can seek to the beginning of the stream, after the first read, like this.
await httpContent.LoadIntoBufferAsync(); var X = await httpContent.ReadAsAsync<T>(); Stream stream = await httpContent.ReadAsStreamAsync(); stream.Seek(0, SeekOrigin.Begin); var Y = await httpContent.ReadAsAsync<Dictionary<string, object>>();
中间的stream不需要using,否则会遇到这种错误
HTTP/1.1 400 BadRequest
{"Message":"The request is invalid.","ModelState":{"request":["Stream was not readable."]}}
作者:Chuck Lu GitHub |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2018-02-26 JSON.stringify()
2018-02-26 dynamic关键字的使用
2017-02-26 Consolidate data by using multiple page fields
2017-02-26 Excel操作之VLOOKUP
2016-02-26 Array.Copy vs Buffer.BlockCopy
2015-02-26 观察者模式和事件的不同之处
2015-02-26 Simple Factory vs. Factory Method vs. Abstract Factory【简单工厂,工厂方法以及抽象工厂的比较】