Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added ${aspnet-request-form} #313

Merged
merged 9 commits into from
Sep 22, 2018
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)
};
}
}
}
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;
}
}
}
3 changes: 3 additions & 0 deletions NLog.Web.Tests/NLog.Web.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@
<Compile Include="..\NLog.Web.AspNetCore.Tests\LayoutRenderers\AspNetMvcActionRendererTests.cs" />
<Compile Include="..\NLog.Web.AspNetCore.Tests\LayoutRenderers\AspNetCookieLayoutRendererTests.cs" />
<Compile Include="..\NLog.Web.AspNetCore.Tests\LayoutRenderers\AspNetItemValueLayoutRendererTests.cs" />
<Compile Include="..\NLog.Web.AspNetCore.Tests\LayoutRenderers\AspNetRequestFormLayoutRendererTests.cs">
<Link>AspNetRequestFormLayoutRendererTests.cs</Link>
</Compile>
<Compile Include="..\NLog.Web.AspNetCore.Tests\LayoutRenderers\AspNetRequestValueLayoutRendererTests.cs" />
<Compile Include="..\NLog.Web.AspNetCore.Tests\LayoutRenderers\AspNetSessionIDLayoutRendererTests.cs" />
<Compile Include="..\NLog.Web.AspNetCore.Tests\LayoutRenderers\AspNetSessionValueLayoutRendererTests.cs" />
Expand Down
3 changes: 3 additions & 0 deletions NLog.Web/NLog.Web.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@
<Compile Include="..\NLog.Web.AspNetCore\LayoutRenderers\AspNetMvcControllerRenderer.cs" />
<Compile Include="..\NLog.Web.AspNetCore\LayoutRenderers\AspNetMvcActionRenderer.cs" />
<Compile Include="..\NLog.Web.AspNetCore\LayoutRenderers\AspNetMvcLayoutRendererBase.cs" />
<Compile Include="..\NLog.Web.AspNetCore\LayoutRenderers\AspNetRequestFormLayoutRenderer.cs">
<Link>AspNetRequestFormLayoutRenderer.cs</Link>
</Compile>
<Compile Include="..\NLog.Web.AspNetCore\LayoutRenderers\AspNetRequestValueLayoutRenderer.cs" />
<Compile Include="..\NLog.Web.AspNetCore\LayoutRenderers\AspNetRequestIpLayoutRenderer.cs" />
<Compile Include="..\NLog.Web.AspNetCore\LayoutRenderers\AspNetSessionIdLayoutRenderer.cs" />
Expand Down