Config Transformation on NLog does not work

17,411

Solution 1

To solve this issue I had to:

1) Avoid the use of nlog.config

2) Create nlog section inside web.config and move the contents of nlog.config to web.config to be able the use the web.config transformation feature with one file. To further instructions please take a look at: NLog configuration instructions

3) Remove xmlns attributes from the nlog node. There seems to be a bug that messes everything during the web.config transformation. You can safely remove the following nodes:

xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

4) I couldn't find a way to transform just a single target under nlog/targets node. To change the connection string of my logger, I had to copy the whole xml node, using a xdt:Transform="Replace" on the parent node like the following:

<nlog
      throwExceptions="true"
      internalLogLevel="Trace"
      internalLogFile="..\..\..\Logs\nlog-app.log" 
      xdt:Transform="Replace">
<!--(copy and paste all nlog configuration here)-->
</nlog>

Solution 2

I've managed it without moving all configuration into web.config or app.config. (There is nothing, connected with nlog in web/app.config at all).

1) Using this article: applying msbuild config transformations to any config file I've created all transformations, which are necessary and added transformation task.

2)Then I've checked if there are any other tasks, which do similar things. In my case there was one, which had been created by SlowCheetah(VS extension to automatically add transformations). I've removed it - and everything became ok. (SlowCheetah can restore its settings on next build, so it is better to remove it or suppress its transformation task)

3) My transform files look like this one:

<?xml version="1.0"?>
<!-- For more information on using app.config transformation visit http://go.microsoft.com/fwlink/?LinkId=125889 -->
<nlog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform" xmlns="http://www.nlog-project.org/schemas/NLog.xsd">
  <targets>
    <target xsi:type="Database" name="DbLogging"
          connectionString=".\SQLEXPRESS;Initial Catalog=xxxxx;User ID=xxxx;Pwd=xxxx;" xdt:Transform="SetAttributes(connectionString)" xdt:Locator="Match(name)">
    </target>
  </targets>
  <rules>
    <logger name="*" minlevel="Debug" writeTo="DbLogging" />
    <logger name="Namespace.*" minlevel="Debug" writeTo="DbLogging" xdt:Transform="SetAttributes(writeTo)" xdt:Locator="Match(name)" />
  </rules>
</nlog>

Solution 3

It appears that I am quite late on this, but I have found that it is necessary for the NLog.config file to have the following:

<?xml version="1.0" encoding="utf-8"?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd">
...
...
</nlog>

And the NLogTransform.config file (or whatever name it may have) to have the following:

<?xml version="1.0"?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
...
...
</nlog>

Here is some sample code to test the NLog transformation:

var tmpConfigFile = new FileInfo("C:\\NLogs\\NLog.config");
var transformFile = new FileInfo("C:\\Transforms\\NLogTransform.config");

if (transformFile.Exists) {
    var xmlTransformableDocument = new XmlTransformableDocument();
    xmlTransformableDocument.Load(tmpConfigFile.FullName);
    var xmlTransformation = new XmlTransformation(transformFile.FullName);
    xmlTransformation.Apply(xmlTransformableDocument);
    xmlTransformableDocument.Save(tmpConfigFile.FullName);
}

Solution 4

I got this working by, in transformation config, include the xmlns:xsi namespace definied in web.config for the nlog section.

<nlog xmlns:xsi="...">
    <variable name="..." value="..." xdt:Transform="Replace" xdt:Locator="Match(name)" />
</nlog>

Solution 5

I ended up changing all of my publishing profiles (.pubxml files). I have added the following to my testing publishing profile as an example:

<Target Name="NLogTransform" AfterTargets="PipelineCopyAllFilesToOneFolderForMsdeploy">
<Message Text="NLog file transform according to NLog.WebDeploy - TEST.config" Importance="high" />
<TransformXml Source="NLog.config"
              Transform="NLog.WebDeploy - TEST.config"
              Destination="$(_PackageTempDir)\NLog.config" />
</Target>

Do notice though this only works for publishing profiles that make use of MsDeploy (aka web deploy). For publishing on a local folder use this target CopyAllFilesToSingleFolderForPackage.

Share:
17,411

Related videos on Youtube

Tamas Ionut
Author by

Tamas Ionut

Updated on August 22, 2020

