קורה שנזקקים ללוג קבוע של כל התעבורה מהאתר לצרכי ניתוח, מסתבר שלקבל את גוף ה RESPONSE ולקשר את זה עם ה REQUEST זה לא פשוט, הפתרון הנ"ל מתבסס על התשובה הזו מסטאק: https://stackoverflow.com/a/1792864.
את הקוד הזה שמים בקובץ Global.asax.cs:
שימו לב ש Application_BeginRequest, Application_AcquireRequestState ו Application_EndRequest יכולים כבר להיות קיימים ומלאים בקוד למטרות אחרות,ואז רק להוסיף את השורות מהקוד שלהלן.
//Fires at the beginning of each request
void Application_BeginRequest(object sender, EventArgs e)
{
//set Filter to this request's response
HttpResponse response = HttpContext.Current.Response;
OutputFilterStream filter = new OutputFilterStream(response.Filter);
response.Filter = filter;
//Save filter in the current Context
HttpContext.Current.Items["filter"] = filter;
//Save the request received time in the current Context
HttpContext.Current.Items["receivedTime"] = DateTime.Now;
//
}
//Fires when request Session state is acquired.
void Application_AcquireRequestState(object sender, EventArgs e)
{
//save SessionId in the current Context (since when in Application_EndRequest the session control is already back to the IIS and the Session info is gone)
if (HttpContext.Current != null && HttpContext.Current.Session != null)
{
HttpContext.Current.Items["SessionID"] = HttpContext.Current.Session.SessionID;
}
}
void Application_EndRequest(object sender, EventArgs e)
{
try
{
HttpApplication app = sender as HttpApplication;
string responseBody = ((OutputFilterStream)HttpContext.Current.Items["filter"]).ReadStream();
HttpContext con = app.Context;
System.Diagnostics.Debug.WriteLine(string.Join("\r\n",
new string[] {
"SessionID",(HttpContext.Current.Items.Contains("SessionID") ? HttpContext.Current.Items["SessionID"].ToString() : "NoID"),
"ResponseTime", DateTime.Now,
"ReceiveTime", HttpContext.Current.Items["receivedTime"].ToString(),
"RequestURL", con.Request.Url.ToString(),
"RequestHeaders", con.Request.Headers.ToString().Replace("&", " "),
"RequestBody", GetRequestBody(),
"ResponseHeaders", con.Response.Headers.ToString().Replace("&", " "),
"ResponseBody", responseBody,
"ResponseStatus", Response.StatusCode.ToString()}));
}
catch (Exception)
{
//Ignore Log Failure
}
}
//This class saves copy of the response sent to the Client son we can read the copy for logging
public class OutputFilterStream : Stream
{
private readonly Stream InnerStream;
private readonly MemoryStream CopyStream;
public OutputFilterStream(Stream inner)
{
this.InnerStream = inner;
this.CopyStream = new MemoryStream();
}
public string ReadStream()
{
lock (this.InnerStream)
{
if (this.CopyStream.Length <= 0L ||
!this.CopyStream.CanRead ||
!this.CopyStream.CanSeek)
{
return String.Empty;
}
long pos = this.CopyStream.Position;
this.CopyStream.Position = 0L;
try
{
return new StreamReader(this.CopyStream).ReadToEnd();
}
finally
{
try
{
this.CopyStream.Position = pos;
}
catch { }
}
}
}
public override bool CanRead
{
get { return this.InnerStream.CanRead; }
}
public override bool CanSeek
{
get { return this.InnerStream.CanSeek; }
}
public override bool CanWrite
{
get { return this.InnerStream.CanWrite; }
}
public override void Flush()
{
this.InnerStream.Flush();
}
public override long Length
{
get { return this.InnerStream.Length; }
}
public override long Position
{
get { return this.InnerStream.Position; }
set { this.CopyStream.Position = this.InnerStream.Position = value; }
}
public override int Read(byte[] buffer, int offset, int count)
{
return this.InnerStream.Read(buffer, offset, count);
}
public override long Seek(long offset, SeekOrigin origin)
{
this.CopyStream.Seek(offset, origin);
return this.InnerStream.Seek(offset, origin);
}
public override void SetLength(long value)
{
this.CopyStream.SetLength(value);
this.InnerStream.SetLength(value);
}
public override void Write(byte[] buffer, int offset, int count)
{
this.CopyStream.Write(buffer, offset, count);
this.InnerStream.Write(buffer, offset, count);
}
}
//This Method returns the Body for the current requst
public static string GetRequestBody()
{
string sReturn = string.Empty;
// Regular request body
using (System.IO.StreamReader sr = new System.IO.StreamReader(HttpContext.Current.Request.InputStream))
{
sReturn = sr.ReadToEnd();
}
// Web service SOAP request body
if (string.IsNullOrEmpty(sReturn))
{
byte[] b = (byte[])typeof(HttpRequest).InvokeMember("EntityBody", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.GetProperty, null, HttpContext.Current.Request, null);
if (b != null && b.Length > 0)
{
using (System.IO.StreamReader sr = new System.IO.StreamReader(new System.IO.MemoryStream(b), true))
{
sReturn = sr.ReadToEnd();
}
}
else
{
sReturn = "";
}
}
//cut the log to reduce size
//sReturn = sReturn.Substring(0, (sReturn.Length < 200 ? sReturn.Length : 200));
//encrypt sensitive info
//if (sReturn.Contains("&pwd="))
//{
// sReturn = String.Join("&", sReturn.Split('&').Select(p => (p.ToLower().StartsWith("pwd") ? Encryption.Encrypt(p, "PO12345678") : p)).ToArray());
//}
return sReturn;
}
פורסם במקור בפורום CODE613 ב22/06/2017 17:50 (+03:00)