diff --git a/NLog.Web.AspNetCore.Tests/LayoutRenderers/AspNetCookieLayoutRendererTests.cs b/NLog.Web.AspNetCore.Tests/LayoutRenderers/AspNetCookieLayoutRendererTests.cs index c162c538..5816f5e9 100644 --- a/NLog.Web.AspNetCore.Tests/LayoutRenderers/AspNetCookieLayoutRendererTests.cs +++ b/NLog.Web.AspNetCore.Tests/LayoutRenderers/AspNetCookieLayoutRendererTests.cs @@ -1,14 +1,14 @@ -#if !NETSTANDARD_1plus -//TODO test .NET Core -using System; +using System; using System.Collections.Generic; using System.Globalization; +using System.Linq; using NLog.Web.LayoutRenderers; using NSubstitute; using NLog.Web.Enums; using Xunit; using System.Reflection; + using NLog.Config; using NLog.Layouts; using NLog.Targets; @@ -18,6 +18,8 @@ using System.Collections.Specialized; using System.Web.SessionState; #else +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Internal; using Microsoft.Extensions.Primitives; using HttpContextBase = Microsoft.AspNetCore.Http.HttpContext; #endif @@ -75,9 +77,34 @@ public void KeyNotFoundRendersEmptyString_Json_Formatting() [Fact] public void KeyFoundRendersValue_Cookie_Mulitple_Items_Flat_Formatting() { +#if NETSTANDARD_1plus + //no multivalue keys in ASP.NET core + var expectedResult = "key=TEST,Key1=TEST1"; +#else var expectedResult = "key=TEST&Key1=TEST1"; +#endif + + var renderer = CreateRenderer(); + + string result = renderer.Render(new LogEventInfo()); + + Assert.Equal(expectedResult, result); + } + + + [Fact] + public void KeyFoundRendersValue_Cookie_Multiple_Items_Flat_Formatting_separators() + { +#if NETSTANDARD_1plus + //no multivalue keys in ASP.NET core + var expectedResult = "key:TEST|Key1:TEST1"; +#else + var expectedResult = "key:TEST&Key1=TEST1"; +#endif var renderer = CreateRenderer(); + renderer.ValueSeparator = ":"; + renderer.ItemSeparator = "|"; string result = renderer.Render(new LogEventInfo()); @@ -97,28 +124,60 @@ public void KeyFoundRendersValue_Single_Item_Flat_Formatting() } [Fact] - public void KeyFoundRendersValue_Cookie_Mulitple_Items_Json_Formatting() + public void KeyFoundRendersValue_Single_Item_Json_Formatting() { - var expectedResult = "{\"key=TEST&Key1=TEST1\"}"; + var expectedResult = "[{\"key\":\"TEST\"}]"; - var renderer = CreateRenderer(); + var renderer = CreateRenderer(addKey: false); + + renderer.OutputFormat = AspNetRequestLayoutOutputFormat.Json; + + string result = renderer.Render(new LogEventInfo()); + + Assert.Equal(expectedResult, result); + } + + [Fact] + public void KeyFoundRendersValue_Single_Item_Json_Formatting_no_array() + { + var expectedResult = "{\"key\":\"TEST\"}"; + + var renderer = CreateRenderer(addKey: false); + + renderer.OutputFormat = AspNetRequestLayoutOutputFormat.Json; + renderer.SingleAsArray = false; + + string result = renderer.Render(new LogEventInfo()); + + Assert.Equal(expectedResult, result); + } + [Theory] + [InlineData(false)] + [InlineData(true)] + public void KeyFoundRendersValue_Cookie_Mulitple_Items_Json_Formatting(bool singleAsArray) + { + var expectedResult = "[{\"key\":\"TEST\"},{\"Key1\":\"TEST1\"}]"; + + var renderer = CreateRenderer(); renderer.OutputFormat = AspNetRequestLayoutOutputFormat.Json; + renderer.SingleAsArray = singleAsArray; string result = renderer.Render(new LogEventInfo()); Assert.Equal(expectedResult, result); } +//no multivalue keys in ASP.NET core +#if !NETSTANDARD_1plus + [Fact] public void KeyFoundRendersVakue_Cookie_Mulitple_Cookies_Cookie_Items_Flat_Formatting() { var expectedResult = "key=TEST&Key1=TEST1,key2=Test&key3=Test456"; - var renderer = CreateRenderer(addCookie2: true); - - + var renderer = CreateRenderer(addCookie2: true); renderer.CookieNames = new List { "key", "key2" }; @@ -130,7 +189,7 @@ public void KeyFoundRendersVakue_Cookie_Mulitple_Cookies_Cookie_Items_Flat_Forma [Fact] public void KeyFoundRendersVakue_Cookie_Mulitple_Cookies_Cookie_Items_Json_Formatting() { - var expectedResult = "{\"key=TEST&Key1=TEST1\"},{\"key2=Test&key3=Test456\"}"; + var expectedResult = "[{\"key\":\"TEST\"},{\"Key1\":\"TEST1\"},{\"key2\":\"Test\"},{\"key3\":\"Test456\"}]"; var renderer = CreateRenderer(addCookie2: true); renderer.OutputFormat = AspNetRequestLayoutOutputFormat.Json; @@ -138,6 +197,9 @@ public void KeyFoundRendersVakue_Cookie_Mulitple_Cookies_Cookie_Items_Json_Forma Assert.Equal(expectedResult, result); } +#endif + +#if !NETSTANDARD_1plus //todo [Fact] public void CommaSeperatedCookieNamesTest_Mulitple_FLAT_Formatting() @@ -170,7 +232,7 @@ public void CommaSeperatedCookieNamesTest_Mulitple_FLAT_Formatting() [Fact] public void CommaSeperatedCookieNamesTest_Mulitple_Json_Formatting() { - var expectedResult = "{\"key=TEST&Key1=TEST1\"}"; + var expectedResult = "[{\"key\":\"TEST\"},{\"Key1\":\"TEST1\"}]"; string config = @" @@ -192,6 +254,8 @@ public void CommaSeperatedCookieNamesTest_Mulitple_Json_Formatting() Assert.Equal(expectedResult, result); } +#endif + /// /// Create cookie renderer with mockup http context /// @@ -200,15 +264,55 @@ public void CommaSeperatedCookieNamesTest_Mulitple_Json_Formatting() /// private static AspNetRequestCookieLayoutRenderer CreateRenderer(bool addKey = true, bool addCookie2 = false) { + var cookieNames = new List(); var httpContext = Substitute.For(); + + +#if NETSTANDARD_1plus + IRequestCookieCollection cookies = Substitute.For(); + var cookieDict = new Dictionary(); + + void AddCookie(string key, string result) + { + cookieNames.Add(key); + cookies[key].Returns(result); + cookieDict.Add(key, result); + } + + AddCookie("key", "TEST"); + + if (addKey) + { + AddCookie("Key1", "TEST1"); + } + + if (addCookie2) + { + AddCookie("key2", "Test"); + AddCookie("key3", "Test456"); + } + + cookies.Count.Returns(cookieDict.Count); + + cookies.TryGetValue("", out var _) + .ReturnsForAnyArgs(callInfo => + { + var name = callInfo.Args().First()?.ToString(); + var returnVal = cookieDict.TryGetValue(name, out var cookie); + callInfo[1] = cookie; + return returnVal; + }); + +#else + var cookie1 = new HttpCookie("key", "TEST"); + cookieNames.Add("key"); if (addKey) { cookie1["Key1"] = "TEST1"; } - var cookies = new HttpCookieCollection { cookie1 }; - var cookieNames = new List { "key" }; + if (addCookie2) { var cookie2 = new HttpCookie("key2", "Test"); @@ -216,6 +320,8 @@ private static AspNetRequestCookieLayoutRenderer CreateRenderer(bool addKey = tr cookies.Add(cookie2); cookieNames.Add("key2"); } +#endif + httpContext.Request.Cookies.Returns(cookies); var renderer = new AspNetRequestCookieLayoutRenderer(); @@ -230,4 +336,3 @@ private static AspNetRequestCookieLayoutRenderer CreateRenderer(bool addKey = tr } } } -#endif \ No newline at end of file diff --git a/NLog.Web.AspNetCore.Tests/LayoutRenderers/AspNetQueryStringLayoutRendererTests.cs b/NLog.Web.AspNetCore.Tests/LayoutRenderers/AspNetQueryStringLayoutRendererTests.cs index 7283072c..d5d2c9e8 100644 --- a/NLog.Web.AspNetCore.Tests/LayoutRenderers/AspNetQueryStringLayoutRendererTests.cs +++ b/NLog.Web.AspNetCore.Tests/LayoutRenderers/AspNetQueryStringLayoutRendererTests.cs @@ -68,7 +68,7 @@ public void KeyNotFoundRendersEmptyString_Json_Formatting() [Fact] public void KeyFoundRendersValue_QueryString_Single_Item_Flat_Formatting() { - var expectedResult = "Id:1"; + var expectedResult = "Id=1"; var renderer = CreateAndMockRenderer(CreateTuple("Id", "1")); @@ -98,7 +98,7 @@ public void KeyFoundRendersValue_QueryString_Single_Item_Json_Formatting() [Fact] public void KeyFoundRendersValue_QueryString_Multiple_Item_Flat_Formatting() { - var expectedResult = "Id:1," + Environment.NewLine + "Id2:2"; + var expectedResult = "Id=1,Id2=2"; var renderer = CreateAndMockRenderer(CreateTuple("Id", "1"), CreateTuple("Id2", "2")); @@ -113,7 +113,7 @@ public void KeyFoundRendersValue_QueryString_Multiple_Item_Flat_Formatting() [Fact] public void EmptyProperyShouldListAll() { - var expectedResult = "Id:1," + Environment.NewLine + "Id2:2"; + var expectedResult = "Id=1,Id2=2"; var renderer = CreateAndMockRenderer(CreateTuple("Id", "1"), CreateTuple("Id2", "2")); @@ -128,7 +128,7 @@ public void EmptyProperyShouldListAll() [Fact] public void NullProperyShouldListAll() { - var expectedResult = "Id:1," + Environment.NewLine + "Id2:2"; + var expectedResult = "Id=1,Id2=2"; var renderer = CreateAndMockRenderer(CreateTuple("Id", "1"), CreateTuple("Id2", "2")); @@ -142,7 +142,7 @@ public void NullProperyShouldListAll() [Fact] public void MultipleValuesForOneKeyShouldWork() { - var expectedResult = "Id:1,2,3"; + var expectedResult = "Id=1,2,3"; var renderer = CreateAndMockRenderer(CreateTuple("Id", "1", "2", "3")); @@ -154,10 +154,27 @@ public void MultipleValuesForOneKeyShouldWork() Assert.Equal(expectedResult, result); } + [Fact] + public void MultipleValuesJsonQuoted() + { + + var expectedResult = @"{""Id"":""a'b,\""c\""""}"; + + var renderer = CreateAndMockRenderer(CreateTuple("Id", "a'b", "\"c\"")); + + renderer.QueryStringKeys = null; + renderer.OutputFormat = AspNetRequestLayoutOutputFormat.Json; + renderer.SingleAsArray = false; + + string result = renderer.Render(new LogEventInfo()); + + Assert.Equal(expectedResult, result); + } + [Fact] public void KeyFoundRendersValue_QueryString_Multiple_Item_Json_Formatting() { - var expectedResult = "[" + "{\"Id\":\"1\"}," + Environment.NewLine + "{\"Id2\":\"2\"}" + "]"; + var expectedResult = "[{\"Id\":\"1\"},{\"Id2\":\"2\"}]"; var renderer = CreateAndMockRenderer(CreateTuple("Id", "1"), CreateTuple("Id2", "2")); diff --git a/NLog.Web.AspNetCore.Tests/NLog.Web.AspNetCore.Tests.csproj b/NLog.Web.AspNetCore.Tests/NLog.Web.AspNetCore.Tests.csproj index a537cd9f..309292fa 100644 --- a/NLog.Web.AspNetCore.Tests/NLog.Web.AspNetCore.Tests.csproj +++ b/NLog.Web.AspNetCore.Tests/NLog.Web.AspNetCore.Tests.csproj @@ -1,7 +1,7 @@  - netcoreapp1.1;net452 + net452 $(DefineConstants);NETSTANDARD_1plus NLog.Web.AspNetCore.Tests @@ -26,6 +26,10 @@ + + + + diff --git a/NLog.Web.AspNetCore/Enums/AspNetCookieLayoutOutPutFormat.cs b/NLog.Web.AspNetCore/Enums/AspNetRequestLayoutOutputFormat.cs similarity index 51% rename from NLog.Web.AspNetCore/Enums/AspNetCookieLayoutOutPutFormat.cs rename to NLog.Web.AspNetCore/Enums/AspNetRequestLayoutOutputFormat.cs index fdff5098..a034cf10 100644 --- a/NLog.Web.AspNetCore/Enums/AspNetCookieLayoutOutPutFormat.cs +++ b/NLog.Web.AspNetCore/Enums/AspNetRequestLayoutOutputFormat.cs @@ -3,16 +3,16 @@ namespace NLog.Web.Enums { /// - /// To control the Cookie Renderer Output formatting. + /// To control the Renderer Output formatting. /// public enum AspNetRequestLayoutOutputFormat { /// - /// Use this format for rendering the cookie renderer output value as a flat string. + /// Use this format for rendering the output value as a flat string. /// Flat = 0, /// - /// Use this format for rendering the cookie renderer output value as a json formatted string. + /// Use this format for rendering the output value as a json formatted string. /// Json = 1, } diff --git a/NLog.Web.AspNetCore/Internal/GlobalConstants.cs b/NLog.Web.AspNetCore/Internal/GlobalConstants.cs deleted file mode 100644 index a1935485..00000000 --- a/NLog.Web.AspNetCore/Internal/GlobalConstants.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace NLog.Web.Internal -{ - internal sealed class GlobalConstants - { - internal const string doubleQuotes = "\""; - internal const string jsonElementSeparator = ","; - internal const string jsonElementStartBraces = "{"; - internal const string jsonElementEndBraces = "}"; - internal const string jsonArrayStartBraces = "["; - internal const string jsonArrayEndBraces = "]"; - } -} \ No newline at end of file diff --git a/NLog.Web.AspNetCore/LayoutRenderers/AspNetLayoutMultiValueRendererBase.cs b/NLog.Web.AspNetCore/LayoutRenderers/AspNetLayoutMultiValueRendererBase.cs new file mode 100644 index 00000000..94cb3d6c --- /dev/null +++ b/NLog.Web.AspNetCore/LayoutRenderers/AspNetLayoutMultiValueRendererBase.cs @@ -0,0 +1,129 @@ +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NLog.Config; +using NLog.Web.Enums; + +namespace NLog.Web.LayoutRenderers +{ + /// + /// Layout renderers for ASP.NET rendering multiple values. + /// + public abstract class AspNetLayoutMultiValueRendererBase : AspNetLayoutRendererBase + { + /// + /// Separator between item. Only used for + /// + public string ItemSeparator { get; set; } = ","; + + /// + /// Separator between value and key. Only used for + /// + public string ValueSeparator { get; set; } = "="; + + /// + /// Single item in array? Only used for + /// + /// Mutliple items are always in an array. + /// + public bool SingleAsArray { get; set; } = true; + + /// + /// Determines how the output is rendered. Possible Value: FLAT, JSON. Default is FLAT. + /// + [DefaultParameter] + public AspNetRequestLayoutOutputFormat OutputFormat { get; set; } = AspNetRequestLayoutOutputFormat.Flat; + + /// + /// Serialize multiple values + /// + /// The values with key and value. + /// Add to this builder. + protected void SerializeValues(IEnumerable> values, + StringBuilder builder) + { + var firstItem = true; + switch (OutputFormat) + { + case AspNetRequestLayoutOutputFormat.Flat: + + foreach (var kpv in values) + { + var key = kpv.Key; + var value = kpv.Value; + + if (!firstItem) + { + builder.Append(ItemSeparator); + } + firstItem = false; + builder.Append(key); + builder.Append(ValueSeparator); + builder.Append(value); + } + + + break; + case AspNetRequestLayoutOutputFormat.Json: + + + var valueList = values.ToList(); + + if (valueList.Count > 0) + { + var addArray = valueList.Count > (SingleAsArray ? 0 : 1); + + if (addArray) + { + builder.Append('['); + } + + foreach (var kpv in valueList) + { + var key = kpv.Key; + var value = kpv.Value; + if (!firstItem) + { + builder.Append(','); + } + firstItem = false; + + //quoted key + builder.Append('{'); + AppendQuoted(builder, key); + + builder.Append(':'); + //quoted value; + AppendQuoted(builder, value); + builder.Append('}'); + } + if (addArray) + { + builder.Append(']'); + } + } + break; + } + } + + /// + /// Append the value quoted, escape quotes when needed + /// + /// + /// + private static void AppendQuoted(StringBuilder builder, string value) + { + builder.Append('"'); + if (!string.IsNullOrEmpty(value) && value.Contains('"')) + { + //escape quotes + builder.Append(value.Replace("\"", "\\\"")); + } + else + { + builder.Append(value); + } + builder.Append('"'); + } + } +} \ No newline at end of file diff --git a/NLog.Web.AspNetCore/LayoutRenderers/AspNetLayoutRendererBase.cs b/NLog.Web.AspNetCore/LayoutRenderers/AspNetLayoutRendererBase.cs index 64a43a1c..877340fe 100644 --- a/NLog.Web.AspNetCore/LayoutRenderers/AspNetLayoutRendererBase.cs +++ b/NLog.Web.AspNetCore/LayoutRenderers/AspNetLayoutRendererBase.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; using System.Text; using NLog.LayoutRenderers; #if NETSTANDARD_1plus @@ -71,5 +73,7 @@ protected override void Append(StringBuilder builder, LogEventInfo logEvent) /// The to append the rendered data to. /// Logging event. protected abstract void DoAppend(StringBuilder builder, LogEventInfo logEvent); + + } } diff --git a/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestCookieLayoutRenderer.cs b/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestCookieLayoutRenderer.cs index 58c78454..66bb4c0b 100644 --- a/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestCookieLayoutRenderer.cs +++ b/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestCookieLayoutRenderer.cs @@ -1,15 +1,18 @@ using System.Text; #if !NETSTANDARD_1plus -using System.Web; using System.Collections.Specialized; +using System.Web; #else using Microsoft.Extensions.Primitives; +using Microsoft.AspNetCore.Http; #endif using NLog.LayoutRenderers; using System.Collections.Generic; using NLog.Config; using NLog.Web.Enums; using System; +using System.Linq; + using NLog.Web.Internal; namespace NLog.Web.LayoutRenderers @@ -25,22 +28,13 @@ namespace NLog.Web.LayoutRenderers /// /// [LayoutRenderer("aspnet-request-cookie")] - public class AspNetRequestCookieLayoutRenderer : AspNetLayoutRendererBase + public class AspNetRequestCookieLayoutRenderer : AspNetLayoutMultiValueRendererBase { - private const string cookiesNameSeparator = "="; - private const string flatItemSeperator = ","; - /// /// List Cookie Key as String to be rendered from Request. /// public List CookieNames { get; set; } - /// - /// Determines how the output is rendered. Possible Value: FLAT, JSON. Default is FLAT. - /// - [DefaultParameter] - public AspNetRequestLayoutOutputFormat OutputFormat { get; set; } = AspNetRequestLayoutOutputFormat.Flat; - /// /// Renders the ASP.NET Cookie appends it to the specified . /// @@ -55,53 +49,72 @@ protected override void DoAppend(StringBuilder builder, LogEventInfo logEvent) return; } - if (this.CookieNames?.Count > 0 && httpRequest?.Cookies?.Count > 0) + var cookies = httpRequest.Cookies; + + if (this.CookieNames?.Count > 0 && cookies?.Count > 0) { - bool firstItem = true; - foreach (var cookieName in this.CookieNames) - { - var cookieValue = httpRequest.Cookies[cookieName]; - this.SerializeCookie(cookieName, cookieValue, builder, firstItem); - firstItem = false; - } + var cookieValues = GetCookies(cookies); + SerializeValues(cookieValues, builder); } } + #if !NETSTANDARD_1plus - /// - /// To Serialize the HttpCookie based on the configured output format. - /// - /// Name of the cookie - /// The current cookie item. - /// The to append the rendered data to. - /// Whether it is first item. - private void SerializeCookie(string cookieName, HttpCookie cookie, StringBuilder builder, bool firstItem) + + private IEnumerable> GetCookies(HttpCookieCollection cookies) { - if (cookie != null) + var cookieNames = this.CookieNames; + if (cookieNames != null) { - this.SerializeCookie(cookieName, cookie.Value, builder, firstItem); + foreach (var cookieName in cookieNames) + { + var value = cookies[cookieName]; + + + + if (value != null) + { + if (this.OutputFormat == AspNetRequestLayoutOutputFormat.Json) + { + //split + var isFirst = true; + foreach (var key in value.Values.AllKeys) + { + var key2 = key; + if (isFirst) + { + key2 = cookieName; + isFirst = false; + } + yield return new KeyValuePair(key2, value.Values[key]); + } + } + else + { + yield return new KeyValuePair(cookieName, value.Value); + } + } + } } } +#else -#endif - private void SerializeCookie(string cookieName, string cookieValue, StringBuilder builder, bool firstItem) + private IEnumerable> GetCookies(IRequestCookieCollection cookies) { - var cookieRaw = $"{cookieName}{cookiesNameSeparator}{cookieValue}"; - - switch (this.OutputFormat) + var cookieNames = this.CookieNames; + if (cookieNames != null) { - case AspNetRequestLayoutOutputFormat.Flat: - if (!firstItem) - builder.Append($"{flatItemSeperator}"); - builder.Append(cookieRaw); - break; - case AspNetRequestLayoutOutputFormat.Json: - if (!firstItem) - builder.Append($"{GlobalConstants.jsonElementSeparator}"); - - builder.Append($"{GlobalConstants.jsonElementStartBraces}{GlobalConstants.doubleQuotes}{cookieRaw}{GlobalConstants.doubleQuotes}{GlobalConstants.jsonElementEndBraces}"); - break; + foreach (var cookieName in cookieNames) + { + if (cookies.TryGetValue(cookieName, out var cookieValue)) + { + yield return new KeyValuePair(cookieName, cookieValue); + } + } } } +#endif + + } } diff --git a/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestQueryStringLayoutRenderer.cs b/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestQueryStringLayoutRenderer.cs index 46ea41e5..a1c65787 100644 --- a/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestQueryStringLayoutRenderer.cs +++ b/NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestQueryStringLayoutRenderer.cs @@ -26,7 +26,7 @@ namespace NLog.Web.LayoutRenderers /// /// [LayoutRenderer("aspnet-request-querystring")] - public class AspNetQueryStringLayoutRenderer : AspNetLayoutRendererBase + public class AspNetQueryStringLayoutRenderer : AspNetLayoutMultiValueRendererBase { /// /// List Query Strings' Key to be rendered from Request. @@ -34,12 +34,6 @@ public class AspNetQueryStringLayoutRenderer : AspNetLayoutRendererBase /// public List QueryStringKeys { get; set; } - /// - /// Determines how the output is rendered. Possible Value: FLAT, JSON. Default is FLAT. - /// - [DefaultParameter] - public AspNetRequestLayoutOutputFormat OutputFormat { get; set; } = AspNetRequestLayoutOutputFormat.Flat; - /// /// Renders the specified ASP.NET Application variable and appends it to the specified . /// @@ -51,10 +45,10 @@ protected override void DoAppend(StringBuilder builder, LogEventInfo logEvent) if (httpRequest == null) return; - - - var allQueryStrings = this.QueryStringKeys == null || this.QueryStringKeys.Count == 0; + + + var printAllQueryString = this.QueryStringKeys == null || this.QueryStringKeys.Count == 0; var queryStringKeys = this.QueryStringKeys; #if !NETSTANDARD_1plus var queryStrings = httpRequest.QueryString; @@ -63,7 +57,7 @@ protected override void DoAppend(StringBuilder builder, LogEventInfo logEvent) return; - if (allQueryStrings) + if (printAllQueryString) { queryStringKeys = new List(queryStrings.Keys.Count); @@ -81,68 +75,41 @@ protected override void DoAppend(StringBuilder builder, LogEventInfo logEvent) if (queryStrings == null) return; - if (allQueryStrings) + if (printAllQueryString) { queryStringKeys = queryStrings.Keys.ToList(); } #endif + var values = GetValues(queryStrings, queryStringKeys); + SerializeValues(values, builder); + } - var includeArrayEndBraces = false; - + private static IEnumerable> GetValues( +#if NETSTANDARD_1plus + IQueryCollection queryStrings, +#else + NameValueCollection queryStrings, +#endif + IEnumerable queryStringKeys) + + { if (queryStrings.Count > 0) { - var firstItem = true; - - foreach (var configuredKey in queryStringKeys) + foreach (var key in queryStringKeys) { // This platoform specific code is to prevent an unncessary .ToString call otherwise. #if !NETSTANDARD_1plus - var value = queryStrings[configuredKey]; + var value = queryStrings[key]; #else - var value = queryStrings[configuredKey].ToString(); + var value = queryStrings[key].ToString(); #endif if (!String.IsNullOrEmpty(value)) { - this.AppendKeyAndValue(builder, configuredKey, value, firstItem, ref includeArrayEndBraces); - firstItem = false; + yield return new KeyValuePair(key, value); } } } - - if (includeArrayEndBraces) - builder.Append(GlobalConstants.jsonArrayEndBraces); - } - - /// - /// Renders the specified Key and Value to the string builder . Also sets whether to append the Array braces for json . - /// - /// The to append the rendered data to. - /// The Key to append to the specified StringBuilder. - /// The Value to append to the specified StringBuilder. - /// The to specify if the Specified Key, Value is a first Item in the collection. - /// The to specify if the builder needs to append the Json Array End braces. - private void AppendKeyAndValue(StringBuilder builder, string configuredKey, string value, bool isFirsItem, ref bool includeArrayEndBraces) - { - if (!isFirsItem) - builder.Append($",{Environment.NewLine}"); - - switch (this.OutputFormat) - { - case AspNetRequestLayoutOutputFormat.Flat: - builder.Append($"{configuredKey}:{value}"); - break; - case AspNetRequestLayoutOutputFormat.Json: - if (!includeArrayEndBraces) - { - builder.Append(GlobalConstants.jsonArrayStartBraces); - includeArrayEndBraces = true; - } - builder.Append($"{GlobalConstants.jsonElementStartBraces}{GlobalConstants.doubleQuotes}{configuredKey}{GlobalConstants.doubleQuotes}:{GlobalConstants.doubleQuotes}{value}{GlobalConstants.doubleQuotes}{GlobalConstants.jsonElementEndBraces}"); - break; - default: - break; - } } } } diff --git a/NLog.Web.AspNetCore/NLog.Web.AspNetCore.csproj b/NLog.Web.AspNetCore/NLog.Web.AspNetCore.csproj index 7577ed58..6347ee72 100644 --- a/NLog.Web.AspNetCore/NLog.Web.AspNetCore.csproj +++ b/NLog.Web.AspNetCore/NLog.Web.AspNetCore.csproj @@ -36,6 +36,7 @@ + diff --git a/NLog.Web/NLog.Web.csproj b/NLog.Web/NLog.Web.csproj index 18ec4d4e..bc6cb2c3 100644 --- a/NLog.Web/NLog.Web.csproj +++ b/NLog.Web/NLog.Web.csproj @@ -60,6 +60,8 @@ + + @@ -76,13 +78,12 @@ - + -