我不知道它是否是一个错误,但我无法在服务器端获得原始请求。
考虑以下控制器方法:
[AllowAnonymous]
[Route("api/sayHello")]
[HttpPost]
public string SayHello([FromBody] string userName)
{
return $"Hello, {userName}.";
}
我通过cUrl调用它:
curl -X POST 'https://localhost:809/api/sayHello' --insecure -d "=userName"
现在我正在尝试添加一些日志记录。我添加了一个全局过滤器,它正在执行以下操作:
public async Task LogFilterAction(HttpActionContext context)
{
if (context == null)
throw new ArgumentNullException(nameof(context));
LogFilterAction(context.ActionDescriptor?.ControllerDescriptor?.ControllerType,
context.ActionDescriptor?.ActionName,
context.Request?.RequestUri,
await GetDataAsString(context.Request?.Content),
context.Response?.StatusCode
);
}
private static async Task<string> GetDataAsString(HttpContent content)
{
if (content == null)
return null;
var contentBytes = await content.ReadAsByteArrayAsync();
return Encoding.UTF8.GetString(contentBytes);
}
但问题是:由于未知原因,contentBytes总是一个空数组。我发现它的实际长度是9(=userName
字符串的长度
甚至
正如您所看到的,ASP.Net已成功请求参数,但是,它并没有以原始方式返回它。 Stream有position = 0,contentConsumed = false,其他一切都很好。但我 无法 读取传递给控制器的数据。
这里有什么问题?
答案 0 :(得分:1)
ASP.NET Web API只读取一次内容,因此在您访问内容流时,它已经被读取并且流被定位在其末尾。另一次尝试阅读内容将不会返回任何内容。
然而,在一个小样本中,我能够重置流并再次读取它:
private async Task<string> GetDataAsString(HttpContent content)
{
if (content == null)
return null;
using (var str = await content.ReadAsStreamAsync())
{
if (str.CanSeek)
str.Seek(0, System.IO.SeekOrigin.Begin);
using (var rdr = new StreamReader(str))
{
return rdr.ReadToEnd();
}
}
}
但是,为了避免副作用,您可能需要考虑使用ActionContext
的{{3}}属性。您可以使用此属性来检索传递给操作以进行日志记录的值。这不会干扰ASP.NET Web API的内部管道。