A simple way to calculate response length in MVC4

I tried to calculate the length of a HTTP Response . It seems that the stream does not want to play. (reading is not allowed, but Content-Length is not displayed) I was hoping to just name some length property in the HttpContent response. Since then I searched Google and saw what seems like a difficult decision around filters that I don’t understand. Is it possible to access the length (the content itself is optional) If not, I would appreciate a link to an example for the filter "mvc4 / .net 4.5" that I should work until I understand. :-)

  public override void Init() { base.Init(); EndRequest += new EventHandler(EndRequestHandler); } public void EndRequestHandler(object sender, EventArgs e) { var admService = new AdminServices(); admService.HTTPTrace(Context); } public void HTTPTrace(HttpContext httpContext) { try { var eventTrace = new MasterEventTrace(); eventTrace.RemoteAddress = req.UserHostAddress; eventTrace.RequestLengthBytes = req.ContentLength; // var targetMemoryStream = new MemoryStream(); // res.OutputStream.CopyTo(targetMemoryStream); int len; int.TryParse(res.Headers["Content-Length"], out len ); eventTrace.StatusCode = res.StatusCode; eventTrace.ResponseLengthBytes = len; // <<<<<<< HOW to calculate this 

EDIT: Based on Darin's answer, I got this job, thanks Darin. I made some adjustments to fit the situation, but otherwise, as suggested. It shows a little more from Global.asax.cs and records request and response information as needed.

 //Global.asax.cs public override void Init() { base.Init(); BeginRequest += new EventHandler(BeginRequestHandler); EndRequest += new EventHandler(EndRequestHandler); } public void EndRequestHandler(object sender, EventArgs e) { var adminService = new AdminServices(); var handler = Context.Response.Filter as ResponseStreamHandler; adminService.HTTPTrace(Context, handler); } public void BeginRequestHandler(object sender, EventArgs e) { BootStrapUnauthentiated(); Context.Response.Filter = new ResponseStreamHandler(Context.Response.Filter); } public void HTTPTrace(HttpContext httpContext, ResponseStreamHandler responseStreamFilter) { try { var _ILuwMaster = BosGlobal.BGA.ILuwMaster(); var req = httpContext.Request; var res = httpContext.Response; var eventTrace = new MasterEventTrace(); eventTrace.EventName = req.RequestType +":"+ req.Url.LocalPath; eventTrace.EventDateTime = BosGlobal.BGA.Calendar.Now; eventTrace.RemoteAddress = req.UserHostAddress; eventTrace.RequestLengthBytes = req.ContentLength; eventTrace.ResponseLengthBytes = responseStreamFilter.ResponseSize; //<<<<<<HERE eventTrace.StatusCode = res.StatusCode; // save trace entry in DB _ILuwMaster.GetRepository<MasterEventTrace>().Add(eventTrace); _ILuwMaster.Commit(); } catch (Exception ex ) {} // DONT KILL Live traffic when logging errors occur } 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); } public override void Flush() { base.Flush(); } } 
+4
source share
1 answer

You can write a custom response filter :

 public class ResponseLengthCalculatingStream: MemoryStream { private readonly Stream responseStream; private long responseSize = 0; public ResponseLengthCalculatingStream(Stream responseStream) { this.responseStream = responseStream; } public override void Write(byte[] buffer, int offset, int count) { this.responseSize += count; this.responseStream.Write(buffer, offset, count); } public override void Flush() { var responseSize = this.responseSize; // Here you know the size of the response ... base.Flush(); } } 

and register it in Global.asax :

 protected void Application_BeginRequest() { Context.Response.Filter = new ResponseLengthCalculatingStream(Context.Response.Filter); } 

And if you want to apply this filter only to specific controller actions, you can write a custom action filter, and not apply it in the BeginRequest event in Global.asax:

 public class ResponseLengthCapturingAttribute: ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { var response = filterContext.HttpContext.Response; response.Filter = new ResponseLengthCalculatingStream(response.Filter); } } 

and then everything that remains decorates the action of the controller with an appropriate action filter:

 [ResponseLengthCapturing] public ActionResult Index() { ... return View(); } 
+6
source

Source: https://habr.com/ru/post/1489625/


All Articles