How to read site's web.config file from Azure WebJob? - c#

I am using custom web.config configuration elements to configure complex application services for my ASP.NET MVC application. I need this configuration data in my Azure WebJob which is deployed alongside the web app. I am trying to avoid copying these sections from website's web.config to webjob's app.config file.
So, apart from connection strings and application settings, is there a way for an Azure WebJob to read the website's web.config file?
Ideally, I would like to use ConfigurationManager.GetSection to create my custom ConfigurationSection instances.

Most web apps + web jobs have sensitive settings that you don’t want in a config file. You can deploy those secrets using ARM/PS see deploying secrets to Azure. So just add all your settings to your ARM/PS script.
Azure App settings apply to the web job and the web app, this is the recommended approach.

Here is a solution for a build time. Probably this sample Msbuild script would insert a peeked xml elements from your web.config into another xml file. Please note it is not tested.
<ItemGroup>
<PublishPackages >
<WebConfigXml>
$(YourProjectPath)web.config
</WebConfigXml>
<WebJobConfig>
$(YourWebJobPath)app.config
</WebJobConfig>
</PublishPackages>
</ItemGroup>
<Target Name="InjectConfigs">
<XmlPeek
XmlInputPath="%(PublishPackages.WebConfigXml)"
Query="//parent/someelement">
<Output TaskParameter="Result" ItemName="Peeked" />
</XmlPeek>
<XmlPoke
XmlInputPath="%(PublishPackages.WebJobConfig)"
Query="//parent/someelement"
Value="$(Peeked)"
Condition =" '$(Peeked)'!=''"
/>
</Target>
</Project>
These docs can help: Configuring Parameters for Web Package Deployment, XmlPeek task
And if XmlPoke and XmlPeek won't do the thing another way is to use XmlFile task. Hope it helps!
UPDATE. Changed to use only XmlPeek and XmlPook without XmlFile.

Here is a solution for installation time. There is a technology called Web Deploy that allows to create packages which can be run from command line and install services. And it allows parameterization of .config files by using one xml file called Parameters.xml. This one can be shared by your web site and Web Job I believe. The howto manual on doing it.

One approach we used for a similar purpose to this was to put all the common configurations on a Table Storage account in Azure and built a helper class that reads the configuration from what we referred to as: "Run Time Configuration", which is basically a configuration database that is hosted in Azure Table storage and all components could read that information...

Try using the CloudConfigurationManager class in the Microsoft.WindowsAzure.ConfigurationManager NuGet package.
ie.
var val = CloudConfigurationManager.GetSetting(key);
I find that this seems to pull the settings from the host Web App while running on Azure. If you're debugging locally you'll still need to set the App.config values, I'm afraid.
Edit: Just re-read your question again (d'uh!) and saw your comment about using Sections. AFAIK that's not supported by this class - AppSettings section only unfortunately.

Related

ASP.Net - use seperate configuration file for database and app settings

I have an asp.net project that is using Entity Framework that is used on several different client servers. This means a different web.config for each for connectionstrings and app settings.
Hasn't been an issue but I changed something that altered the web.config file recently and I manually had to adjust this for each client, I also have to exclude the web.config file in updates to ensure their own one is not overwritten.
What I would like to achieve is store these settings in maybe another config file that the project can pick up and use. Maybe that on Globals Application_Start gets these and imports them/overwrites the current web.config file perhaps.
Essentially I don't want to affect the current code that uses the connection string and ConfigurationManager.AppSettings used throughout the project but I do want to be able to let the web.config file update for each client and use a seperate file for some settings.
NOTE: I do not have access to publish directly to each server so I can't simply write a different deploy web.config for each one. I have to publish the files locally, store as zip and automated routine on servers downloads and extracts accordingly.
EDIT:
Please do say if this is considered a bad idea but an idea I had was to put something similar in Global.asax Application_Start method:
Does config file exist?
If no, create file and append all current settings in web.config
If yes, open and import those settings to the current web.config overwriting the original values
Hopefully then in a few weeks time, after I have asked all clients to perform a manual update they will have this code and I can begin to include the web.config in updates.
In VS, inside the Build menu, the last item is Configuration Manager.
In here you can specify various different release environments which can each have their own web.config transforms.
This is normally used for production/staging/test environments. However, I can see no reason why you could not use this and have a configuration file for each of your servers/environments.
You will then need to create the transformations for each environment, by rightclicking the web.config, then selecting Add Config Transform.
each of the environments you had setup can then override the settings in the main web.config. (That now acts as a template/default settings)
e.g.
In Web.EnvironmentA.Config
<add key="ConnectionString" value="ConStringA" xdt:Transform="SetAttributes" xdt:Locator="Match(key)"/>
In Web.EnvironmentB.Config
<add key="ConnectionString" value="ConStringB" xdt:Transform="SetAttributes" xdt:Locator="Match(key)"/>
Then when you do a publish, you simply setup which config file to use. If you use Azure or the VS publish method, it will save each of these settings, so then you can simply push to the relevant environment easily.
Just make sure you test this works as you intent first, before you start publishing everywhere ;)

Azure app sharing

