diff --git a/examples/ASP.NET Core 3/ASP.NET Core 3 - VS2019/NLog.config b/examples/ASP.NET Core 3/ASP.NET Core 3 - VS2019/NLog.config index 6ee74312..0a62c3a0 100644 --- a/examples/ASP.NET Core 3/ASP.NET Core 3 - VS2019/NLog.config +++ b/examples/ASP.NET Core 3/ASP.NET Core 3 - VS2019/NLog.config @@ -22,7 +22,7 @@ layout="${longdate}|${event-properties:item=EventId_Id:whenEmpty=0}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}" /> - + diff --git a/examples/ASP.NET Core 5/ASP.NET Core 5 NLog Example/nlog.config b/examples/ASP.NET Core 5/ASP.NET Core 5 NLog Example/nlog.config index 26d58d4c..0b7abe44 100644 --- a/examples/ASP.NET Core 5/ASP.NET Core 5 NLog Example/nlog.config +++ b/examples/ASP.NET Core 5/ASP.NET Core 5 NLog Example/nlog.config @@ -22,7 +22,7 @@ layout="${longdate}|${event-properties:item=EventId_Id:whenEmpty=0}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}|${callsite}| body: ${aspnet-request-posted-body}" /> - + diff --git a/src/NLog.Web.AspNetCore/Config/SetupExtensionsBuilderExtensions.cs b/src/NLog.Web.AspNetCore/Config/SetupExtensionsBuilderExtensions.cs index f8a95c75..b4f58637 100644 --- a/src/NLog.Web.AspNetCore/Config/SetupExtensionsBuilderExtensions.cs +++ b/src/NLog.Web.AspNetCore/Config/SetupExtensionsBuilderExtensions.cs @@ -2,6 +2,8 @@ using System.Reflection; using NLog.Config; using NLog.Web.DependencyInjection; +using NLog.Web.LayoutRenderers; +using HttpContextBase = Microsoft.AspNetCore.Http.HttpContext; namespace NLog.Web { @@ -25,5 +27,18 @@ public static ISetupExtensionsBuilder RegisterNLogWeb(this ISetupExtensionsBuild return setupBuilder.RegisterAssembly(typeof(NLogAspNetCoreOptions).GetTypeInfo().Assembly); } + + + /// + /// Register a custom layout renderer using custom delegate-method + /// + /// Fluent style + /// Name of the layout renderer - without ${}. + /// Delegate method that returns layout renderer output. + public static ISetupExtensionsBuilder RegisterAspNetLayoutRenderer(this ISetupExtensionsBuilder setupBuilder, string name, Func layoutMethod) + { + AspNetLayoutRendererBase.Register(name, layoutMethod); + return setupBuilder; + } } } diff --git a/src/NLog.Web/Config/SetupBuilderExtensions.cs b/src/NLog.Web/Config/SetupBuilderExtensions.cs new file mode 100644 index 00000000..4234b803 --- /dev/null +++ b/src/NLog.Web/Config/SetupBuilderExtensions.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NLog.Config; + +namespace NLog.Web +{ + /// + /// Extension methods to setup LogFactory options + /// + public static class SetupBuilderExtensions + { + /// + /// Register the NLog.Web LayoutRenderers before loading NLog config + /// + public static ISetupBuilder RegisterNLogWeb(this ISetupBuilder setupBuilder) + { + setupBuilder.SetupExtensions(e => e.RegisterNLogWeb()); + return setupBuilder; + } + } +} diff --git a/src/NLog.Web/Config/SetupExtensionsBuilderExtensions.cs b/src/NLog.Web/Config/SetupExtensionsBuilderExtensions.cs new file mode 100644 index 00000000..8a6ff3f2 --- /dev/null +++ b/src/NLog.Web/Config/SetupExtensionsBuilderExtensions.cs @@ -0,0 +1,33 @@ +using System; +using System.Web; +using NLog.Config; +using NLog.Web.LayoutRenderers; + +namespace NLog.Web +{ + /// + /// Extension methods to setup NLog extensions, so they are known when loading NLog LoggingConfiguration + /// + public static class SetupExtensionsBuilderExtensions + { + /// + /// Register the NLog.Web LayoutRenderers + /// + public static ISetupExtensionsBuilder RegisterNLogWeb(this ISetupExtensionsBuilder setupBuilder) + { + return setupBuilder.RegisterAssembly(typeof(SetupExtensionsBuilderExtensions).Assembly); + } + + /// + /// Register a custom layout renderer using custom delegate-method + /// + /// Fluent style + /// Name of the layout renderer - without ${}. + /// Delegate method that returns layout renderer output. + public static ISetupExtensionsBuilder RegisterAspNetLayoutRenderer(this ISetupExtensionsBuilder setupBuilder, string name, Func layoutMethod) + { + AspNetLayoutRendererBase.Register(name, layoutMethod); + return setupBuilder; + } + } +} diff --git a/tests/NLog.Web.Tests/AspNetTests.cs b/tests/NLog.Web.Tests/AspNetTests.cs new file mode 100644 index 00000000..3298fc0c --- /dev/null +++ b/tests/NLog.Web.Tests/AspNetTests.cs @@ -0,0 +1,29 @@ +using System; +using NLog.Web.Targets.Wrappers; +using Xunit; + +namespace NLog.Web.Tests +{ + public sealed class AspNetTests + { + [Fact] + public void RegisterNLogWebTest() + { + // Act + var logFactory = new NLog.LogFactory().Setup().RegisterNLogWeb().LoadConfigurationFromXml( + @" + + + + + + + + + ").LogFactory; + + // Assert + Assert.NotNull(logFactory?.Configuration?.FindTargetByName("hello")); + } + } +} diff --git a/tests/Shared/RegisterCustomLayoutRenderer.cs b/tests/Shared/RegisterCustomLayoutRenderer.cs index ab993798..a68639c3 100644 --- a/tests/Shared/RegisterCustomLayoutRenderer.cs +++ b/tests/Shared/RegisterCustomLayoutRenderer.cs @@ -26,19 +26,28 @@ public void RegisterLayoutRendererTest() #endif // Act - AspNetLayoutRendererBase.Register("test-web", + var logFactory = new LogFactory().Setup().RegisterNLogWeb().SetupExtensions(ext => + ext.RegisterAspNetLayoutRenderer("test-web", (logEventInfo, httpContext, loggingConfiguration) => #if ASP_NET_CORE - httpContext.Connection.LocalPort); + httpContext.Connection.LocalPort) #else - httpContext.Request.RawUrl); + httpContext.Request.RawUrl) #endif - SimpleLayout l = "${test-web}"; - (l.Renderers.FirstOrDefault() as NLogWebFuncLayoutRenderer).HttpContextAccessor = httpContextMock; - var result = l.Render(LogEventInfo.CreateNullEvent()); + ).LoadConfiguration(builder => + { + builder.ForLogger().WriteTo(new NLog.Targets.MemoryTarget("hello") { Layout = "${test-web}" }); + }).LogFactory; + + var target = logFactory.Configuration.FindTargetByName("hello"); + var layoutRenderer = (target.Layout as NLog.Layouts.SimpleLayout).Renderers.FirstOrDefault() as NLogWebFuncLayoutRenderer; + layoutRenderer.HttpContextAccessor = httpContextMock; + + logFactory.GetCurrentClassLogger().Info("Hello World"); // Assert - Assert.Equal("123", result); + Assert.Single(target.Logs); + Assert.Equal("123", target.Logs[0]); } } }