I' creating a log and i need to retrieve the request body to save in db. i created a filter with HttpActionContext. I tried recover via filterContext.Request.Content.ReadAsStringAsync().Result; but it always return me an empty string.
LogFilter.cs
public override void OnActionExecuting(HttpActionContext filterContext)
{
try
{
Task<string> content = filterContext.Request.Content.ReadAsStringAsync();
string body = content.Result;
logModel.RequestLog rl = new logModel.RequestLog();
rl.IP = ((HttpContextWrapper)filterContext.Request.Properties["MS_HttpContext"]).Request.UserHostAddress;
rl.Type = filterContext.ControllerContext.RouteData.Values["controller"].ToString().ToUpper();
rl.URL = filterContext.Request.RequestUri.OriginalString;
rl.Operation = filterContext.Request.Method.Method;
rl.RequestDate = DateTime.Now;
filterContext.ControllerContext.RouteData.Values.Add("reqID", new deviceLog.RequestLog().Add(rl).ID.ToString());
}
catch { }
//return new deviceLog.RequestLog().Add(rl);
base.OnActionExecuting(filterContext);
}
Maybe request stream already reached to end. Try reset stream position to beginning:
public class MyAttribute:ActionFilterAttribute
{
public override void OnActionExecuted(HttpActionContext actionContext)
{
string rawRequest;
using (var stream = new StreamReader(actionContext.Request.Content.ReadAsStreamAsync().Result))
{
stream.BaseStream.Position = 0;
rawRequest = stream.ReadToEnd();
}
}
}
almost 7 years late... I was tasked to create a filter for a legacy project - about 8 years old - with no patterns or architecture whatsoever.
I tried reading from stream with stream/string async but it doesn't let you read more than once, and it was already read before the action filter - Seek was false, position was readonly.
I tried reflection but it was too much for little gain and again I didn't like it.
I tried getting "MS_HttpContext" but it wasn't in the dictionary.
After 8 hours of research I compromised with getting all the action arguments from the request and just turn them into Json.
For 4.7 framework API:
private string requestBody = "";
public override void OnActionExecuting(HttpActionContext actionContext)
{
requestBody = JsonConvert.SerializeObject(actionContext.ActionArguments);
base.OnActionExecuting(actionContext);
}
For .NET 5.0:
I use this on OnResultExecuted method. The stream is already read so you need to reposition the request body at 0.
private static async Task<string> FormatRequestBody(HttpRequest request)
{
// we set the stream position to 0 to reset the pointer. If this is not done, the read stream will be incorrect and the Body will be empty
request.Body.Position = 0;
// We now need to read the request stream. First, we create a new byte[] with the same length as the request stream...
var buffer = new byte[Convert.ToInt32(request.ContentLength)];
//...Then we copy the entire request stream into the new buffer.
await request.Body.ReadAsync(buffer, 0, buffer.Length);
// We convert the byte[] into a string using UTF8 encoding...
//... and send it back...
return Encoding.UTF8.GetString(buffer);
}
Hope this helps someone, because I stumbled on this post along with other 15 stackoverflow posts while doing my research.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.