Comments

  • Tamas Ionut
    Tamas Ionut over 3 years

    I have a web project (ASP.NET MVC 4 project) that has a number of configurations stored in Web.Config and in NLog.config files.

    I have several publish profiles PublishProfile1, PublishProfile2 etc. When using a publish profile to deploy my web project to a server, I want to change a number of configs from both config files after deploy (some App Settings in Web.config and some values in NLog.config).

    I have followed the steps from here and it works perfectly for changing the settings in Web.Config (e.g. the transformations from Web.PublishProfile1.Config are respected).

    This is my NLog.PublishProfile1.Config transformation file:

    <nlog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform" xmlns="http://www.nlog-project.org/schemas/NLog.xsd">
      <nlog  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <targets >
          <target xsi:type="File"
                  name="tracelog"
                  fileName="NEW_VALUE_HERE" layout="${longdate} [${threadname}::${threadid}] ${pad:padding=5:inner=${level:uppercase=true}} ${logger} - ${message}"
                  xdt:Transform="Replace"  xdt:Locator="Match(name)" />
        </targets>
      </nlog>
    </nlog>
    

    The problem is that I have the same transforms in NLog.PublishProfile1.config but these transformations are not applied after deploy as well.

    Does anyone has a clue on why this transformation does not work for NLog.config but works ok for Web.config on a publish profile?

    • pepo
      pepo about 10 years
      When you run it what happens? Does the transformation run and place the transformed Nlog.config in the output directory?
  • warbi
    warbi over 9 years
    This is the solution I'm using; it's good practice to create NLog config files for each configuration, but you can prevent build errors by adding: Condition="Exists('NLog.$(Configuration).config')" to your new TransformXml element in your .csproj. Bear in mind this might cause unwanted behaviour on subsequent builds because your base NLog.config file will be overwritten with the transform on each build. Haven't found a way around that yet.
  • prime_z
    prime_z over 9 years
    Sorry, but I don't understand a first part of your comment. Why do we need condition if we create transformations by ourselves. I have not found a way to prevent constant changing of main NLog.config files as well
  • warbi
    warbi over 9 years
    In case one forgets to add a config file for the current configuration. In which case, I suppose, you would probably want an error to be thrown. Good point!
  • flq
    flq almost 9 years
    You can easily work on a single target by using xdt:Locator="Match(name)"
  • Gerrie Pretorius
    Gerrie Pretorius over 7 years
    you save the day: Just by adding the xmlns="nlog-project.org/schemas/NLog.xsd" line, in the transform nlog.config file, suddenly made it to start working, while all other tutorials, showed people taking out that line
  • Ross Presser
    Ross Presser over 7 years
    Moving nlog into web.config is a suboptimal solution. The point of nlog.config is being able to tweak logging configuration on the fly without forcing an application reload, which is what changing web.config will unquestionably do.
  • Caius Jard
    Caius Jard almost 7 years
    Rather than removing the XMLNS nodes (which caused errors in my web config/caused the transform to fail) I found i had to ADD those nodes to my transform file.. I hope you don't mind, but I'll edit your answer and add some detail..
  • Davatar
    Davatar over 6 years
    That only works for me on build, but not on publish. Do you have any idea about how to solve it for publish?
  • prime_z
    prime_z over 6 years
    Unfortunately, I haven't tried it on publish, but if you provide more information about the problem we would be able to solve it
  • xforfun
    xforfun over 5 years
    I encountered some problems with nlog.config and AzureWebJob. The first mentioned here (johan.driessen.se/posts/…) is the solution to this!
  • Alexander Derck
    Alexander Derck over 5 years
    Maybe helpful for future readers: when you remove xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" (not needed when you don't use NLog.config but use web.config instead), you will get errors in your xml file. When you don't use the namespace, you can change the xsi:type attribute by just type and everything will work just fine.
  • bN_
    bN_ about 5 years
    This solution works great during build but not when publishing, unless you transform the source file which in my opinion is not a good idea. I was able to solve this with an additionnal "BeforePublish" build event that copy the file to PackageTmp before package creation.
  • RaSor
    RaSor over 4 years
    I didn't have to remove xmlns:xsi=, but only xmlns=. Thanks for your help @Mário
  • Rich
    Rich over 3 years
    Interesting that this seemed to work for me in Visual Studio 2015 even though Visual Studio underlines the tag and tells me it won't work.