-
Notifications
You must be signed in to change notification settings - Fork 165
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Added aspnet-request-form layout renderer that outputs all or some of the request form collection. * Made the aspnet-request-form layout renderer output uniform in both asp.net core and .net * Added unit tests for aspnet-request-form layout renderer. * Fixed issues with the unit tests for aspnet-request-form not working in the AspNetCore.Tests project. * Removed code duplication by changing to a foreach that works for both AspNetCore and .net framework . * Changed Include and Exclude to case insensitive HashSets. * Added unit test to cove exclude/include precedence and updated comments. * Made AspNetRequestFormLayoutRenderer a subclass of AspNetLayoutMultiValueRendererBase
- Loading branch information
1 parent
9d95873
commit 21989ad
Showing
4 changed files
with
247 additions
and
0 deletions.
There are no files selected for viewing
147 changes: 147 additions & 0 deletions
147
NLog.Web.AspNetCore.Tests/LayoutRenderers/AspNetRequestFormLayoutRendererTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
using NLog.Web.Tests.LayoutRenderers; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
using NLog.Web.LayoutRenderers; | ||
using NLog.Web.Tests; | ||
using NSubstitute; | ||
using System.Collections.Specialized; | ||
#if ASP_NET_CORE | ||
using Microsoft.AspNetCore.Http; | ||
using Microsoft.Extensions.Primitives; | ||
#else | ||
using System.Web; | ||
#endif | ||
using Xunit; | ||
|
||
namespace NLog.Web.Tests.LayoutRenderers | ||
{ | ||
public class AspNetRequestFormLayoutRendererTests : TestInvolvingAspNetHttpContext | ||
{ | ||
[Fact] | ||
public void ShouldReturnEmptyIfFormCollectionIsEmpty() | ||
{ | ||
// Arrange | ||
var expectedResult = ""; | ||
var renderer = CreateRenderer(false); | ||
|
||
// Act | ||
string result = renderer.Render(new LogEventInfo()); | ||
|
||
// Assert | ||
Assert.Equal(expectedResult, result); | ||
} | ||
|
||
[Fact] | ||
public void ShouldReturnAllIfDefaultsAreUsed() | ||
{ | ||
// Arrange | ||
var expectedResult = "id=1,name=Test Person,token=86abe8fe-2237-4f87-81af-0a4e522b4140"; | ||
var renderer = CreateRenderer(); | ||
|
||
// Act | ||
string result = renderer.Render(new LogEventInfo()); | ||
|
||
// Assert | ||
Assert.Equal(expectedResult, result); | ||
} | ||
|
||
[Fact] | ||
public void ShouldReturnOnlySpecifiedIfIncludeIsUsed() | ||
{ | ||
// Arrange | ||
var expectedResult = "id=1,name=Test Person"; | ||
var renderer = CreateRenderer(); | ||
renderer.Include.Add("id"); | ||
renderer.Include.Add("name"); | ||
|
||
// Act | ||
string result = renderer.Render(new LogEventInfo()); | ||
|
||
// Assert | ||
Assert.Equal(expectedResult, result); | ||
} | ||
|
||
[Fact] | ||
public void ShouldNotReturnKeysSpecidiedInExclude() | ||
{ | ||
// Arrange | ||
var expectedResult = "id=1,name=Test Person"; | ||
var renderer = CreateRenderer(); | ||
renderer.Exclude.Add("token"); | ||
|
||
// Act | ||
string result = renderer.Render(new LogEventInfo()); | ||
|
||
// Assert | ||
Assert.Equal(expectedResult, result); | ||
} | ||
|
||
[Fact] | ||
public void ShouldUseTheSpecifiedSeparator() | ||
{ | ||
// Arrange | ||
var expectedResult = "id=1\r\nname=Test Person\r\ntoken=86abe8fe-2237-4f87-81af-0a4e522b4140"; | ||
var renderer = CreateRenderer(); | ||
renderer.ItemSeparator = "${newline}"; | ||
|
||
// Act | ||
string result = renderer.Render(new LogEventInfo()); | ||
|
||
// Assert | ||
Assert.Equal(expectedResult, result); | ||
} | ||
|
||
[Fact] | ||
public void ExcludeShouldTakePrecedenceOverInclude() | ||
{ | ||
// Arrange | ||
var expectedResult = "name=Test Person"; | ||
var renderer = CreateRenderer(); | ||
renderer.Include.Add("id"); | ||
renderer.Include.Add("name"); | ||
renderer.Exclude.Add("id"); | ||
|
||
// Act | ||
string result = renderer.Render(new LogEventInfo()); | ||
|
||
// Assert | ||
Assert.Equal(expectedResult, result); | ||
} | ||
|
||
private AspNetRequestFormLayoutRenderer CreateRenderer(bool hasFormValues = true) | ||
{ | ||
#if ASP_NET_CORE | ||
var httpContext = this.HttpContext; | ||
httpContext.Request.ContentType = "application/x-www-form-urlencoded"; | ||
#else | ||
var httpContext = Substitute.For<HttpContextBase>(); | ||
httpContext.Request.ContentType.Returns("application/x-www-form-urlencoded"); | ||
#endif | ||
|
||
if (hasFormValues) | ||
{ | ||
#if ASP_NET_CORE | ||
var formCollection = new FormCollection(new Dictionary<string, StringValues>{ | ||
{ "id","1" }, | ||
{ "name","Test Person" }, | ||
{ "token","86abe8fe-2237-4f87-81af-0a4e522b4140" } | ||
}); | ||
httpContext.Request.Form = formCollection; | ||
#else | ||
var formCollection = new NameValueCollection(){ | ||
{ "id","1" }, | ||
{ "name","Test Person" }, | ||
{ "token","86abe8fe-2237-4f87-81af-0a4e522b4140" } | ||
}; | ||
httpContext.Request.Form.Returns(formCollection); | ||
#endif | ||
} | ||
|
||
return new AspNetRequestFormLayoutRenderer | ||
{ | ||
HttpContextAccessor = new FakeHttpContextAccessor(httpContext) | ||
}; | ||
} | ||
} | ||
} |
94 changes: 94 additions & 0 deletions
94
NLog.Web.AspNetCore/LayoutRenderers/AspNetRequestFormLayoutRenderer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
using NLog.LayoutRenderers; | ||
using NLog.Web.Internal; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
|
||
namespace NLog.Web.LayoutRenderers | ||
{ | ||
/// <summary> | ||
/// ASP.NET Request Form Data | ||
/// </summary> | ||
/// <example> | ||
/// <para>Example usage of ${aspnet-request-form}:</para> | ||
/// <code lang="NLog Layout Renderer"> | ||
/// ${aspnet-request-form} - Produces - All Form Data from the Request with each key/value pair separated by a comma. | ||
/// ${aspnet-request-form:Include=id,name} - Produces - Only Form Data from the Request with keys "id" and "name". | ||
/// ${aspnet-request-form:Exclude=id,name} - Produces - All Form Data from the Request except the keys "id" and "name". | ||
/// ${aspnet-request-form:Include=id,name:Exclude=id} - Produces - Only Form Data from the Request with key "name" (<see cref="Exclude"/> takes precedence over <see cref="Include"/>). | ||
/// ${aspnet-request-form:ItemSeparator=${newline}} - Produces - All Form Data from the Request with each key/value pair separated by a new line. | ||
/// </code> | ||
/// </example> | ||
[LayoutRenderer("aspnet-request-form")] | ||
public class AspNetRequestFormLayoutRenderer : AspNetLayoutMultiValueRendererBase | ||
{ | ||
/// <summary> | ||
/// Gets or sets the form keys to include in the output. If omitted, all are included. <see cref="Exclude"/> takes precedence over <see cref="Include"/>. | ||
/// </summary> | ||
/// <docgen category='Rendering Options' order='10' /> | ||
#if ASP_NET_CORE | ||
public ISet<string> Include { get; set; } | ||
#else | ||
public HashSet<string> Include { get; set; } | ||
#endif | ||
|
||
/// <summary> | ||
/// Gets or sets the form keys to exclude from the output. If omitted, none are excluded. <see cref="Exclude"/> takes precedence over <see cref="Include"/>. | ||
/// </summary> | ||
/// <docgen category='Rendering Options' order='10' /> | ||
#if ASP_NET_CORE | ||
public ISet<string> Exclude { get; set; } | ||
#else | ||
public HashSet<string> Exclude { get; set; } | ||
#endif | ||
|
||
/// <summary> | ||
/// Constructor | ||
/// </summary> | ||
public AspNetRequestFormLayoutRenderer() | ||
{ | ||
Include = new HashSet<string>(StringComparer.OrdinalIgnoreCase); | ||
Exclude = new HashSet<string>(StringComparer.OrdinalIgnoreCase); | ||
} | ||
|
||
/// <summary> | ||
/// Renders the Form Collection from the HttpRequest and appends it to the specified <see cref="StringBuilder" />. | ||
/// </summary> | ||
/// <param name="builder"></param> | ||
/// <param name="logEvent"></param> | ||
protected override void DoAppend(StringBuilder builder, LogEventInfo logEvent) | ||
{ | ||
if (HttpContextAccessor?.HttpContext?.TryGetRequest() == null) | ||
{ | ||
return; | ||
} | ||
|
||
var formDataToInclude = GetPairsToInclude(); | ||
|
||
if (formDataToInclude.Any()) | ||
{ | ||
SerializePairs(formDataToInclude, builder, logEvent); | ||
} | ||
} | ||
|
||
private IEnumerable<KeyValuePair<string, string>> GetPairsToInclude() | ||
{ | ||
var httpRequest = HttpContextAccessor?.HttpContext?.TryGetRequest(); | ||
var pairs = new List<KeyValuePair<string, string>>(); | ||
|
||
if (httpRequest.Form != null) | ||
{ | ||
foreach (string key in httpRequest.Form.Keys) | ||
{ | ||
if ((!Include.Any() || Include.Contains(key)) && !Exclude.Contains(key)) | ||
{ | ||
pairs.Add(new KeyValuePair<string, string>(key, httpRequest.Form[key])); | ||
} | ||
} | ||
} | ||
|
||
return pairs; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters