What I'm trying to do is transform one of appSettings which is in external file:
Here is external.config
<?xml version="1.0"?>
<appSettings>
<add key="SomeKey" value="some value" />
</appSettings>
Web.config
<?xml version="1.0"?>
<configuration>
<appSettings file="..\..\external.config">
<add key="SomeKey1" value="some value 1" />
</appSettings>
</configuration>
Web.Debug.config
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<appSettings>
<add key="SomeKey" value="some changed value"xdt:Transform="SetAttributes" xdt:Locator="Match(key)"/>
</appSettings>
</configuration>
After build in proper configuration which in my example is Debug there's only this:
<?xml version="1.0"?>
<configuration>
<appSettings file="..\..\external.config">
<add key="SomeKey1" value="some value 1" />
</appSettings>
</configuration>
but it should be:
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<appSettings>
<add key="SomeKey1" value="some value 1" />
<add key="SomeKey" value="some changed value"/>
</appSettings>
</configuration>
I tryed to make shared appSettings by 2 or more different project 1-st is WCF Service second ASP.NET MVC 4 Application
Edited:
I've tryed to move this file attribute to Web.Debug.config but it's as well doesn't work.
The question is:
How can i accomplish such thing?Is it even possible?
Interesting. I have the same issue like yours. So now here is a workaround for your reference.
Please open project file - XXX.csproj
for example, ISWB.Test.Unit.csproj
add below section like this
<!-- Rock Add here, 2015.03.19 enable the external config transformation -->
<Target Name="BeforeCompile" Condition="Exists('ISWB.$(Configuration).config')">
<!--Generate transformed app config in the intermediate directory-->
<TransformXml Source="ISWB.config" Destination="$(IntermediateOutputPath)ISWB.config" Transform="ISWB.$(Configuration).config" />
<!--Force build process to use the transformed configuration file from now on.-->
<ItemGroup>
<AppConfigWithTargetPath Remove="ISWB.config" />
<AppConfigWithTargetPath Include="$(IntermediateOutputPath)ISWB.config">
<TargetPath>ISWB.config</TargetPath>
</AppConfigWithTargetPath>
</ItemGroup>
</Target>
<Target Name="AfterCompile" Condition="Exists('app.$(Configuration).config')">
<!--Generate transformed app config in the intermediate directory-->
<TransformXml Source="app.config" Destination="$(IntermediateOutputPath)$(TargetFileName).config" Transform="app.$(Configuration).config" />
<!--Force build process to use the transformed configuration file from now on.-->
<ItemGroup>
<AppConfigWithTargetPath Remove="app.config" />
<AppConfigWithTargetPath Include="$(IntermediateOutputPath)$(TargetFileName).config">
<TargetPath>$(TargetFileName).config</TargetPath>
</AppConfigWithTargetPath>
</ItemGroup>
</Target>
Please notice the added section, you have to add it into cs project file in a TEXT editor manually.
Please replace ISWB with yours. And then save it.
it should work well.
Enjoy it!
Related
I have Nlog configuration in the web config file and I would like to change the file path in the CD pipeline in order to put some dynamic path based on the environment.
Right now the web.config file variable substitution (XML Variable Substitution option) does not support it.
What are the other ways this can be done? I really don't have a choice to go the Web.Config transformation approach.
Any guidance on this will really help.
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
throwExceptions="false"
internalLogLevel="Error" internalLogFile="c:\Logs\nlog-internal.log">
<targets name="nlogconfig" async="true">
<target xsi:type="File" name="name"
fileName="Path/${shortdate}.log"
archiveFileName="Path/${shortdate}.{###}.log"
layout="${longdate} ${uppercase:${level}} ${callsite:className=true:includeSourcePath=true:methodName=true:skipFrames=1:cleanNamesOfAnonymousDelegates=true} ${newline} ${message} ${newline} ${exception:innerFormat=ToString:maxInnerExceptionLevel=2:innerExceptionSeparator=newline:separator=newline:format=ToString,StackTrace}${newline}"
archiveAboveSize="8388608"
archiveNumbering="Rolling"
archiveEvery="Day"
concurrentWrites="true"
maxArchiveFiles="100" />
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="name" />
</rules>
</nlog>
What are the other ways this can be done?
You could use the Replace Token task from Replace Tokens Extension.
Here are my steps, you could refer to them:
Nlog configuration:
<targets>
<target name="logfile" xsi:type="File" fileName="#{variable}#/#{shortdate}#.log />
<target name="logconsole" xsi:type="Console" />
</targets>
Replace Token task sample:
- task: replacetokens#3
inputs:
rootDirectory: 'Folder Path'
targetFiles: '**/*.config'
encoding: 'auto'
writeBOM: true
actionOnMissing: 'warn'
keepToken: false
tokenPrefix: '#{'
tokenSuffix: '}#'
useLegacyPattern: false
enableTelemetry: true
Variable:
Then the variables in Nlog configuration will be replaced.
Alternative solution is to deploy an environment-specific override-file next to the default NLog.config.
Example of environment-specific NLog.override.config:
<nlog>
<variable name="LogDirectory" value="D:/Path" />
</nlog>
Example of NLog.config:
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<variable name="LogDirectory" value="${basedir}" /> <!-- Default Value -->
<include file="NLog.override.config" ignoreErrors="true" /> <!-- Override Value -->
<targets async="true">
<target xsi:type="File" name="name" fileName="${LogDirectory}/${shortdate}.log" />
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="name" />
</rules>
</nlog>
The deployment-package could include multiple nlog.override.config-files. One for each environment and just deploy the right one based on chosen environment.
See also: https://github.com/nlog/nlog/wiki/Configuration-file#include-files
I'm trying to set up a token replacement for my config files. I have the source filename set to:
$(System.DefaultWorkingDirectory)/TFS Web Build 1.0/Corporate Art\app.RM.config
(Here, the RM file is the tokenized config file using token)
The destination filename is set to the true name of the config file:
Company.Client.Corporate.exe.config
I have the json file on the build server at:
\0111-03-0555-01\c$\BuildFiles\Transforms.json
The transforms.json file has the following data in it:
[
{
"CompanyTestDomain": {"QA4"},
"Environment": {"QA4.com"},
"CheckForContext": {"true"},
"ServiceTierAppHost": {"0111-06-0555-00-01.Company.com"},
"ServiceTierCsHost": {"0111-03-0444-00.Company.com"},
"ReportServer": {"0777-02-0111-00-01.Company.com"},
"ReportID": {"systemID"},
"ReportDomain": {"Corp"},
"ReportPWord": {"Password"}
}
]
The powershell is executed C:\Users\Public\Downloads\agent\tasks\Tokenizer\2.0.2\tokenize.ps1
The next line is grey as opposed to black which all the other information is:
##[debug]Performing the operation "Copy File" on target "Item:
C:\Agent_work\85c7a0d97\TFS Web Build 1.0\CorporateArt\app.RM.config
Destination: C:\Users\Public\Downloads\agent\tasks\Tokenizer\2.0.2\Isagenix.Clients.CorporateBackOffice.exe.config.tmp".
after which, I start getting messages that it's Updating token 'CompanyTestDomain'
No value found for token 'CompanyTestDomain'
So, can someone help me figure out what i'm doing wrong?
The content of configuration file should be like this (Contains a section ConfigChanges)
For example:
Sources file content:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="TestKey1" value="__Token1__" />
<add key="TestKey2" value="__Token2__" />
<add key="TestKey3" value="__Token3__" />
<add key="TestKey4" value="__Token4__" />
</appSettings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
</startup>
</configuration>
Configuration file content:
{
"Default Environment": {
"CustomVariables": {
"Token2": "value_from_custom2",
"Token3": "value_from_custom3"
},
"ConfigChanges": [
{
"KeyName": "/configuration/appSettings/add[#key='TestKey1']",
"Attribute": "value",
"Value": "value_from_xpath"
}
]
}
}
Variable in release definition: Token4 t4
Result:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="TestKey1" value="value_from_xpath" />
<add key="TestKey2" value="value_from_custom2" />
<add key="TestKey3" value="value_from_custom3" />
<add key="TestKey4" value="t4" />
</appSettings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
</startup>
</configuration>
More information, you can check these articles (1, 2).
After switching the logging library behind Common.Logging 2.1.1 from log4net to NLog 2.0 my ASP.NET MVC 2 application kept logging correctly, but it started calling the HttpApplication.Session_Start method for each request.
I'm trying to use NLog's File target with the following configuration files:
web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="common">
<section
name="logging"
type="Common.Logging.ConfigurationSectionHandler, Common.Logging" />
</sectionGroup>
.
.
.
<configSections>
.
.
.
<common>
<logging>
<factoryAdapter type="Common.Logging.NLog.NLogLoggerFactoryAdapter, Common.Logging.NLog20">
<arg key="configType" value="FILE" />
<arg key="configFile" value="~/NLog.config" />
</factoryAdapter>
</logging>
</common>
</configuration>
NLog.config
<?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">
<!--
See http://nlog-project.org/wiki/Configuration_file
for information on customizing logging rules and outputs.
-->
<targets async="true">
<target
name="f"
xsi:type="File"
fileName="${basedir}/bin/statistics/logs/${shortdate}.log"
layout="${longdate} ${uppercase:${level}} ${callsite} ${message}"/>
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="f" />
</rules>
</nlog>
I have already tried the following:
Debugging the application. The ASP.NET_SessionId cookie is being sent to the server and the Session.SessionID property is not changing between requests.
Switching back to Common.Logging - log4net to verify that the problem is related to Common.Logging - NLog. It works.
Omitting the async="true" attribute in the targets node of the configuration file of NLog to disable the AsyncWrapper of NLog. It doesn't work.
Using other NLog targets, tried Debugger and Database. It works.
I need to hold to the File target and I'd like to use NLog.
I'm using the Meleze.Web library for my web application and I want to add the compression only on release builds.
I tried to do a web.config transformation but in the Web.Release.config file, when I try to do
<configuration>
<system.web.webPages.razor>
<host xdt:Transform="Replace" factoryType="Meleze.Web.Razor.MinifyHtmlWebRazorHostFactory, Meleze.Web, Version=1.4.0.3, Culture=neutral, PublicKeyToken=0a868b5321967eda" />
</system.web.webPages.razor>
</configuration>
gives me an error saying that the :Transform is not declared. Any help would be appreciated. Please note, this is the Web.Config in the Views folder.
You can use the following Web.Release.config file for transforming your Web.config file.
<?xml version="1.0" encoding="utf-8"?>
<!-- For more information on using web.config transformation visit http://go.microsoft.com/fwlink/?LinkId=125889 -->
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<!--
In the example below, the "SetAttributes" transform will change the value of
"connectionString" to use "ReleaseSQLServer" only when the "Match" locator
finds an attribute "name" that has a value of "MyDB".
<connectionStrings>
<add name="MyDB"
connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True"
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
</connectionStrings>
-->
<system.web.webPages.razor>
<host factoryType="Meleze.Web.Razor.MinifyHtmlWebRazorHostFactory, Meleze.Web, Version=1.4.0.6, Culture=neutral, PublicKeyToken=0a868b5321967eda" xdt:Transform="Replace" />
</system.web.webPages.razor>
<system.web>
<!--
In the example below, the "Replace" transform will replace the entire
<customErrors> section of your web.config file.
Note that because there is only one customErrors section under the
<system.web> node, there is no need to use the "xdt:Locator" attribute.
<customErrors defaultRedirect="GenericError.htm"
mode="RemoteOnly" xdt:Transform="Replace">
<error statusCode="500" redirect="InternalError.htm"/>
</customErrors>
-->
</system.web>
</configuration>
For me, its working perfectly. Steps that I followed are here:
Install Meleze.Web via Package Manager Console PM> Install-Package Meleze.Web
Open View/Web.config and replace the <host...../> line inside <system.web.webPages.razor> with <host factoryType="Meleze.Web.Razor.MinifyHtmlWebRazorHostFactory, Meleze.Web, Version=1.4.0.3, Culture=neutral, PublicKeyToken=0a868b5321967eda" />
That's all I did. Btw, I am using MVC 4.
i'm trying to use the Web.config transformations in my ASP.NET MVC 2 project running on .NET 4. However, I am having a problem:
// Root Web.config
<add name="MyDB" connectionString="default...default" />
// Root Web.Debug.config
<add name="MyDB" connectionString="debug...debug" xdt:Transform="SetAttributes" xdt:Locator="Match(name)" />
// Root Web.Release.config
<add name="MyDB" connectionString="release... release" xdt:Transform="SetAttributes" xdt:Locator="Match(name)" />
I keep getting this error:
Warning No element in the source document matches '/configuration/add[#name='MyDB']' C:\filePath\Web.Release.config
I narrowed this down to the Web.Config file inside the Views folder. If I give it a connectionString, such as the one in the root Web.config file, than all is well, but that means I have to maintain two Web.config files. Is there any solution to this? Am I doing something wrong?
Not sure why web.config in the views folder is being implicated but from the error you're getting it sounds like you've got a mismatch between the element in web.config and the transform config files.
In web.config, assuming <add /> is a child of <connectionStrings /> you'd do:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
...
<connectionStrings>
<add name="SomeName" providerName="System.Data.SqlClient" connectionString="SomeConnectionString" />
</connectionStrings>
...
</configuration>
and in web.debug.config
<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
...
<connectionStrings>
<add xdt:Locator="Match(name)" xdt:Transform="SetAttributes(connectionString)" name="SomeName" connectionString="SomeOtherConnectionString" />
</connectionStrings>
...
</configuration>
As I already said:
Don't forget to manually copy all the other attributes of "configuration" from the original "web.config", as it seems that VS2012 doesn't do it automatically, so there will be no match...