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

HttpContextAccessor is null in AspNetLayoutRendererBase #327

Closed
jholovacs opened this issue Oct 30, 2018 · 7 comments
Closed

HttpContextAccessor is null in AspNetLayoutRendererBase #327

jholovacs opened this issue Oct 30, 2018 · 7 comments
Labels

Comments

@jholovacs
Copy link

jholovacs commented Oct 30, 2018

  • Bug

I've got NLog wired into DI like so:

		public static IApplicationBuilder StartLogging(this IApplicationBuilder app,
			IConfiguration config)
		{
			var loggerFactory = app.ApplicationServices.GetService<ILoggerFactory>();
			loggerFactory.AddNLog(new NLogAspNetCoreOptions
			{
				RegisterHttpContextAccessor = true,
				IgnoreEmptyEventId = true,
				IncludeScopes = true
			});
			LogManager.LoadConfiguration("nlog.config");
			LogManager.Configuration.Variables["appDbConnectionString"] =
				config["ConnectionStrings:ApplicationContext"];
			return app;
		}

		public static IServiceCollection ConfigureLogging(this IServiceCollection services,
			IConfiguration config)
		{
			services.AddLogging();
			return services;
		}

I've made my own test renderer (off of AspNetLayoutRendererBase) and registered it just to see why I could not get the user info to work.

The ClaimsPrincipal is properly filled out with the user claims. The ClaimsIdentity has the proper username. The protected override void DoAppend(StringBuilder builder, LogEventInfo logEvent) method in the layout renderer was never reached... so I dug a bit further back and found that the protected override void Append(StringBuilder builder, LogEventInfo logEvent) method was being hit. However, the HttpContextAccessor property was null, so it never got to the DoAppend method.

I see this method is populated with a ServiceLocator, but I don't know if maybe that can't figure out how to access the ServiceProvider in .NET Core 2.1, or do I need to configure something that I'm missing?

NLog version: 4.5.10

NLog.Web/NLog.Web.AspNetCore version: 4.7.0

NLog.Extensions.Logging version: 1.3.0

Platform: .NET Core 2.1

Current NLog config (xml or C#, if relevant)

<?xml version="1.0" encoding="utf-8"?>

<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xsi:schemaLocation="NLog NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      autoReload="true"
      throwExceptions="true"
      internalLogIncludeTimestamp="true"
      internalLogFile="nlog-internal.log"
      internalLogLevel="Error">
  <extensions>
    <add assembly="NLog.Web.AspNetCore"/>
  </extensions>
  <targets>
    <target xsi:type="File"
            name="fileSystem"
            fileName="cfcommunity.log"
            layout="${date}|${level:uppercase=true}|${message} ${exception}|${logger}|${all-event-properties}"
            cleanupFileName="true" enableFileDelete="true"
            maxArchiveFiles="5" archiveAboveSize="1000000" archiveOldFileOnStartup="true" />
    <target xsi:type="ColoredConsole"
            name="console"
            layout="${date}|${level:uppercase=true}|${message} ${exception}|${logger}|${all-event-properties}" />
    <target xsi:type="Database"
            name="database"
            commandType="Text"
            dbProvider="Npgsql.NpgsqlConnection, Npgsql"
            connectionString="${var:appDbConnectionString}"
            commandText="Layout">
      <commandText>
        insert into "logs" ("application", "user", "level", "message", "exception", "logger")
        values (@application, @user, @level, @message, @exception, @logger);
      </commandText>
      <parameter name="@application" layout="MyApp" />
      <parameter name="@user" layout="${aspnet-user-identity}" />
      <parameter name="@level" layout="${level}" />
      <parameter name="@message" layout="${message}" />
      <parameter name="@exception" layout="${exception:format=tostring}" />
      <parameter name="@logger" layout="${logger}" />
    </target>
  </targets>
  <rules>
    <logger name="MyApp.*" minlevel="Info" writeTo="database" final="true" />
    <logger name="*" minlevel="Error" writeTo="fileSystem,database" final="true"/>
    <logger name="*" minlevel="Warn" writeTo="database" final="true"/>
  </rules>
</nlog>

In case of a BUG:

  • What is the current result? User column stored to db is blank.
  • What is the expected result? User column displays the logged-in user.
  • Did you checked the Internal log? even when set to debug, it is not producing any results. CORRECTION When setting output to console with Debug level I do see the message "Missing serviceProvider, so no HttpContext".
  • Please post full exception details (message, stacktrace, inner exceptions)
  • Are there any workarounds? not that I can find
  • Is there a version in which it did work? not that I can find
  • Can you help us by writing an unit test? With a static ServiceLocator pattern, I don't think that I can. The IHttpContextAccessor is registered as a Singleton in the application already, and it still not able to find it.
@snakefoot
Copy link
Contributor

snakefoot commented Oct 30, 2018

If wanting to configure NLog in Startup.cs using AddNLog (ASP NET Core v1 style):

NLog/NLog#2859 (comment)

But the recommended way is UseNLog in Program.cs: https://github.com/NLog/NLog.Web/wiki/Getting-started-with-ASP.NET-Core-2#4-update-programcs

Please do not apply both approaches at the same time.

@jholovacs
Copy link
Author

Now that is a buried nugget of gold. That did indeed solve my issue. Thank you.

@snakefoot
Copy link
Contributor

@jholovacs Remember not to use both AddNLog (ver. 1) and UseNLog (ver. 2) at the same time.

@jholovacs
Copy link
Author

@snakefoot Thanks, but it's not clear how I would be able to use the connection string in my appsettings from Program.cs before DI is configured. Can you point me to where I'd find that info?

@snakefoot
Copy link
Contributor

snakefoot commented Oct 31, 2018 via email

@jholovacs
Copy link
Author

I don't see how that would work to load a connection string that's stored in an appsettings.json file. I need the IConfiguration object loaded before setting the value.

@snakefoot
Copy link
Contributor

snakefoot commented Oct 31, 2018 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants