Background:
I have an ASP.NET web app configured for federation with AD FS. I'm using VS 2012, and have TFS for source control, builds and deployments.
We're currently deploying by copying the built files from the build server (TFS) to the alpha environment. From there we would copy from alpha to beta, then from beta to production. So there is not a unique build for each environment. The way we're handling environment-specific settings right now is there is one config file that has all the settings for each environment Let's call this EnvironmentSpecificSettings.config (I'll refer to it below). There is a static file on each server that indicates which environment the server should be in, and so when that config file is read in, the matching settings can be applied.
The problem:
The ADFS configuration is handled in the web.config. There are a few things that are specific to the environment. How might I handle this within my current deployment paradigm? I had a couple of ideas:
include a file reference in the web.config that reads in a static environment-specific file that would not be part of the deployment.
Try to pull something off in Application_Start that would read in settings from EnvironmentSpecificSettings.config (mentioned above) and alter the web.config.
Try to tweak the configuration of the WSFederationAuthenticationModule at runtime
the first idea (#1) is less than optimal because it requires files hanging around outside of source control and outside of deployments, however it should work easily enough. Next, #2 I kinda think isn't possible. I'm not sure you can change your web.config like I am hoping, but maybe? Finally, #3 Is only reasonable because I'm in a special situation where I'm not doing regular passive authentication, instead I'm manually redirecting to adfs, so I have a chance to change settings, such as injecting the whr parameter to avoid HRD. So, it might be possible, however, I'm not sure how or if you can change some of these values on the fly such as thumbprint, or wsFederation issuer or realm.
Does anyone have any better ideas or experience in handling environment-specific settings without doing the visual studio web deploys with transforms?
Related
I understand that the WebRole module inside my Web Role web app project runs inside WAIISHost.exe and the rest of the app runs inside W3WP.EXE. Therefore web.config settings cannot be read from the WebRole app domain.
This can be solved by creating a special "waiishost.exe.config" in the web project file and set the "Copy to Output Directory" property to "Copy Always".
That's fine. However, now, I have config settings in ServiceConfiguration AND web.config AND "waiishost.exe.config". This is only a minor but annoying issue though. The biggest problem is that when I publish my Azure project, ServiceConfiguration and web.config get automatically transformed into the production values whereas waiishost.exe.config does not get transformed, so I end up with development config going into the production environment. (the production env is not live yet, so not a major issue yet)
Can anyone think of any ideas as to how I can also have the Publish process transform waiishost.exe.config? Maybe I could run some kind of startup process which could simply copy and rename the web.config file to be waiishost.exe.config before waiishost.exe starts.
BTW, I cannot simply move config to the ServiceConfiguration file as I have whole config sections and connection strings which are used by third party components, like the ServiceBusConfiguration section.
Many thanks
Yes, there is.
A little manual, but is "one-time-setup" per project. Check out this and that blog posts I've made a while ago (even before you could have ServiceConfiguration files). These blog posts will give you a great idea on how to achieve your desire.
I’m a fan of the new VS 2010 Web.config transformations. I use this feature for deployment purposes and wondered if it is possible to use them for debugging too.
I think of using them in the IDE: I want to create different built configuration (with linked transformation configurations); choose one of them; start the web site in the IDE and debug the different configurations this way.
Update
Thanks to a 3rd party plugin, SlowCheetah, this is now possible. Scot Hanselman has a blog post about it.
Original response:
Unfortunately, the web.config transformations appear to effect only publishing sites and building deployment packages.
In our scenario we have two development groups, one with access to multiple environments (in-house) and the other with access to a single environment (offshore). We have periods where the in-house group needs to debug directly against QA, while offshore remains locked-out (so their web.config's must point to the dev environment).
We were hoping to have 1x build-configuration per-environment, and be able to choose the build-configuration which matched the environment to debug against--which, as I understand it is your question.
In case anyone is curious why they haven't built this feature, from:
http://forums.asp.net/p/1532038/3711423.aspx
"When the web app gets run, the web.config under project root folder will be picked up by asp.net and I know unfortunately it is under source control . I certainly understand the cleanness coming with letting runtime use a transformed web.config from a temp folder; however, asp.net runtime doesn't know anything about vs projec structure and it is totaly based on directory structure. Using alternate path might also break as a web.config under a subfolder expect to inherit settings from the upper level of directory."
I found an alternative solution that does not involve any third party tool: http://ledtalks.blogspot.in/2011/09/webconfig-transformations-when.html. I only tried this for the web.config file
We have a series of web services that live in different environments (dev/qa/staging/production) that are accessed from a web application, a web site, and other services. There are a few different service areas as well. So for production, we have services on four different boxes.
We conquered the db connection string issue by checking the hostname in global.asax and setting some application wide settings based on that hostname. There is a config.xml that is in source control that list the various hostnames and what settings they should get.
However, we haven't found an elegant solution for web services. What we have done so far is add references to all the environments to the projects and add several using statements to the files that use the services. When we checkout the project, we uncomment the appropriate using statement for the environment we're in.
It looks something like this:
// Development
// using com.tracking-services.dev
// using com.upload-services.dev
// QA
// using com.tracking-services.qa
// using com.upload-services.qa
// Production
// using com.tracking-services.www
// using com.upload-services.www
Obviously as we use web services more and more this technique will get more and more burdensome.
I have considered putting the namespaces into web.config.dev, web.config.qa, etc and swapping them out on application start in global.asax. I don't think that will work because by the time global.asax is run the compilation is already done and the web.config changes won't have much effect.
Since the "best practices" include using web services for data access, I'm hoping this is not a unique problem and someone has already come up with a solution.
Or are we going about this whole thing wrong?
Edit:
These are asmx web services. There is no url referenced in the web.config that I can find.
Make one reference and use configuration to switch the target urls as appropriate. No reason to have separate proxies at all.
Is it possible to configure an IIS site to read ASP.Net settings from a site OTHER than web.config?
We'd like to have three config files in our codebase -- web-dev.config, web-test.config, and web-prod.config. Each IIS instance would be configured to read from their specific file. This way we have version control them all next to each other (and one-click deploy the entire site) but know that each IIS instance will read the settings specific to itself.
I've found in IIS where it shows where the web.config is, but I can't see how to change the location.
I use the configSource property to specify an external config file for sections that need different values for dev and production.
<connectionStrings configSource="Config\ConnDev.config"/>
Then you only have to change one setting (manually or with a tool) to switch from Dev to Production configs.
The best solution right now is to use different configs for development and production. This however will change with .net 4 and VS 2010 which they have added Web.Debug.config, Web.Release.config, Web.Staging.config and Web.Testing.config which will then publish the config you need in relation to the environment.
At my company we just have our deployment tool set to copy the appropriate file to web.config depending on what kind of deployment we're doing.
I believe it has to be named web.config.
You are facing a common problem.
One solution that I have used that worked really well in a large organization was to set environment variables on the web servers. Such as DEV, QA, UAT, PROD. Then, in code, you can query the environment variable to see which machine you are on, and then choose the values of appSettings accordingly. For example, you could have a database connection string named DEVconnection, and another named UATconnection. If your code determines from the environment variable that you are on UAT, then it would use UATconnection.
This does assume that you have the ability to set environment variables on the web server. In this instance, the admins running the servers were the ones who suggested this solution.
What was sweet about this was that there was ever only one version of web.config.
I do not think we can make web.config declaratively so that we can specify different config file. One thing you can do you can split your configuration file and set for different environments.
Please go through this article
http://jetmathew.wordpress.com/2011/02/07/split-web-config-for-different-environment/
cheers
How can one specify the connection string in a config file of a class library and later modify this when used in a ASP.NET Web Application?
The Class library is a data access layer that has a Dataset connecting to a database based on a connection string specified in a config file (Settings.settings/app.config).
This class library is used in a web application where user inputs data and is written to the database using the DAL classes & methods exposed in the class library.
Now, I want to migrate this application from development environment to testing environment and later to production. The problem I'm facing is that after migrating to testing, the app in testing still connects to development database. I've changed the connection string mentioned in <class library>.dll.config file but this seems to have no impact.
Can someone explain the right way to achieve this? Thanks in advance for any help. Cheers.
With the .config files the name has to match the main executing assembly. For example I had a situation like yours, I needed a class library to have its settings in a .dll.config file. While it was able to reference it the actual application would not be able to read the config file because it was expecting .exe.config. Renaming the .dll.config to .exe.config fixed the problem.
In your case migrating your connection strings from .dll.config to web.config should fix your problem!
Good luck!
Joshua is partly right ... For posterity I would like to add a bit more to this answer as I have delt with the same problems on several occasions. First, one must consider their architecture. There are several issues you can run into with .config files in ASP.NET based on deployments.
Considering the architectural ramifications:
Single tier (one server):
A simple web application may be able to leverage a reference to the sites Web.config file and resolve your issues. This would be a fine solution for a single tier application. In the case of a windows application leveraged as a .exe file, the App.config will work too.
Multi-tier (more than one server):
Here is where things became a bit hairy for me the first time I was working with .config files across boundries. Remember the hierarchy of the config structure and keep this in mind (MSDN Article on .Config structure) - there is a machine.config at the root in the appropriate ASP.NET folder. These reside at each physical server. These are overridden by the site Web.config (or App.config) which are in turn overridden by subfolder .config files. If you have more than one .config file you may want to use one of the methods to pass the file path for the specific .config you want to use. More importantly, these files each may have connection information. ASP.NET's machine.config holds some for the framework ... so you should at least be senstive to the fact this is an "inheritance" chain. Second, any changes to the Web.config file once deployed will tell the application to restart. This will result in loss of state (bad if you have active users on the site). The way around this is to keep a separate .config file (e.g. connections.config) and put a reference to that file in the Web.config. This will allow you to change the connection information (e.g. password) without having to restart the application. Here is a link to more info: MSDN: Working with Configuration Files. This article lays out all the details you need to be aware of in a normal server / IIS deployed application. Keep in mind that the .config files are mainly intended for applications, not libraries. If you have several tiers, chances are you are using some communicaiton / messaging layer (e.g. WCF). This will have / allow its own Web.config. You can keep connection strings there (and encrypt them if needed), but better yet, put them in a second file referenced by the Web.config for manageability. One final point, if you are ever going to consider the cloud, .config files are wrapped for application deployments which in effect removes all of the benefits they offer in terms of "not having restart or redeploy". Azure deployments will want to consider this article to save themselves from nightmares of maintenance: Bill Lodin blog - Configuration files in Azul / Cloud. One other point on this article – great example on how to programmatically select configuration depending on deployment! Be sure to check that out if you want to add flexibility to deploy in or out of the cloud .
I hope these points saves all of you time and headaches. I know I lost a couple days of programming time dealing with these issues ... and it was hard to find all the reasons in one place why may app was not "implementing" its connection object. Hopefully this will save you all from the same fate I had.