计算MVC4中响应长度的简单方法

phi*_*ady 5 asp.net asp.net-mvc

我试图计算一个长度HTTP Response.似乎流不想播放.(没有允许读取.并且Content-Length似乎没有设置)我希望简单地在HttpContent响应上调用一些length属性.从那以后,我用谷歌搜索,看到了什么看起来像我不明白的过滤器周围的复杂解决方案.是否有可能访问长度(内容本身是额外的选项)如果不是我会欣赏一个链接到'mvc4/.net 4.5过滤器'的例子,我应该工作,直到我明白.:-)

   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
Run Code Online (Sandbox Code Playgroud)

编辑:基于达林的回应,我得到了这个工作,谢谢你Darin 我做了一些调整,以适应这种情况,但除此之外建议.它显示了Global.asax.cs中的更多信息,并根据需要记录了请求和响应信息.

//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();
    }
}
Run Code Online (Sandbox Code Playgroud)

Dar*_*rov 7

您可以编写自定义响应过滤器:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

并在您的注册中注册Global.asax:

protected void Application_BeginRequest()
{
    Context.Response.Filter = new ResponseLengthCalculatingStream(Context.Response.Filter);
}
Run Code Online (Sandbox Code Playgroud)

如果您只想对特定的控制器操作应用此过滤器,您可以编写自定义操作过滤器,而不是将其应用于Global.asax中的BeginRequest事件:

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

然后剩下的就是使用相应的动作过滤器来装饰控制器动作:

[ResponseLengthCapturing]
public ActionResult Index()
{
    ...
    return View();
}
Run Code Online (Sandbox Code Playgroud)