How to conditionally return web.config entry - asp.net

How do I return web.config entry conditionally.
I.E: If the web.config folder is 'C:\inetpub\www\myTestSite' then return 'connectionString' TestDB
else return 'ProdDB'

You can try something like this:
string conn;
if (Server.MapPath("~/web.config").StartsWith(#"C:\inetpub\www\myTestSite"))
conn = ConfigurationManager.ConnectionStrings["TestDB"].ConnectionString;
else
conn = ConfigurationManager.ConnectionStrings["ProdDB"].ConnectionString;
Although I would recommend a different approach, either by using separate config files for your sites or by using a more sophisticated method of testing where your code is located. What I do is put a key in appSettings in the machine.config file for my development machine, as well as my test, and production web servers so that my application knows what environment it is running on. I use the value of that appSetting to determine which connection string to use.

It is much better to use different config files for the different wnvironments.
You can have the following in your web.config file:
<connectionStrings configSource="SiteSettings\connectionStrings.config"/>
where the configSource is path relative to the path of the web.config file. Then you can easily create 4 different connectionStrings.config files in your project: connectionStrings.config.dev, connectionStrings.config.test, connectionStrings.config.staging, connectionStrings.config.prod. With that set up you can configure your build process to automatically choose the right connectionStrings.config file for the right environment. This way maintenance will be a lot easier.
ScottGu has an article describing this method. And one more article about Customizing web.config for different environments which you may find helpful.

Related

customising web.config based on domain name

Most of my websites include one LIVE (production) and two TEST environments which are accessible via three different domain names e.g.
www.mysite.com
test1.mysite.com
test2.mysite.com
Each of the above are IIS Websites which point to the same physical versioned folder when they are all running the same version of the website.
What I typically do when releasing a new version is to place the new version into a new physical folder e.g. /inetpub/wwwroot/mywebsite/v41/ and point one of the TEST sites to that version of the site and test it. Once passed, the LIVE (and other TEST) websites are also repointed to the new version (e.g. v41).
Now my problem is this. Each website has its own database (TESTs have a copy of LIVE which can be refreshed via a couple of SQL BACKUP/RESTORE commands) however, the three sites are all "looking" at the same web.config file and therefore the same Database Connection Strings (either a System.Data.SqlClient or System.Data.EntityClient provider).
Is there any way that I can configure web.config to provide different connectionStrings based on the domain name/IIS website of the incoming request?
Maybe a tag or an attribute that qualifies a given tag?
I've looked all over for a solution but not yet found one.
Thanks in advance,
BloodBaz
there are two ways to manage multiple environment Specific Web.config file....
using t4 template,below is the link for that
http://ilearnable.net/2010/08/02/t4-for-complex-configuration/
VS Configuration Manager and create new "LIVE", "test1", "test2" build configurations for your project,check out the link
http://weblogs.asp.net/scottgu/archive/2007/09/21/tip-trick-automating-dev-qa-staging-and-production-web-config-settings-with-vs-2005.aspx
hope this helps..
why not split your config file up so connectionStrings.config is its own file. Then you can deploy everything and not overwrite that connectionString file.
where you normally would put the connectionString do this
<connectionStrings configSource="connectionStrings.config" />
Then create a file named connectionString.config
<?xml version="1.0"?>
<connectionStrings>
</connectionStrings>
Alternatively you can create another build option other than just release/debug. You can have web.config transforms that output a different config file depending on which one is selected.
I had a similar problem; I solved it by setting up all the database connection info in the same web config file, and then writing a handler that decides on the fly, based on the request and context, which environment it's in and uses that database.

How do I get multiple overlapping config files for multiple solutions in ASP.NET?

I'm very new to ASP.net, so I'm just figuring this out.
First off, I have multiple separate projects that will be hosted on the same server.
Second, they must be able to share certain settings (like connection string, configuration options, etc).
Third, those shared settings must be configurable for different deployments (test, prod, etc).
For example, I have two projects:
Project A
Project B
I have a setting called "Setting1" which should be accessible to both projects.
The value for "Setting1" should come from one of these files:
"TEST-config.xml"
"PROD-config.xml"
(There will be more than two config files, but I'll keep it simple for now)
And I want to have only a single place to change a single text file, which determines which of the *-config.xml files will be used:
"WhichSettingsFile.xml"
Here's an example of the file structure:
\WhichSettingsFile.xml
\TEST-config.xml
\PROD-config.xml
\Project1\Project1.csproj
\Project1\web.config
\Project1... (more files)
\Project2\Project2.csproj
\Project2\web.config
\Project2... (more files)
So currently, each project has a "web.config" like this:
<appSettings file="..\WhichSettingsFile.xml">
...
</appSettings>
Then I have a file "WhichSettingsFile.xml" like this:
<?xml version="1.0" encoding="utf-8" ?>
<appSettings>
<add key="SettingsFilenamePrefix" value="PROD" />
</appSettings>
And I have code like this:
public static string GetSetting(name) {
string filename = System.Web.Configuration.WebConfigurationManager.AppSettings["SettingsFilenamePrefix"] + "-config.xml";
// Open filename, parse as XML, get the values I need from it.
}
This means I can host both projects on Server A, set the WhichSettingsFile.xml to contain "PROD", and all settings will be read from "PROD-config.xml". I can do the same for the test server. And all those values are shared among the separate projects.
However, I need to be able to edit these files on the filesystem, and not have them embedded within the dlls / assemblies. When I run the project(s) from visual studio, the built-in asp.net hosting server will deploy the files to something like:
C:\Users\[username]\AppData\Local\Temp\6\Temporary ASP.NET Files\lskdjflskj\slkdjfsld\klsjdfwbe
But there will be no "WhichSettingsFile.xml" file since it's embedded in the assembly. Furthermore, the "PROD-config.xml" and "TEST-config.xml" files will not be included since they're not really part of the "code", and are not copied.
Ideally, I want to have this in the deployment folder:
C:\Users\[username]\AppData\Local\Temp\6\Temporary ASP.NET Files\abc123\Project1\(all the compiled files here)
C:\Users\[username]\AppData\Local\Temp\6\Temporary ASP.NET Files\abc123\Project2\(all the compiled files here)
C:\Users\[username]\AppData\Local\Temp\6\Temporary ASP.NET Files\abc123\WhichSettingsFile.xml
C:\Users\[username]\AppData\Local\Temp\6\Temporary ASP.NET Files\abc123\PROD-config.xml
C:\Users\[username]\AppData\Local\Temp\6\Temporary ASP.NET Files\abc123\TEST-config.xml
But I'm not sure how to do this.
So my problems:
-The "WhichSettingsFile.xml" is embedded into the assembly. I want this to be a plain text file on the filesystem that is referenced at runtime by the application. I realize I might need to avoid using for this. Is there a better way?
-I want to have multiple config files, also as plain text files on the filesystem.
I know what I've got is not working, and probably convoluted. But is there a better way to do this? Thanks!!
you can have a separate web.config per directory.
the root directory web.config will affect all sub folders. but values can be overwritten in sub folders with local web.config files.
you can add a new values with <add ... />, you can remove exist value set in global web.config with <remove ... />, you can clear all values in a section using <clear />.
http://weblogs.asp.net/mnolton/archive/2005/01/10/349986.aspx
If having separate directories doesn't fit with your architecture, you can store your configuration in a database, which is ideal in most scenarios as it offers caching, ability to change values w/out restarting application, sharing settings among multiple web servers, easier deployments (since you don't have to deploy files when changing settings) and so on.

Modifying Root Web.config in code

I would like to store some meta-information about a given site instance that can (a) be managed by that site instance and (b) persist clobbering of Web.config file.
The site will run in multiple environments (dev,testing,staging and production) and each environment can have different values for this metadata.
Note: All environments are running IIS 7.0+
The Root Web.config seems very appealing, as it is certainly outside of the website. Therefore, both files and databases can be changed while maintaining the metadata. I have seen how to modify the appSettings of the Web.config stored in the website, but is it possible to similarly modify the appSettings in the Root Web.config (Specifically within the proper directive)?
If you have other suggestions of approaching this problem, I would be very happy to hear them. Thank you!
would not use web.config for runtime modifications, that will cause the application to recycle, perhaps some other form of configuration file like app.config
if my assumption is incorrect and the web.config will not be edited after the application is started, then you can use WebConfigurationManager to access the file sections
Yes you can modufy the app settings within your web.config Just use the WebConfigurationManager class in the System.Web.Configuration namespace to create a Configuration object. This object could then be used to read and write changes to the web.config file.
You could then create your own "keys" or attributes that could be read as needed.
Depending upon what your attributes represent or if they need to be picked up by multiple environmnets from that server I would also look into making the modifications within the machine.config file as then those settings would apply to the enter machine and thereby picked up by multiple environments( if you are hosting multiple webapps from the server). This could save you time in modifying multiple web.config files and narrorw the storage or the metadata to one location vs. multiple config files in certain situations.

Read a web.config file in a virtual directory

I have an ASP.NET application (Root Application) that has a virtual directory set up to another ASP.NET application (Virtual Application). How can I make the Virtual Application read values from the Root Application's web.config file? I was looking at the WebConfigurationManager.OpenWebConfiguration() class, but I'm unsure how how to tell it to go up one level from the root. For example, I would tell it to go to ~/web.config to get the the Virtual Application's web.config file, but I need it to go up one more level to the Root Application's file structure. Is this even the correct approach?
Any help would be greatly appreciated!!
You can use the ExeConfigurationFileMap class with ConfigurationManager, like:
string configFile = new FileInfo(Server.MapPath("/Web.config")).Directory.Parent.FullName + "\\Web.config";
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = configFile;
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
Response.Write(config.AppSettings.Settings["Test"].Value);
IIS does have programmatic access to its configuration data (which is documented on MSDN and/or Technet). This will be the only supported route (i.e. will continue to work across IIS versions).
Otherwise you can hack a solution (both of these will require higher than usual rights for the process):
Parse the output from appcmd.exe:
E.g. here:
> C:\Windows\system32\inetsrv\appcmd.exe list vdir
VDIR "Default Web Site/" (physicalPath:E:\Dev\weblocal\XYZ)
VDIR "Default Web Site/DevRoot/TestWebClient" (physicalPath:E:\Dev\Tests\ClientSideWeb)
VDIR "Default Web Site/Home" (physicalPath:E:\Data\Homepages)
Read the configuration directly from C:\Windows\System32\inetsrv\config.
I think you will find that your desired behavior is in fact the default behavior.
web.config settings cascade down. Your app will look up to the next hierarchical web.config if it can't find the value.
This would allow you to just look up via AppSettings etc. for most cases.
I'm not sure what happens if you really need to direct access to the file as opposed to the various config api access methods.
I have a setup like this right now using IIS7 with multiple virtual apps configured.
I tried HectorMac's suggestion again and it still doesn't work for me. As a result I am going to seek an alternative to storing my value in the web.config file.

asp.net managing multiple web.config files

Can anyone suggest a good way to manage multiple web.config files?
For example, I have a development web.config I use on my localmachine named "localWeb.config" and then one I use for production called "prodWeb.config". I keep the .config extensions so no one can access them from the web server.
localWeb.config will for example have a connection string to a development database while prodWeb.config has one to the production database.
Currently, I am using a postbuild event that will copy the contents of localWeb.config or prodWeb.config to web.config. This works well but I was wondering if anyone knew of any better ways.
You could see if the method outlined on this CodeCarnage page suits your needs better. It utilizes the configsource attribute to point to DB and APP settings, each of which are seperated by environment. This could perhaps allow you to keep the consistent stuff in web.config and keep environment specific "stuff" in other config files.
Check out the Web Deployment Tool:
Here are just a few of the tasks that
be accomplished using the tool:
Create a package that contains content, configuration and SQL
databases for deployment or sharing
with others.
Use the package as a way to version your application or create backups.
Add parameters to replace a connection string or other value in a
file during install of a package.
Enable non-administrators to deploy packages and granularly control their
access.
Synchronize or migrate both sites and servers running IIS 6.0 and IIS
7.0.
this will continue to be a hack until asp.net 4 arrives http://www.asp.net/learn/whitepapers/aspnet40/#_Toc223325501
I keep a single config file and use logic at runtime to detect of which subset of configuration to use. If the hostname is "prodsrvr-*" then I use the production server configuration, including db connections, etc. If the hostname is "test-*" then I use the test config data. And etc.
EDIT: here's some code that does what I described.
public static string GetConnString()
{
string connString = ConfigurationSettings.AppSettings[GetConfigKey("database")];
return connString;
}
public static string GetConfigKey(string baseKey)
{
string str = baseKey;
if (Dns.GetHostName().StartsWith("dinoch"))
{
str = str + "-dev";
}
else if (Dns.GetHostName().StartsWith("prodsrvr"))
{
str = str + "-prod";
}
return str;
}
<configuration>
<appSettings>
<add key="database-dev" value="server=(local)\vsdotnet;database=ASPXAPPS;Integrated Security=SSPI" />
<add key="database-prod" value="server=(local)\vsdotnet;database=ASPXAPPS;Integrated Security=SSPI" />
</appSettings>
</configuration>
I use a simple StartsWith() , with some "magic strings" hardcoded.
To avoid that, I could imagine defining a map of regex's to suffixes in the web.config file. Where, if regex1 is a match on the hostname, then use suffix1. If regex2, then use suffix2. Etc. You would load the map just once, and then just to a foreach() enumerating through the regex's and returning if they match the hostname.
Or, maybe there is a different criterion you want to use, to distinguish prod from dev from test servers, other than hostname. It's up to you.

Resources