diff --git a/src/Library/WcfSoapLogger/HandlerCustom/HandlerCustom.cs b/src/Library/WcfSoapLogger/HandlerCustom/HandlerCustom.cs index ba46bc0..1bdabf0 100644 --- a/src/Library/WcfSoapLogger/HandlerCustom/HandlerCustom.cs +++ b/src/Library/WcfSoapLogger/HandlerCustom/HandlerCustom.cs @@ -1,7 +1,4 @@ -using System; -using System.Text; -using WcfSoapLogger.EncodingExtension; -using WcfSoapLogger.Exceptions; +using WcfSoapLogger.EncodingExtension; namespace WcfSoapLogger.HandlerCustom { @@ -25,27 +22,32 @@ public override void HandleBody(byte[] body, bool request) this.HandleBodyOnClient(body, request); } } - + + // see stages + // https://github.com/capslocky/WcfSoapLogger/blob/master/docs/GeneralFlow.md private void HandleBodyOnService(byte[] body, bool request) { if (request) { + // service request [stage 3. logging] + SoapLoggerService.SetSettings(_settings); SoapLoggerService.SetRequestBody(body); - return; } + else + { + // service response [stage 5. logging ] - // service response [5. logging ] + var requestException = SoapLoggerService.GetRequestException(); - var requestException = SoapLoggerService.GetRequestException(); + if (requestException != null) + { + throw requestException; + } - if (requestException != null) - { - throw requestException; + SoapLoggerService.CallResponseCallback(body, _settings); } - - SoapLoggerService.CallResponseCallback(body, _settings); } @@ -53,10 +55,12 @@ private void HandleBodyOnClient(byte[] body, bool request) { if (request) { + // client request [stage 2. logging] SoapLoggerClient.CallRequestCallback(body, _settings); } else { + // client response [stage 6. logging ] SoapLoggerClient.CallResponseCallback(body, _settings); } } diff --git a/src/Library/WcfSoapLogger/HandlerCustom/SoapLoggerClient.cs b/src/Library/WcfSoapLogger/HandlerCustom/SoapLoggerClient.cs index 6ae581b..adac7c5 100644 --- a/src/Library/WcfSoapLogger/HandlerCustom/SoapLoggerClient.cs +++ b/src/Library/WcfSoapLogger/HandlerCustom/SoapLoggerClient.cs @@ -25,7 +25,7 @@ internal static void CallRequestCallback(byte[] requestBody, SoapLoggerSettings if (_client == null) { const string methodName = "SoapLoggerClient.SetCustomHandlerCallbacks"; - throw new LoggerException("You have enabled 'useCustomHandler' for client class of given service. So method '" + methodName+ "' should be called before making any request. Make sure to call it everywhere."); + throw new LoggerException("You have enabled 'useCustomHandler' for client class of given service. So method '" + methodName+ "' should be called before each request (typically in constructor of inhereted client class)."); } _client.HandleRequestBodyCallback(requestBody, settings); diff --git a/src/Library/WcfSoapLogger/HandlerCustom/SoapLoggerService.cs b/src/Library/WcfSoapLogger/HandlerCustom/SoapLoggerService.cs index 83cb8bf..1793ac2 100644 --- a/src/Library/WcfSoapLogger/HandlerCustom/SoapLoggerService.cs +++ b/src/Library/WcfSoapLogger/HandlerCustom/SoapLoggerService.cs @@ -82,7 +82,7 @@ internal static void CallResponseCallback(byte[] responseBody, SoapLoggerSetting //TODO add logging error message to file - throw new LoggerException("something went wrong, either pipeline execution didn't reach web-service method or web-service method didn't call 'ReadRequestSetResponseCallback'"); + throw new LoggerException("something went wrong, either pipeline execution didn't reach web-service method or web-service method didn't execute 'SoapLoggerService.CallCustomHandlers'"); } try diff --git a/src/UsageExamples/ExampleAlpha/Client/Program.cs b/src/UsageExamples/ExampleAlpha/Client/Program.cs index a5d0842..3eee364 100644 --- a/src/UsageExamples/ExampleAlpha/Client/Program.cs +++ b/src/UsageExamples/ExampleAlpha/Client/Program.cs @@ -13,7 +13,7 @@ private static void Main() Console.WriteLine(); var serviceClient = new WeatherServiceClient(); - var randomDataClient = new RandomDataClient(serviceClient); + var randomDataClient = new RandomDataClient(() => serviceClient); randomDataClient.StartThreads(); Console.ReadLine(); diff --git a/src/UsageExamples/ExampleBeta/Client/Program.cs b/src/UsageExamples/ExampleBeta/Client/Program.cs index 03b636b..5cd176f 100644 --- a/src/UsageExamples/ExampleBeta/Client/Program.cs +++ b/src/UsageExamples/ExampleBeta/Client/Program.cs @@ -14,8 +14,10 @@ private static void Main() Console.ReadKey(); Console.WriteLine(); + // if no custom handling - it's ok to reuse client class object + var serviceClient = new WeatherServiceClient(); - var randomDataClient = new RandomDataClient(serviceClient); + var randomDataClient = new RandomDataClient(() => serviceClient); randomDataClient.StartThreads(); Task.Delay(500).ContinueWith(_ => Process.Start("explorer.exe", @"C:\SoapLog\Beta")); diff --git a/src/UsageExamples/ExampleCommon/CommonClient/CommonClient.csproj b/src/UsageExamples/ExampleCommon/CommonClient/CommonClient.csproj index 5ac0b09..8e91568 100644 --- a/src/UsageExamples/ExampleCommon/CommonClient/CommonClient.csproj +++ b/src/UsageExamples/ExampleCommon/CommonClient/CommonClient.csproj @@ -39,7 +39,7 @@ - + diff --git a/src/UsageExamples/ExampleCommon/CommonClient/CustomHandling/RandomDataClientCustomHandler.cs b/src/UsageExamples/ExampleCommon/CommonClient/CustomHandling/WeatherServiceClientCustomHandler.cs similarity index 71% rename from src/UsageExamples/ExampleCommon/CommonClient/CustomHandling/RandomDataClientCustomHandler.cs rename to src/UsageExamples/ExampleCommon/CommonClient/CustomHandling/WeatherServiceClientCustomHandler.cs index d77e8dc..1f89c31 100644 --- a/src/UsageExamples/ExampleCommon/CommonClient/CustomHandling/RandomDataClientCustomHandler.cs +++ b/src/UsageExamples/ExampleCommon/CommonClient/CustomHandling/WeatherServiceClientCustomHandler.cs @@ -7,32 +7,17 @@ namespace CommonClient.CustomHandling { - public class RandomDataClientCustomHandler : RandomDataClient, ISoapLoggerHandlerClient + public class WeatherServiceClientCustomHandler : WeatherServiceClient, ISoapLoggerHandlerClient { - public RandomDataClientCustomHandler(WeatherServiceClient client) : base(client) + public WeatherServiceClientCustomHandler() { - } - - protected override void SendRandomReport(string location) - { - SoapLoggerClient.SetCustomHandlerCallbacks(this); - base.SendRandomReport(location); - } - - protected override void GetLastReport(string location) { - SoapLoggerClient.SetCustomHandlerCallbacks(this); - base.GetLastReport(location); - } - - protected override void GetForecast(string location, int days) { + // you need just this line in constructor of inherited client class to apply your custom handler to all requests + // NOTE: don't reuse this custom handling client class object twice, it should be instantiated for every new request SoapLoggerClient.SetCustomHandlerCallbacks(this); - base.GetForecast(location, days); } - - public void HandleRequestBodyCallback(byte[] requestBody, SoapLoggerSettings settings) { WriteFileCustom(requestBody, true, settings.LogPath); @@ -50,8 +35,7 @@ public void CustomHandlersDisabledCallback(SoapLoggerSettings settings) - - + // this custom handling method looks for 'GetLastReportByLocation' only private void WriteFileCustom(byte[] body, bool request, string logPath) { const string operationNameToLog = "GetLastReportByLocation"; @@ -70,12 +54,8 @@ private void WriteFileCustom(byte[] body, bool request, string logPath) } fileNameFactory.AddSegment(operationName); - fileNameFactory.AddSegment(message.GetNodeValue("Body", operationNameToLog, "Location")); -// fileNameFactory.AddSegment(message.GetNodeValue("Body", "SendReport", "report", "location")); -// fileNameFactory.AddSegment(message.GetNodeValue("Body", "GetForecastByLocation", "location")); - fileNameFactory.AddDirection(request); string indentedXml = message.GetIndentedXml(); @@ -95,5 +75,6 @@ private void WriteFileCustom(byte[] body, bool request, string logPath) } } + } } diff --git a/src/UsageExamples/ExampleCommon/CommonClient/RandomDataClient.cs b/src/UsageExamples/ExampleCommon/CommonClient/RandomDataClient.cs index e51043a..aa14fe5 100644 --- a/src/UsageExamples/ExampleCommon/CommonClient/RandomDataClient.cs +++ b/src/UsageExamples/ExampleCommon/CommonClient/RandomDataClient.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading; using System.Threading.Tasks; @@ -10,12 +7,12 @@ namespace CommonClient public class RandomDataClient { private readonly Random _random; - private readonly IWeatherService _client; + private readonly Func _getClient; - public RandomDataClient(IWeatherService client) + public RandomDataClient(Func getClient) { _random = new Random(); - _client = client; + _getClient = getClient; } public void StartThreads() @@ -46,7 +43,7 @@ private void ThreadSleep(int minValue, int maxValue) Thread.Sleep(TimeSpan.FromMilliseconds(_random.Next(minValue, maxValue))); } - protected virtual void SendRandomReport(string location) { + protected void SendRandomReport(string location) { WeatherReport newReport = new WeatherReport(); newReport.DateTime = DateTime.Now; @@ -61,7 +58,7 @@ protected virtual void SendRandomReport(string location) { try { - long id = _client.SendReport(newReport); + long id = _getClient().SendReport(newReport); Console.WriteLine("Report for " + location + ": Report ID = " + id); } catch (Exception ex) @@ -70,10 +67,14 @@ protected virtual void SendRandomReport(string location) { } } - private float GetRandomValue(float minimum, float maximum) - { - return (float)_random.NextDouble() * (maximum - minimum) + minimum; - } + private float GetRandomValue(float minimum, float maximum) + { + double value = minimum + _random.NextDouble() * (maximum - minimum); + value = value * 100; + value = Math.Round(value, MidpointRounding.AwayFromZero); + value = value / 100; + return (float) value; + } private void WatchLastReport(string location) @@ -85,11 +86,11 @@ private void WatchLastReport(string location) } } - protected virtual void GetLastReport(string location) + protected void GetLastReport(string location) { try { - var report = _client.GetLastReportByLocation(location); + var report = _getClient().GetLastReportByLocation(location); if (report == null) { @@ -110,16 +111,16 @@ private void WatchForecast(string location, int days) { while (true) { - ThreadSleep(4000, 7000); + ThreadSleep(3000, 6000); GetForecast(location, days); } } - protected virtual void GetForecast(string location, int days) + protected void GetForecast(string location, int days) { try { - var forecastArray = _client.GetForecastByLocation(location, days); + var forecastArray = _getClient().GetForecastByLocation(location, days); Console.WriteLine("Forecast for " + location + " for " + forecastArray.Length + " days received."); } catch (Exception ex) diff --git a/src/UsageExamples/ExampleCommon/CommonService/CommonService.csproj b/src/UsageExamples/ExampleCommon/CommonService/CommonService.csproj index f7e1bdb..af84517 100644 --- a/src/UsageExamples/ExampleCommon/CommonService/CommonService.csproj +++ b/src/UsageExamples/ExampleCommon/CommonService/CommonService.csproj @@ -44,7 +44,6 @@ - diff --git a/src/UsageExamples/ExampleCommon/CommonService/CustomHandling/CustomHandler_GetForecastByLocation.cs b/src/UsageExamples/ExampleCommon/CommonService/CustomHandling/CustomHandler_GetForecastByLocation.cs deleted file mode 100644 index 398ae81..0000000 --- a/src/UsageExamples/ExampleCommon/CommonService/CustomHandling/CustomHandler_GetForecastByLocation.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System; -using System.IO; -using WcfSoapLogger; -using WcfSoapLogger.Exceptions; -using WcfSoapLogger.FileWriting; -using WcfSoapLogger.HandlerCustom; - -namespace CommonService.CustomHandling -{ - public class CustomHandler_GetForecastByLocation : ISoapLoggerHandlerService - { - public void HandleRequestBody(byte[] requestBody, SoapLoggerSettings settings) - { - WriteFileCustom(requestBody, true, settings.LogPath); - } - - public void HandleResponseBodyCallback(byte[] responseBody, SoapLoggerSettings settings) - { - WriteFileCustom(responseBody, false, settings.LogPath); - } - - public void CustomHandlersDisabled(SoapLoggerSettings settings) - { - Console.WriteLine("CustomHandlersDisabled"); - } - - - private void WriteFileCustom(byte[] body, bool request, string logPath) - { - logPath = Path.Combine(logPath, "GetForecastByLocation"); - - var fileNameFactory = new FileNameFactory(); - - try - { - var message = SoapMessage.Parse(body, request); - fileNameFactory.AddSegment(message.GetOperationName()); - - fileNameFactory.AddSegment(message.GetNodeValue("body", "GetForecastByLocation", "Location")); - - fileNameFactory.AddSegment(message.GetNodeValue("body", "GetForecastByLocationResponse", "GetForecastByLocationResult", "WeatherReport", "Location")); - fileNameFactory.AddSegment(message.GetNodeValue("body", "GetForecastByLocationResponse", "GetForecastByLocationResult", "WeatherReport", "Temperature")); - - fileNameFactory.AddDirection(request); - string indentedXml = message.GetIndentedXml(); - - SoapLoggerTools.WriteFile(fileNameFactory.GetFileName(), indentedXml, null, logPath); - } - catch (FileSystemAcccesDeniedException) - { - throw; - } - catch (Exception ex) - { - fileNameFactory.AddSegment("ERROR"); - SoapLoggerTools.WriteFile(fileNameFactory.GetFileName(), null, body, logPath); - - fileNameFactory.AddSegment("exception"); - SoapLoggerTools.WriteFile(fileNameFactory.GetFileName(), ex.ToString(), null, logPath); - } - } - - } -} diff --git a/src/UsageExamples/ExampleCommon/CommonService/CustomHandling/WeatherServiceEuropeCustomHandler.cs b/src/UsageExamples/ExampleCommon/CommonService/CustomHandling/WeatherServiceEuropeCustomHandler.cs index 0f3fa0c..60e4820 100644 --- a/src/UsageExamples/ExampleCommon/CommonService/CustomHandling/WeatherServiceEuropeCustomHandler.cs +++ b/src/UsageExamples/ExampleCommon/CommonService/CustomHandling/WeatherServiceEuropeCustomHandler.cs @@ -1,47 +1,82 @@ using System; +using System.IO; using WcfSoapLogger; +using WcfSoapLogger.Exceptions; using WcfSoapLogger.FileWriting; using WcfSoapLogger.HandlerCustom; namespace CommonService.CustomHandling { + // this class just inherits standard web-service example and adds own custom handler public class WeatherServiceEuropeCustomHandler : WeatherServiceEurope, ISoapLoggerHandlerService { - public override long SendReport(WeatherReport report) + public WeatherServiceEuropeCustomHandler() { + // you need just this line in web-service constructor to apply your custom handlers to all operation methods + // default WCF behavior is assumed here - creating new class instance 'per call' SoapLoggerService.CallCustomHandlers(this); - return base.SendReport(report); } - public override WeatherReport GetLastReportByLocation(string location) - { - SoapLoggerService.CallCustomHandlers(this); - return base.GetLastReportByLocation(location); - } - - public override WeatherReport[] GetForecastByLocation(string location, int days) - { - SoapLoggerService.CallCustomHandlers(new CustomHandler_GetForecastByLocation()); - return base.GetForecastByLocation(location, days); - } - - - public void HandleRequestBody(byte[] requestBody, SoapLoggerSettings settings) { - SoapLoggerTools.WriteFileDefault(requestBody, true, settings.LogPath); + WriteFileCustom(requestBody, true, settings.LogPath); } public void HandleResponseBodyCallback(byte[] responseBody, SoapLoggerSettings settings) { - SoapLoggerTools.WriteFileDefault(responseBody, false, settings.LogPath); + WriteFileCustom(responseBody, false, settings.LogPath); } public void CustomHandlersDisabled(SoapLoggerSettings settings) { Console.WriteLine("CustomHandlersDisabled"); } + + + + // this custom handling method looks for 'GetForecastByLocation' only + private void WriteFileCustom(byte[] body, bool request, string logPath) + { + const string operationNameToLog = "GetForecastByLocation"; + logPath = Path.Combine(logPath, operationNameToLog); + + var fileNameFactory = new FileNameFactory(); + + try + { + var message = SoapMessage.Parse(body, request); + string operationName = message.GetOperationName(); + + if (operationName != operationNameToLog) + { + return; + } + + fileNameFactory.AddSegment(message.GetNodeValue("Body", "GetForecastByLocation", "Location")); + + fileNameFactory.AddSegment(message.GetNodeValue("Body", "GetForecastByLocationResponse", "GetForecastByLocationResult", "WeatherReport", "Location")); + fileNameFactory.AddSegment(message.GetNodeValue("Body", "GetForecastByLocationResponse", "GetForecastByLocationResult", "WeatherReport", "Temperature")); + + fileNameFactory.AddDirection(request); + string indentedXml = message.GetIndentedXml(); + + SoapLoggerTools.WriteFile(fileNameFactory.GetFileName(), indentedXml, null, logPath); + } + catch (FileSystemAcccesDeniedException) + { + throw; + } + catch (Exception ex) + { + fileNameFactory.AddSegment("ERROR"); + SoapLoggerTools.WriteFile(fileNameFactory.GetFileName(), null, body, logPath); + + fileNameFactory.AddSegment("exception"); + SoapLoggerTools.WriteFile(fileNameFactory.GetFileName(), ex.ToString(), null, logPath); + } + } + } } diff --git a/src/UsageExamples/ExampleCommon/CommonService/ForecastCalculator.cs b/src/UsageExamples/ExampleCommon/CommonService/ForecastCalculator.cs index 4a910aa..374556c 100644 --- a/src/UsageExamples/ExampleCommon/CommonService/ForecastCalculator.cs +++ b/src/UsageExamples/ExampleCommon/CommonService/ForecastCalculator.cs @@ -40,6 +40,8 @@ public WeatherReport[] GetForecast(string location, int days) clone.DateTime = clone.DateTime.AddDays(i + 1).Date; clone.Temperature += GetRandomValue(0.1f, 3); clone.Pressure += GetRandomValue(-10, +10); + clone.WindSpeed = GetRandomValue(0.1f, 8.0f); + clone.WindDirection = GetRandomValue(0, 360); list.Add(clone); } @@ -49,7 +51,11 @@ public WeatherReport[] GetForecast(string location, int days) private float GetRandomValue(float minimum, float maximum) { - return (float)_random.NextDouble() * (maximum - minimum) + minimum; + double value = minimum + _random.NextDouble() * (maximum - minimum); + value = value * 100; + value = Math.Round(value, MidpointRounding.AwayFromZero); + value = value / 100; + return (float) value; } } } diff --git a/src/UsageExamples/ExampleCommon/CommonService/ReportRepository.cs b/src/UsageExamples/ExampleCommon/CommonService/ReportRepository.cs index 2728ac4..cda2c7e 100644 --- a/src/UsageExamples/ExampleCommon/CommonService/ReportRepository.cs +++ b/src/UsageExamples/ExampleCommon/CommonService/ReportRepository.cs @@ -17,6 +17,8 @@ public long Add(WeatherReport report) if (report.Id % 5 == 0) { + + Console.WriteLine("Throwing exception for Report ID = " + report.Id); throw new InvalidOperationException($"Oops! Report with ID '{report.Id}' produced an error on server. Look for its Fault_Response.xml in log folder."); } diff --git a/src/UsageExamples/ExampleCommon/CommonService/WeatherServiceEurope.cs b/src/UsageExamples/ExampleCommon/CommonService/WeatherServiceEurope.cs index 7843f65..4642696 100644 --- a/src/UsageExamples/ExampleCommon/CommonService/WeatherServiceEurope.cs +++ b/src/UsageExamples/ExampleCommon/CommonService/WeatherServiceEurope.cs @@ -4,6 +4,8 @@ namespace CommonService { + // this class is simple standard web-service example without any extra stuff + [ServiceBehavior(Namespace = XmlNamespaces.WeatherService)] public class WeatherServiceEurope : IWeatherService { @@ -11,7 +13,8 @@ public class WeatherServiceEurope : IWeatherService private static readonly ForecastCalculator _forecastCalculator = new ForecastCalculator(_reportRepository); private static readonly Random _random = new Random(); - public virtual long SendReport(WeatherReport report) + + public long SendReport(WeatherReport report) { Console.WriteLine("SendReport for " + report.Location + ": request"); @@ -22,7 +25,8 @@ public virtual long SendReport(WeatherReport report) return id; } - public virtual WeatherReport GetLastReportByLocation(string location) + + public WeatherReport GetLastReportByLocation(string location) { Console.WriteLine("GetLastReport for " + location + ": request"); @@ -38,7 +42,8 @@ public virtual WeatherReport GetLastReportByLocation(string location) return lastReport; } - public virtual WeatherReport[] GetForecastByLocation(string location, int days) + + public WeatherReport[] GetForecastByLocation(string location, int days) { Console.WriteLine("Forecast for " + location + " for " + days + " days: request"); diff --git a/src/UsageExamples/ExampleDelta/Client/Program.cs b/src/UsageExamples/ExampleDelta/Client/Program.cs index 0fa134a..11f5ad9 100644 --- a/src/UsageExamples/ExampleDelta/Client/Program.cs +++ b/src/UsageExamples/ExampleDelta/Client/Program.cs @@ -19,7 +19,7 @@ private static void Main() serviceClient.ClientCredentials.UserName.UserName = "neo"; serviceClient.ClientCredentials.UserName.Password = "matrix"; - var randomDataClient = new RandomDataClient(serviceClient); + var randomDataClient = new RandomDataClient(() => serviceClient); randomDataClient.StartThreads(); Task.Delay(500).ContinueWith(_ => Process.Start("explorer.exe", @"C:\SoapLog\Delta")); diff --git a/src/UsageExamples/ExampleEpsilon/Client/Program.cs b/src/UsageExamples/ExampleEpsilon/Client/Program.cs index 1c8b146..2e145ab 100644 --- a/src/UsageExamples/ExampleEpsilon/Client/Program.cs +++ b/src/UsageExamples/ExampleEpsilon/Client/Program.cs @@ -30,7 +30,7 @@ private static void Main() var serviceClient = new WeatherServiceClient(customBinding, address); - var randomDataClient = new RandomDataClient(serviceClient); + var randomDataClient = new RandomDataClient(() => serviceClient); randomDataClient.StartThreads(); Task.Delay(500).ContinueWith(_ => Process.Start("explorer.exe", logPath)); diff --git a/src/UsageExamples/ExampleGamma/Client/Program.cs b/src/UsageExamples/ExampleGamma/Client/Program.cs index c670e59..07eda85 100644 --- a/src/UsageExamples/ExampleGamma/Client/Program.cs +++ b/src/UsageExamples/ExampleGamma/Client/Program.cs @@ -15,11 +15,12 @@ private static void Main() Console.ReadKey(); Console.WriteLine(); - var serviceClient = new WeatherServiceClient(); - var randomDataClient = new RandomDataClientCustomHandler(serviceClient); + // if we use custom handling - each new request should use new client class object + + var randomDataClient = new RandomDataClient(() => new WeatherServiceClientCustomHandler()); randomDataClient.StartThreads(); - Task.Delay(500).ContinueWith( _ => Process.Start("explorer.exe", @"C:\SoapLog\Gamma")); + Task.Delay(3000).ContinueWith( _ => Process.Start("explorer.exe", @"C:\SoapLog\Gamma")); Console.ReadLine(); }