Replace config value in teamcity build step - msbuild

I have a build step in teamcity which allows me to replace web.config values with web.release.config values. I would like to add one more step - pass some parameter from teamcity to web.config. In my case it will be release version, which is part of connection string. The best idea I have is just to have some powershell script which will replace text in some file (web.config). Are there any better options?
Example web config
<add key="Version" value="Replace me, please from teamcity"/>
<add key="some key" value="example 2. version as part of some value #VERSION"/>

You could use File Content Replacer.

Instead of making the creation of the web.config in release dependent of TeamCity, you can use the web.config transformation syntax
ie: To create a specific connection string:
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<connectionStrings>
<add name="MyDB"
connectionString="value for the deployed Web.config file"
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
</connectionStrings>
</configuration>

Related

How to use --connectionStringConfigPath for FluentMigrator MSBuild runner

How do you use the --connectionStringConfigPath for FluentMigrator when using the MSBuild runner?
The documentation says
Connection (required)
The connection string to the server and database you want to execute
your migrations against. This can be a full connection string or the
name of the connection string stored in a config file.
When specifying a named connection string, FluentMigrator searchs for
it in this order:
The specified config file via --connectionStringConfigPath parameter
Target assembly’s config file
Machine.config config file
I was not able to get this to work and couldn't find any examples of usage with FluentMigrator's MSBuild runner.
The connectionStringConfigPath parameter is used in conjuction with the Connection parameter. The Connection parameter specifies the name of the connection string.
This is an example of the migrate task:
<Migrate Database="sqlserver2012"
Connection="SRVConnectionString"
ConnectionStringConfigPath="db.config"
Target="./Migrations/bin/Debug/Migrations.dll">
</Migrate>
And this is the db.config file:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<clear />
<add name="SRVConnectionString" connectionString="server=SQLEXPRESS;uid=test;pwd=test;database=Test"/>
</connectionStrings>
</configuration>
I will update the wiki with this example.

Specify Machine Name in Web.Config Transform

I am using Web.config transforms to successfully create debug and release versions of the my web.config - this is working correctly.
I am interested to know whether there is a 'machine name' property to specify the current machine name which I can use in a debug URL, rather than hard-coding a specific machine name (using localhost isn't an option in the case), e.g.
<add name="XrmService" connectionString="http://$(ComputerName):5555/Service.svc" />
Are there any properties available using Web.config transforms? Similar to MSBuild's $(ComputerName) property?
I faced a similar issue, what I ended up doing is :
1) Added the following build target to the project file. (Which is an MSBuild script effectively)
<Target Name="AfterBuild">
<TransformXml Source="Web.config" Condition="Exists('Web.$(Computername).config') " Transform="Web.$(Computername).config" Destination="Web.config" />
</Target>
2) Added a Web.MyMachineName.config config transform file to the project. In your case it should look like this:
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<connectionStrings>
<add name="XrmService"
connectionString="http://MyMachineName:5555/Service.svc"
xdt:Transform="SetAttributes"
xdt:Locator="Match(name)"/>
</connectionStrings>
</configuration>
This has the benefit of running different transformations based on the machine name, without creating a separate build configuration. You can configure it to be debug only by specifying Condition="'$(Configuration)' == 'Debug'".
There is an Environment Variable that you can use. It is $(COMPUTERNAME).
Open a command window, type "set" (without the double quotes) and press Enter. You will see this Environment Variable somewhere at the top of the screen.

Why is msbuild duplicating entries in web.config transformations?

I am using web.config transformations to insert entries into the web.config for certain build configurations.
E.g. my Web.Test.config has this entry:
<elmah>
<errorMail from="me#me.com" to="me#me.com" async="false" smtpPort="25" smtpServer="mail" subject="test.senegal.co.uk Exception" xdt:Transform="Insert" />
</elmah>
This works absolutely fine building from visual studio.
However when creating a deployment package using msbuild, the entry is duplicated in the web.config. This obviously causes an exception.
Any ideas?
UPDATE
My "master" config is Web.Master.config not Web.config. The web.config file gets overwritten on build in visual studio. I think it must have something to do with this.
What I think is happening is msbuild is transforming web.config rather than using the Web.Master.config.
The question is how to tell it to use the right master.
I added /p:TransformWebConfigEnabled=false to the msbuild parameters, as my web.config was already being transformed in a BeforeBuild target like so:
<Target Name="BeforeBuild">
<TransformXml Source="$(MSBuildProjectDirectory)\Web.Master.config" Transform="$(MSBuildProjectDirectory)\Web.$(Configuration).config" Destination="$(MSBuildProjectDirectory)\Web.config" />
</Target>
In my case duplication was caused by xdt:Transform="Insert". If remove it from Web..config and leave the rest it will work properly, e.g.:
<!-- doesn't work -->
<add name="EventLog" type="System.Diagnostics.EventLogTraceListener" initializeData="My"
xdt:Transform="Insert" />
vs.
<!-- works -->
<add name="EventLog" type="System.Diagnostics.EventLogTraceListener" initializeData="My"
/>

Migrations (Entity Framework 4.3) - script doesn't get executed

