Reputation: 11348
In a WEBAPI filter, im trying to calculate response size. A similar process works for MVC controllers.
Inside actionExecutedContext.Response. i cant see a filter?
So I tried this filter below but this doesnt work.
How can i get the length of a WEBApi response ? I could stick this in Global.ASAX and it works, but then every http call is logged... So an API filter would be ideal. Is there something obviously wrong here ?
public class BosAPIFilter : System.Web.Http.Filters.ActionFilterAttribute{
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) {
base.OnActionExecuted(actionExecutedContext);
var httpContext = actionExecutedContext.Request.Properties["MS_HttpContext"] as HttpContextWrapper;
if (httpContext != null) {
actionExecutedContext.Response.
httpContext.Response.Filter = new ResponseStreamHandler(httpContext.Response.Filter);
var handler = httpContext.Response.Filter as ResponseStreamHandler;
var adminService = new AdminServices();
adminService.HttpTrace(httpContext, handler);
}
}
public class ResponseStreamHandler : MemoryStream {
private readonly Stream _responseStream;
public long ResponseSize { get; private set; }
public ResponseStreamHandler(Stream responseStream) {
this._responseStream = responseStream;
ResponseSize = 0;
}
public override void Write(byte[] buffer, int offset, int count) {
this.ResponseSize += count;
this._responseStream.Write(buffer, offset, count);
}
// ReSharper disable once RedundantOverridenMember
public override void Flush() { base.Flush(); }
}
Upvotes: 0
Views: 1718
Reputation: 19311
In ASP.NET Web API pipeline, action filters run before the result you return from the action method gets serialized. If you look at actionExecutedContext.Response.Content
inside the filter, it will be System.Net.Http.ObjectContent
(depending on your action method). So, you can calculate the response size only later in the pipeline. You can use a message handler to do this but then the granularity is not at the action method level. The lowest granularity you can get is at a route level. One way you get around this is to set a flag in the request dictionary from the filter and log from the handler only when the flag is set.
Upvotes: 1