I have a azure app. Is it possible to share it as free aplication(so anyone will be able to deploy it on own azure account) without giving out source code and recompiling it each time. I'm using azure database, so I need connection string to it for making requests and now it string is hardcoded. Also I'm using hardcoded connection string to access to blobs and dynamic instances allocation. Is there the way to take these strings out and allow to change it wihout recompiling project?
Thanks.
Yes, absolutely. When you compile a cloud project, it creates a package file and a configuration file. If you want, you could distribute those files.
Regarding removing connection strings and other settings, one thing you could do is create a separate cloud project that has the same settings as your main cloud project. Only thing is that the settings which are specific to a user environment (like connection strings) would be empty. Then you would package this cloud project and distribute cspkg and cscfg file.
To elaborate further, take a look at the screenshot below:
Essentially here I have 2 cloud projects (Web.Azure and Web.Test.Local) and both of the cloud projects are referencing same Web project. Now in our case Web.Azure is our development cloud project and Web.Test.Local is the test cloud projects. Both of these projects have same settings name e.g. SqlConnectionString. Now in the Web.Azure, I have specified its value to be that of our development SQL Server but in Web.Test.Local I can specify any other value. When we want our testers to test the application, they get the package for Web.Test.Local and they get the settings based on that project. Taking the same analogy, you could have two cloud projects (let's call then Dev and Release). What you have to do is use the same settings in both cloud projects but there won't be any values for those settings in your Release project.
Yet another approach you could take is what's described in this blog post: http://blog.paraleap.com/post/2011/09/13/Managing-environments-in-a-distributed-Azure-or-other-cloud-based-NET-solution.
Please note that cspkg file is essentially a zip file. I could change the extension of the package file from cspkg to zip and unzip that file and see all the binaries. I could then use a tool like RedGate's Reflector or Telerik's Just Decomplie to decompile the binary files and possibly look at the source code. To avoid that, you may want to obfuscate the binaries before packaging them.

Allowing a Windows Service to be configured

I have a Windows Service that I'm creating and I'm wondering what options are available in order for me let developers configure the service.
The service is part of an over all larger open source project and hence the service is going to be installed on lots of different machines.
Normal I would use a web/app.config for this but I'm not sure if this is possible.
Hence I am looking to so how others handle this case.
you do as you expect. You use the app.config, which will be renamed to <exeName>.configwhen the project is built and then <exeName>.config will be read by the service called <exeName>.
Settings are applied in a layered way and may come from other configuration files on the machine, such as machine.config. You can read about how configuration is handled on MSDN
EDIT
In response to comment: A service will only read the config when it starts (for perf reasons). If you want to reload the config file later, you need to handle that yourself I think.
You could read the last modified date/time of the config file to determine if the file has been changed, or setup a file system watcher and then tell the configuration manager to reload that section again next time it is read, by calling ConfigurationManager.RefreshSection("appSettings") and that section will be reloaded from disk when you next access it. See the ConfigurationManager MSDN docs
You can just use a .config file with the same name as the exe that is the service.
If your service runs as MyService.exe, it's config file would be MyService.exe.config.
In Visual Studio, just add an Application Configuration file. This will add an app.config file to the project.
You can then access things like AppSettings and ConnectionStrings using the ConfigurationManager class, just like you do with ASP.Net applications.

Can multiple C# apps use one App.Config file?

We have many C# console apps that run on scheduled tasks. All of these apps have their own config file, which contain settings like our smtp server. If our smtp server ever changed, we would have to manually go into each config file and change it. Can multiple apps look at 1 config file on the C: drive, or is that considered bad practice? Using the database to store values is a no no.
You can point to external config files inside your application's configuration file like the following, and have all your applications use the same set of settings from a single file:
<appSettings file="c:\CommonSettings.config">
<add key="MyKey" value="12"/>
</appSettings>
For more information, you can read following articles:
AppSettings can Reference an External Config File
How to share custom application configuration settings across projects in .NET
It is not directly possible to share one application configuration file because the .config filename needs to match the executable name (so for example.exe it would be example.exe.config).
It makes sense to have separate values for the different applications, as they are separate applications.
If there are configuration sections that you do want to share, you can use the configSource attribute to point to a file. The appSettings section also has a specific file attribute that you can use in the same manner.
If there are certain configuration values that are shared across all applications, you can consider placing them in the machine.config file for the version of the framework you are using.
Can you use custom xml files to store configuration data ?
There's no necessity to use app.config.
Using Cinchoo framework you can achieve this, by simply creating custom configuration object and use it all the console applications. All of them will read from same configuration file. For more information, please visit http://www.cinchoo.com

Using Log4Net during setup application

I'm having trouble seeing how I can use logging in my setup / install project.
I've got Log4net working on installed applications, but I can't seem to log the install / uninstall process.
My main problem is with the logging config file.
I suppose it's a bit of a chicken/egg scenario - theres no way for me to grab the just-installed logging file?
I have a method that finds the root directory of my app, using - AppDomain.CurrentDomain.SetupInformation.ApplicationBase
and i normally use this to locate the logging config file.
This directory however, during install, is not where it is installing (obviously) it is somewhere within the windows filesystem.
Does anybody have any ideas to this?
Consider configuring log4net in code and not using a file or storing the configuration as a file resource of your custom action assembly and using XmlConfigurator.Configure(Stream configStream) overload.
Of course if you want to reuse the configuration of the application this is not a clean solution.
Also checkout this question:
log4net pure code configuration with filter in c#
When executing MSI's you are bound to msiexec's logging mechanisms (which is not as friendly as log4net).

Categories

Resources