The scripts are generated correctly, i use multiple layers so the following commands are run into the Package Manager Console
Eg. When i added Email column to the table : "Owner"
Add-Migration AddEmailToOwner -StartupProjectName "FacturatieMVCv2.Data" -Verbose
--> Result:
Using NuGet project 'FacturatieMVCv2.Data'.
Target database is: 'FacturatieMVCv2.Data.Website.MyResellerContext' (DataSource: V-File \SQLEXPRESS, Provider: System.Data.SqlClient, Origin: Convention).
Next command i use is:
Update-Database -StartupProjectName "FacturatieMVCv2.Data" -Verbose
--> Result:
Using NuGet project 'FacturatieMVCv2.Data'.
Target database is: 'FacturatieMVCv2.Data.Website.MyResellerContext' (DataSource: V-FILE\SQLEXPRESS, Provider: System.Data.SqlClient, Origin: Convention).
Applying explicit migrations: [201203080906140_AddDamnToOwner].
Applying explicit migration: 201203080906140_AddDamnToOwner.
ALTER TABLE [Owners] ADD [Damn] [nvarchar](max)
[Inserting migration history record]
My connectionstring in the App.Config is :
<parameter value="Server=V-FILE\SQLEXPRESS;Persist Security Info=True;Initial Catalog=ProductionReseller;uid=sa;password=n*****3;" />
Although i specified the Initial catalog, it is targetting the wrong catalog. It's created / updated the database table named: FacturatieMVCv2.Data.Website.MyResellerContext .
Following is my app.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=4.3.1.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</configSections>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework">
<parameters>
<!--<parameter value="Data Source=.\SQLEXPRESS; Integrated Security=True; MultipleActiveResultSets=True" />-->
<parameter value="Server=V-FILE02\SQLEXPRESS;Persist Security Info=True;Initial Catalog=ProductionReseller;uid=sa;password=12345678;" />
</parameters>
</defaultConnectionFactory>
</entityFramework>
</configuration>
In short, the Update-Database command, updated the wrong database.
Using the following command:
Update-Database -StartupProjectName "FacturatieMVCv2.Data" -Verbose -ConnectionString "Server=V-FILE\SQLEXPRESS;Persist Security Info=True;Initial Catalog=ProductionReseller;uid=mydbuser;password=mydbpass;" -ConnectionProviderName "System.Data.SqlClient"
Fixed my problem.
SqlConnectionFactory adds the Initial Catalog to the value you provide. If you want to use a specific connection string for a context, you should add an entry in the connectionStrings section instead. E.g.
<connectionStrings>
<add name="MyResellerContext" connectionString="Server=V-FILE\SQLEXPRESS;Persist Security Info=True;Initial Catalog=ProductionReseller;uid=sa;password=12345678;" providerName="System.Data.SqlClient" />
</connectionStrings>
We store config variables in build configs to switch between these and ran into this issue; the solution was to Clean then explicitly Build.
To expand on that:
Our Db class (the one that inherits DbContext) has a Constructor like:
public Db()
#if AltDb
: base("AltDb")
#else
: base("Db")
#endif
{
}
So if the AltDb build var is defined, it's going to use the ConnectionString named AltDb; otherwise it uses the one named Db. In our Project configs, we have one named AltDb and all it does is define the AltDb build variable.
So we have those 2 connection strings defined in Web.Config:
<connectionStrings>
<add name="Db" connectionString="Initial Catalog=MyProj;Data Source=.\SQLEXPRESS...
<add name="AltDb" connectionString="Initial Catalog=Staging;Data Source...
So, when we want to update the alternate db, we SHOULD be able to just switch build configs and run update-database. This has worked in every project for years, but today it just wouldn't.
When I ran a Clean, then made sure this build config was selected and the startup Project was selected, and explicitly Built, magically it was solved - even though EF appears to build everything every time you run update-database.
I have no explanation as to why this would occur, but that's the cause and solution for us.

NServiceBus persisting subscriptions in Pub/Sub sample

I want to figure out how I to set up the Pub/Sub sample from NServiceBus to work in the case of publisher malfunction.
When I start the samples and accidentaly close the Subscribers, if I restart everything works fine.
If however I kill the publisher and the subscriptions continue to work, if I restart the publisher, then it doesn't seem to know it has subscribers and doesn't post any messages.
I added the config entry
<MsmqSubscriptionStorageConfig Queue="subscriptions"/>
but it seems to not function... I miss something. I googled about MsmqSubscriptionStorageConfig and DbSubscriptionStorageConfig but i didn't find a solution.
Could someone point me in the right direction ?
I found that a couple additional steps are required in order to get this working with the Pub/Sub sample under .Net 4.0, using a SQLite subscription storage system.
Combining the previous suggestions with the new ones, here are the required changes, all of which apply to the MyPublisher project.
Add a reference to System.Data.SQLite. Be sure to choose the version that matches your desired architecture (x86/x64). These items can be found in the 'binaries' folder.
In the App.config file, add the following as a new configSection element:
<section name="DBSubscriptionStorageConfig"
type="NServiceBus.Config.DBSubscriptionStorageConfig, NServiceBus.Core" />
In the App.config file add, the following as a new configuration element:
<DBSubscriptionStorageConfig>
<NHibernateProperties>
<add Key="connection.provider"
Value="NHibernate.Connection.DriverConnectionProvider"/>
<add Key="connection.driver_class"
Value="NHibernate.Driver.SQLite20Driver"/>
<add Key="connection.connection_string"
Value="Data Source=.\Subscriptions.sqlite;Version=3;New=True;"/>
<add Key="dialect"
Value="NHibernate.Dialect.SQLiteDialect"/>
</NHibernateProperties>
</DBSubscriptionStorageConfig>
Add this chunk of XML to the configuration section of the NServiceBus.Host.exe.config file:
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0"/>
</startup>
You need to change the profile of the publisher to production.
See http://docs.particular.net/nservicebus/hosting/nservicebus-host/profiles
For debugging this way, go to the properties of the publisher project, into the Debug tab, and put in NServiceBus.Production in the Command line arguments of the Start Options section.