How do I get multiple overlapping config files for multiple solutions in ASP.NET? - 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.

Related

Shared config file among multiple web projects

I have multiple web projects each with its own web.config file.
These web projects have some common settings which I want to add in a separate config file say CommonSettings.Config
I tried adding a config file (as a linked item) as suggested in this post -
How to share configuration files between projects
But because I already have web.config file in my projects,
run-time is looking only into web.config file and not in CommonSettings.config
Is there any possibility to add CommonSettings.Config as a shared file among all projects?
Thank you!
P.S. I don't want to add these settings in machine.config file.

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.

Could not find file "C:\WINDOWS\TEMP\xxxx.dll

Here is what I have tried:
Change the directory in which the temp files are stored. (Changed locally to each website).
Store the XMLSerialization object in a global variable and use that instead of creating a new one each time.
Delete all temp files in the windows temp folder.
Set permissions on the windows\temp folder (I have them set to everyone at the moment just to try and resolve the issue).
My Setup is as follows:
IIS7 on windows 2008 dedicated server.
The website is written in ASP.NET using Delphi.
I have several XML files that need serializing so not just one.
My website talks to the web service and processes the XML (I am guessing this is the part that is breaking everything)
Does anyone have any suggestions other than what is listed? I have read about using SGEN to pre-compile the serialization object but will this work for more than one XML file? I don't really know much about it.
Here is an example:
This is the code for one of my XML files. StockXMLSer is held globally and after testing is only created once per site.
function IntGetSTOCK_ITEMS(S: TStream): STOCK_ITEMS;
begin
if not Assigned(StockXMLSer) then begin
StockXMLSer := XmlSerializer.Create(STOCK_ITEMS.ClassInfo);
OutputDebugString('StockXMLSer Serializer Created');
end;
Result := STOCK_ITEMS(StockXMLSer.Deserialize(S));
end;
You will need to add some settings to your code in order to be able debug your serialization code. Please consult the following article on msdn.
Troubleshooting Common Problems with the XmlSerializer
Also there is a neat trick there that will keep the files created in your temp folder so you can see what is happening.
Under normal circumstances, the
XmlSerializer deletes the C# source
files for the serialization classes
when they are no longer needed. There
is an undocumented diagnostics switch,
however, which will instruct the
XmlSerializer deletes to leave these
files on your disk. You can set the
switch in your application's .config
file:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.diagnostics>
<switches>
<add name="XmlSerialization.Compilation" value="4" />
</switches>
</system.diagnostics>
</configuration>
With this switch present in the
.config file, the C# source files stay
in your temp directory. If you are
working on a computer running Windows
2000 or later, the default location
for the temp directory is \Documents and Settings\\LocalSettings\Temp or
\Temp, for web
applications running under the ASPNET
account. The C# files are easy to miss
because they have very odd looking,
randomly generated filenames,
something like: bdz6lq-t.0.cs. The
XmlSerializerPreCompiler sets this
diagnostics switch, so you can open
the files to inspect the lines on
which the XmlSerializerPreCompiler
reported compilation errors in Notepad
or Visual Studio.
Just for the record, I had an error similar to this one and found the solution from this blog
After setting the permissions on the TEMP folder, the functionality that the error had started to work again.
XML Serialization creates a temporary DLL with the serialization code in it, somewhere in the temp directory. This is loaded into your App Domain when the serializer is created. It's possible that you are deleting this DLL when you clear the Temp directory, and for some reason, it's not getting regenerated correctly.

How to conditionally return web.config entry

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.

ASP.NET: external custom config file in a virtual directory - how to?

I know that there at least two approaches to leverage the web.config file:
using the configSource attribute which was introduced in .NET 2.0 - here is a good blog entry about it.
The file attribute of the appSettings tag which lets you point to an external file with a relative path. Described in the MSDN documentation on the appSettings element.
Now, my problem is that both approaches work well only for physical paths. But I need to address a config file which is in a virtual directory.
Which other method could I use to put my config resources in a virtual directory?
Note: I want to do it this way, because I have multiple instances of my web application on the same server (and that on many servers). To keep deployment easy and clean, I want to keep one directory for all the files (aspx, ascx, images, css, js etc.) and point the web apps in IIS for different customers (=domains, https etc.) to this single directory. In every IIS web I would have a virtual directory called "custom" which points to a different folder for each web.
Update: I'd like to point out that this virtual directory "custom" is not suited to contain an inherited web.config - that web.config would be valid only for the custom folder which doesn't contain aspx/ascx files.
I have the same scenario and after reading you post I realised that asp.net won't let you do this for various security reasons.
Therefore I turned to the OS to find an equivalent to the Linux soft link function which in turn led me to the Junction utility from sysinternals. This can create a directory that is actually any other directory on that volume and asp.net can't tell the difference and so happy loads the config sections that are not actually in a subdirectory of you website. Works for me :)
Virtual Directories can be set as applications, and you can just place another web.config there.
It will inherit any changes from the parent config, and you can add custom settings in it.
I was looking to do the same thing but it did not work, so I decided to do the opposite, as you know the web.config can be inherited, so I pointed IIS to a folder containing the client config (connection string, file path etc) files and the website files i put them on a virtual directory with the rest of the webconfig (where it load dll and other application files needed)
So basically i can use the website files to multple clients and the clients with their own Database connection string and other specific client settings.

Resources