לוג של כל התעבורה באתר דוט נט
-
קורה שנזקקים ללוג קבוע של כל התעבורה מהאתר לצרכי ניתוח, מסתבר שלקבל את גוף ה 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)