I'm using Visual Studio 2008, developing a winforms app.
I have my database connection string stored in settings.settings.
My development and production environments require different database login credentials and right now I'm manually changing the connectionstring by hand before building for the 2 different environments.
Is there a better solution?
An eternal problem! :-)
Basically, right now, Microsoft doesn't really have a good answer for this.
What I would do is have both connection strings in my settings file, under two separate names, and then have a config setting in app.config which tells me which one to use:
MyDatabaseDEV = server=(local);database=mydatabase;-........
MyDatabasePROD = server=ProdServer;database=MyDatabase;........
and in app.config
<appSettings>
<add key="UseDatabase" value="MyDatabaseDEV" />
</appSettings>
This setting in app.config can be tweaked in your build process, e.g. by a "after build" batch file, or an MSBuild task or something, to be switched to "MyDAtabasePROD", when you do a production (release) build.
Microsoft promises us more and more flexible tools for .NET 4.0 / Visual Studio 2010, which should be out by the end of the year 2009. You should be able to create "config transformations" - check out these blog posts:
Web Deployment: Web.Config Transformation
ASP.NET 4.0 and Visual Studio 2010 Web Development Beta 1 Overview
Visual Studio 2010: Web.config transforms
Web.config Transformations with Visual Studio 2010
Marc
Where I work this is done by creating a folder called config that holds the various configurations.
source
config
MyProject
environment1
environment2
MyProject2
environment1
environment2
When the build script is run, it grabs the correct config based on which environment you're doing the build for...
you can make form asking the user to enter the connection parameters such as server name and database..., and store those parameters in Registry, files etc...
You should add an app.config file to your winform application. In this file store the connection string under the ConnectionStrings section.
In your code, when create a connection use that connection string using ConfigurationManager class to access config file.
So when you deploy your application, you have to chance the connection string once in config file and everything runs as expected!
You can defines your connections in settings, use dev connection in debug mode else production connection with #if directive.
//affect your prod connection here
#if DEBUG
//re affect your dev connection here;
#endif
A link to explain : http://msdn.microsoft.com/fr-fr/library/4y6tbswk.aspx
Right-click on the web site in the Solution Explorer and select Add Web Deployment Project.
Whenever this new WDP project is built, it will replace all the configuration elements you specify. You can also have different versions depending on Debug or Release builds. It works for almost all of the configuration options, including the connection string. There's lots of documentation on how to configure it correctly on the net, just search for "Web Deployment Project".
This is definitely the new "default" way to do this until MS decides to make it more formal in some future version of .Net/Visual Studio, if they ever do.
I've started using a setting called TestMode="dev|prod|uat".
The problem with compilation targets is that you can't change anything after build.
With this approach you can include all the connection strings and settings you need for all the environments you want. In your code configuration provider you can switch based on this setting.
With this approach all you have to do is change the flag once deployed or use deployment software like Octopus to change it for you.
I have given up with merging .config files which is difficult and error prone.
Related
TFS 2015, vNext build process (not xaml)
I'm trying to automate the deployment process for an MVC web app. The servers that it would be deploying to have different SQL connection strings. So my current deployment is to copy the web.config file to web.config.save manually, deploy the new version using WebDeploy then go to the old web.config.save file and copy over the connection string. I'm to the size now where this is not going to be sustainable much longer. So I need to automate this process further. I've got TFS automatically building and deploying to my test server (which also has a different connection string so it's a great test). In the "publish" properties, I tried deselecting the "Use This connection string at runtime (update destination web.config)" checkbox in the publish-settings-database section then checked in the project again to TFS. But when deployed, the web.config took the default setting. I don't want to remove this setting because I want a default connection string there for new installs.
I could write an xml transfer program to save off the current connection string then overwrite when complete again. But I figured there must be a way to do this with the current tool set and why try reinventing the wheel?
I started down the path to use transforms. So I created a web.config.release in VS2015 then added in this into the web.config.release file:
<connectionStrings>
<add xdt:Transform="InsertIfMissing" xdt:Locator="Match(name)" name="AppEntities" connectionString="metadata=res://*/Models.DBName.csdl|res://*/Models.DBName.ssdl|res://*/Models.DBName.msl;provider=System.Data.SqlClient;provider connection string="data source=.\SQLExpress;initial catalog=DBName;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
So, does anyone know how I can make the SQL connection string update only if it doesn't exist in the current web.config for deployment?
I got this experience with TFS 2015 vNext build,
in the 2Q of 2016 we assigned a Dev Ops person, who was really good with PowerShell, and he took ownership of the build and deploy process. Some of the things he came up with was a post build script.
Now to answer your question: For us, the Post-Build script would do the deployment part, and as part of the deployment you would update the connection string in the web.config. Now this would require someone in your team to become really good with PowerShell.
Now what I would do is write a special word in the original file like "{ConStringHere}", and the replace it with the Powershell script, that way you'll only replace it once.
See this how to verify if a file contains a word and replace it using PowerShell:
Powershell, using contains to check if files contain a certain word
I'll highlight some of the benefits we have encountered with this approach:
You don't need a solution, project and classes to modify some files. Most post-build files modifications can be done in powershell with line or 2.
You can keep the powershell scripts in TFS keeping a history and comments of the changes.
You can have the special values (Connection Strings, users, passwords) defined as build variables that are easier to change and with higher security than hardcoded values in a project.
You can have multiple scripts per environment. Ideally all scripts should be almost the same per environment, but maybe in production you are publishing to 2 different servers, so you'll need to call a line twice.
You'll save developers time, since the person maintaining the powershell doesn't have to be a full stack developer.
I have an ASP.NET project that outputs a class library as a dll which is then deployed to IIS. Per standard builds a config file is also output along with the dll as xxx.dll.config and it contains many useful environment variables such as connection strings (i.e. it conforms to the application settings architecture requirements).
In VS 2012 the contents of xxx.dll.config file were sourced from app.config in the project root directory.
In VS 2015 it appears xxx.dll.config's contents are instead sourced from web.config in the project root directory.
Steps to reproduce:
Create a ASP.NET application with VS2015.
Add a app.config file in this application.
Build this application.
Open the bin folder and find the application.dll.config file and open it. The content is the same with Web.config.
Do the same operations from Step 1 to Step 4 in Visual Studio 2012, the content is the same with App.config.
This is causing me a bit of a headache as I was relying on app.config to hold variables (connection strings, auth providers) for my functional tests while web.config held variables for deployed code.
Most of the reading I've done on AppDomains and their configuration variables seems to indicate that web.config shouldn't factor into the build output unless explicitly instructed and even then it isn't exactly easy to transform a web.config file, nevermind have it end up as the xxx.dll.config file.
I could rework my test fixtures to set the environment variables directly from the tests but for things like ASP.Identity that requires writing quite a few new classes to load a RoleManager and associated providers which I'd like to avoid.
If anyone could suggest how to engineer the VS build to output a config file that is easily used by the assembly AND the nunit tests when run via the nunit runner or Resharper that would be awesome.
To restore the original behaviour of Visual Studio 2015 back to what I was accustomed to in Visual Studio 2012 I added a post build event:
Go to Project-> Properties
Select Build Events
Add the following to the "Post-build event command line" :
copy /Y "$(ProjectDir)\App.config" "$(TargetDir)\$(TargetName).dll.config"
The .dll.config is now once again the App.config instead of Web.config
Anyone have a preferred method for making web.config transforms? I am curious as to what others have done for this. I hate having to continuously update the web.config every time I update or republish.
A few years ago Scott Hanselman gave a solution using pre-build events and batch files:
http://www.hanselman.com/blog/ManagingMultipleConfigurationFileEnvironmentsWithPreBuildEvents.aspx
Basically you maintain a separate different configuration for each build and run the batch script pre-build to copy over the Web.Config. The obvious disadvantage is that if you have thirty different build configurations you need thirty different configs, but I find it's nice for projects where you only have two or three configs (like hobby projects, or tools you'll only ever be publishing to internal servers). Plus, it's nice knowing that if you want to you can take extra control of the build process if you want to.
The easiest way to use VS built in support:
You have versions of web.config, for your build versions, (by default Debug and Release)
In the release version you can define transforms what are applied during build. The effective web.config will be the result.
Look into the nuget package for slow cheetah: https://www.nuget.org/packages/SlowCheetah/ This does what you are looking for quite nicely. Be aware that it is for publish transformations only, switching to a different config for local debugging will have no affect.
Create a build configuration for each server you want to deploy to
Example
-Dev Server "copy from debug"-
-Prod Server Debug "copy from debug"-
-Prod Server Release "copy from release"-
Then right click your web.config and select "add config transforms"
You will get new transforms for each configuration you added above.
Now configure your web config transforms for each environment.
Now when you publish you can just select the configuration "Dev, Prod Debug, or Prod Release" and out it goes, no need to update them after that.
Now, the base web.config should always be configured for your local environment, so if you set up in IIS locally it will use web.config without any transforms. Your transforms should transform your local settings in the base web.config to w/e they need to be.
I work on a team that works on a project. I change my project web config file to set a specific connection string but when I check-in or get latest version of project it changes to others connection strings. I have same problem in WCF Service references. appconfig and xsd files of service references always corrupted when I check-in or get latest version of program from tfs and I have to delete service references and add it again! How can I get rid of this?
We had the same issue on our project (with connection strings), and found a good solution: http://msdn.microsoft.com/en-us/library/ms254494(v=vs.110).aspx
By adding a connections.config file for each developer with his own connection string, we just needed to say that this file must not be a part of Source Control. Then in the web.config connectionString section, you just refer to the connections.config file.
Just be aware that you need to either transform your web.config or add the connections.config when publishing the site.
I know you can do the same about the appSettings section in the web.config.
How you do it with WCF, I don't know - but it sounds strange to me that your are not using the same WCF refence.
There are many solutions.
The team uses the same configuration (e.g. everyone uses localhost references)
You separate user from application settings (do not apply to all kind of settings nor projects)
Use transforms and solution configuration to map have per-environment setting
Use configSource to move config section in separate files that are not under version control
I do not think there is a perfect solution, but maybe you apply a mix of these. I strongly suggest to apply them in the stated order.
I have an asp.net/c# website that runs on a dev server and a prod server. We keep the code identical between both servers. Is it possible, based on the URL to assign different settings in the web.config (e.g. for error pages etc)
Ideally I want an IF statement in the web.config e.g.
if (url.contains "http://dev") {
web.config += #'<customErrors mode="Off" />'
} else {
web.config += #'<customErrors mode="On" defaultRedirect="~/web/error.aspx" />'
}
Application configuration files have no direct templating nor scripting support so the approach outlined in the question is not possible. Building configuration files per environment is better placed as part of a build process.
If you are using Visual Studio 2012+ (or 2010 with the Visual Studio Web Publish Update) then you can use web.config transformations to manage the difference configurations across your environments.
This can be made to work for Web Site projects as per the question using some creative thinking. E.g. http://andrewtwest.com/2010/02/25/using-web-config-transformations-in-web-site-projects/. Although this involves creating a separate project for configuration management, it is a considerably less complex approach to implementing a full build process outside of the IDE.
Using this approach, you have a master web.config which contains your base config that is common across environments. In addition, you have a web.config transform file per build configuration that applies transformations specific to that environment. In your case, this would be to turn off customErrors in dev.
More information available here: http://msdn.microsoft.com/en-us/library/vstudio/dd465318(v=vs.100).aspx
But the basic idea is make sure you have all the build configurations you need, then right click on your web.config and select add transforms. These are then applied when the site is deployed using the respective build configuration.