Azure config - not connection string or app setting - azure

When deploying a cloud service worker role to Azure, I always set the various connection strings and app settings/configuration settings via the cscfg files and then via the Azure web interface if they need to change at run time, which all works fine.
Is it possible to do something similar for configs which are not connection strings or app settings/configuration settings?
Specifically I have something similar to the following:
<log4net>
<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
<bufferSize value="1" />
<connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<!-- This is the connection string I would like to store in Azure -->
<connectionString value="Server=tcp:azure.sql.server,1433;Database=MyAzureSqlDbName;User ID=my-user-name#my-server;Password=my-password;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;Application Name=log4net" />
<commandText value="INSERT INTO [MyLogTableName] ( [Date], [etc] ) VALUES ( #log_date, etc)" />
<parameter>
<parameterName value="#log_date" />
<dbType value="DateTime" />
<layout type="log4net.Layout.RawTimeStampLayout" />
</parameter>
</appender>
</log4net>
Is there any way of putting that connection string into cscfg files or Azure like my other settings? It's a pain to keep changing it manually in the app.config when I deploy, I keep forgetting (!) which means another re-deploy which is takes 4/5 minutes each time.
I can't use transforms btw as these settings are stored in app.config file of my worker role app and my understanding is that transforms only work with web.config files.

I think the easiest way will be for you to change the settings of the appender at runtime. If you add some logic in your global.asax.cs Application_Start method, you can change the connection string using the CloudConfigurationManager which will then either pull it from the cscfg or the app.config.
Steps would be:
add an appSetting in the app.config to hold the connection string you want to use when running locally
add a setting to your cscfg with the same name as your appSetting to hold the azure db connection string
install the Microsoft.WindowsAzure.ConfigurationManager nuget package if you don't already use it
Add the following code to your global.asax.cs Application_Start:
protected void Application_Start()
{
var hier = (Hierarchy)LogManager.GetRepository();
if (hier != null)
{
var appenders = hier.GetAppenders().OfType<AdoNetAppender>();
foreach (var appender in appenders)
{
appender.ConnectionString =
CloudConfigurationManager.GetSetting(connectionStringKey);
appender.ActivateOptions();
}
}
}
Two helpful links for you:
4 Tips for using Log4NET's ADONetAppender in ASP.NET
Changing Log4net Connection String at Runtime

The cscfg file is just name/value pairs, and is there for you to set any parameters you might need (specifically, ones you would like to be able to set/change without redeploying your app).
But more importantly: The only config file exposed externally is the .cscfg. You cannot arbitrarily access a different config file in the same way. You'd need to modify the config file yourself, based on cscfg changes. Alternatively, you can download your config file from somewhere (e.g. storage blob) on startup. This lets you modify a config, push to blob storage, and have your app download/use the new config (you'd just need to come up with a trigger mechanism to signal your role instances to re-initialize with the new config).

Related

Basic of Azure WebJobs SDK

I would like to know about JobHostConfiguration on Azure WebJobs SDK.
Where I can find the config ? is it on app.config ?
How can JobHostConfiguration identified this is IsDevelopment or not ?
I cannot find it on app.config
What config that JobHostConfiguration read ?
Thank You
Where I can find the config ? is it on app.config ?
Yes, it is in app.config file. You also could add some new configs manually in this file.
How can JobHostConfiguration identified this is IsDevelopment or not ?
It depends on whether the JobHost is running in a Development environment. The default value is false. If you want it to be true, you could add the following code in app.config file to let the JobHost run in a
Development environment. And you could read this article to learn more about this configuration.
<appSettings>
<add key="AzureWebJobsEnv" value="Development"/>
</appSettings>
The result is like this:
What config that JobHostConfiguration read ?
It could read many information of config, such as the connection string of Azure Web Jobs. You could click New Project>Cloud>choose Azure WebJob to create a Web Jobs to try.
Read connection string in app.config file:
<connectionStrings>
<!-- The format of the connection string is "DefaultEndpointsProtocol=https;AccountName=NAME;AccountKey=KEY" -->
<!-- For local execution, the value can be set either in this config file or through environment variables -->
<add name="AzureWebJobsDashboard" connectionString="your storage connection string" />
<add name="AzureWebJobsStorage" connectionString=" your storage connection string " />
</connectionStrings>

How do I enable the cscfg overrides to work with NServiceBus Azure configuration

When using NServiceBus the Transport connection string doesn't seem to be fetched from the applicable Cloud configuration first but immediately from the app.config.
Options I've tried:
Using the configuration section (:
cscfg
<ConfigurationSettings>
<Setting name="AzureServiceBusQueueConfig.ConnectionString" value="Endpoint=sb://xxx.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=yyy" />
</ConfigurationSettings>
app.config
<AzureServiceBusQueueConfig ConnectionString="Endpoint=sb://xxx.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=yyy" />
Using a custom connection string name:
cscfg
<ConfigurationSettings>
<Setting name="NServiceBus.Transport" value="Endpoint=sb://xxx.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=yyy" />
</ConfigurationSettings>
app.config
<connectionStrings>
<add name="NServiceBus.Transport" connectionString="Endpoint=sb://xxx.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=yyy"/>
</connectionStrings>
Also tried to override it by using the following line of code, since this issue is still open (https://github.com/Particular/NServiceBus.AzureServiceBus/issues/20):
configuration.UseTransport<AzureServiceBusTransport>().ConnectionString(CloudConfigurationManager.GetSetting("AzureServiceBusQueueConfig.ConnectionString"));
Or tried to set the connection string name manually, which works again using the app.config but doesn't let the cscfg override.
configuration.UseTransport<AzureServiceBusTransport>().ConnectionStringName("NServiceBus.Transport");
Did you turn the azure configuration source on? You can do so using following extension method on the bus configuration:
.AzureConfigurationSource()

Publishing Web.Config to Azure removes Azure storage connection string

I've got a web.config that contains my SQL connection string and my Azure Blob storage connection string.
A Web.Config transformation replaces my Local SQL connection string with the Azure one.
When I publish the site to Azure, the Blob storage connection string is deleted and replaced with a duplicate SQL connection string, but with the blob storage string's name.
The only way I've found to fix is to log in via FTP and manually change the erroneous Storage connection string with the correct one from my local machine.
How do I get VS to publish my web config to Azure and leave it alone!!!
Web.Config
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\.mdf;Integrated Security=True" providerName="System.Data.SqlClient" />
<add name="StorageConnectionString" connectionString="DefaultEndpointsProtocol=https;AccountName=;AccountKey=" />
</connectionStrings>
Web.Release.Config
<connectionStrings>
<add name="DefaultConnection"
connectionString="Server=.database.windows.net,1433;Database=;User ID=#;Password=!;Trusted_Connection=False;Encrypt=True;Connection Timeout=30;"
providerName="System.Data.SqlClient"
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
I had a similar issue to yours. I'm not sure why but when you define the connection strings in the "Configure tab" in the azure portal and associate a "Linked Resource" on the linked resource tab it may override certain properties in the Web.config transform causing unexpected results. One of the options when you set up a new azure website is linking to (or creating a new) database to associate with your website - thereby automatically assigning the related connection string which may try to override your transform operation defined in the Web.Release.config.
Check and see if removing all connection strings and linked resources inside the "Azure Portal" fixes your problem. Just make sure that you have both your production database and storage connections strings defined properly in the Web.Release.config.
I struggled with this problem this morning and I came up with a solution for VS2015/17.
So I have an Azure VM, and to publish my web app on this machine, I used the Web deploy to an Azure VM proposed by VS.
I put my connection strings in an external file, so the useful part of my web.config looks like this :
</entityFramework>
<connectionStrings configSource="ConnectionStrings.config">
</connectionStrings>
</configuration>
in order to prevent VS of adding some connection strings during publication (ADO.Net code first MSSQL database connection string in my case), you can edit the following file in your project :
...\MyProject\Properties\PublishProfiles\YourPublishProfile - WebDeploy.pubxml
In this file look into the ItemGroup part and edit it to delete the connection strings you don't need:
<PublishDatabaseSettings>
<Objects xmlns="">
<ObjectGroup Name="MyProject.Models.MSSQL_DB" Order="1" Enabled="False">
<Destination Path="" />
<Object Type="DbCodeFirst">
<Source Path="DBContext" DbContext="MyProject.Models.MSSQL_DB, MyProject" Origin="Convention" />
</Object>
</ObjectGroup>
</Objects>
</PublishDatabaseSettings>
</PropertyGroup>
<ItemGroup>
<here are some entries delete the ones you don't need/>
</ItemGroup>
Be careful, if you add a file in this repertory, there is chances that it breaks the publication process on VS. Don't add file, just edit.

DiagnosticMonitorTraceListener not working in Azure

I've got an app that I've deployed with Azure, and I am trying to get plain vanilla Tracing working
I've gone through all of these articles:
https://stackoverflow.com/search?q=diagnosticmonitortracelistener
Here's my role entry point:
public class WebRole :RoleEntryPoint {
public override bool OnStart() {
if (RoleEnvironment.IsAvailable) {
LocalResource localResource = RoleEnvironment.GetLocalResource("MyCustomLogs");
DirectoryConfiguration dirConfig = new DirectoryConfiguration();
dirConfig.Container = "diagnostics-mycustomlogs-container";
dirConfig.DirectoryQuotaInMB = localResource.MaximumSizeInMegabytes;
dirConfig.Path = localResource.RootPath;
DiagnosticMonitorConfiguration diagMonitorConfig = DiagnosticMonitor.GetDefaultInitialConfiguration();
diagMonitorConfig.Directories.ScheduledTransferPeriod = TimeSpan.FromMinutes(1.0);
diagMonitorConfig.Directories.DataSources.Add(dirConfig);
DiagnosticMonitor diagMonitor = DiagnosticMonitor.Start("Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString", diagMonitorConfig);
Trace.Listeners.Add(new Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener());
Trace.AutoFlush = true;
Trace.WriteLine("Role Starting");
}
return base.OnStart();
}
}
Also put the trace listener in global.asax.cs:
if (RoleEnvironment.IsAvailable) {
Trace.Listeners.Add(new Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener());
Trace.AutoFlush = true;
}
I've also tried just pasting it directly into web.config
<trace>
<add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener,
Microsoft.WindowsAzure.Diagnostics,
Version=1.8.0.0,
Culture=neutral,
PublicKeyToken=31bf3856ad364e35"
name="AzureDiagnostics">
<filter type="" />
</add>
This directory gets created in my Azure VM
C:\Resources\Directory\d63aeab4198d458a9c0b1d0f818e4054.CorpQna.Web.MyCustomLogs
This is in my ServiceDefinition.csdef file:
<LocalResources>
<LocalStorage name="MyCustomLogs" cleanOnRoleRecycle="false" sizeInMB="10" />
</LocalResources>
When I add a TextWriterTraceListener in my local Compute Emulator, it works:
<trace autoflush="true">
<listeners>
<add type="System.Diagnostics.TextWriterTraceListener" name="TextWriter"
initializeData="c:\trace.log" />
</listeners>
</trace>
However, this does not work on Azure. (I suspect permissions?)
I'm at a standstill at this point. No errors anywhere, but no logs either. There's no record of the Blob being created in my Blob Store.
Doug, you are confusing a few different concepts here:
Diagnostics Tracing to a file
Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener
WAD DirectoryConfiguration
In .NET, diagnostics tracing will write to all of the registered listeners. The Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener is a trace listener which essentially writes to the WADLogsTable table in Azure Storage. Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener does not write to a local file such as your MyCustomLogs folder. The WAD DirectoryConfiguration will upload files, but this really doesn't have anything to do with .NET diagnostics tracing, unless you are also adding a TextWriterTraceListener.
So your code as-is probably works fine, but you are looking in the wrong place for the data. It won't be in a blob coming from the MyCustomLogs folder, but rather in the WADLogsTable table. If you want the tracing to also be in the MyCustomLogs folder then you can add another listener of type TextWriterTraceListener pointing to a file in your MyCustomLogs folder.
Have you checked that in your service configuration, you are using correct storage account for diagnostic.
By default, it is pointing to local dev storage. you may have to change with valid storage account.
<Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="UseDevelopmentStorage=true" />

Set the application ConnectionString in the Service Configuration instead of web.config in Azure

I have an application currently in Azure and whenever we push it into the Staging segment, we cannot truly test since the connection string is pointing to the prod database.
Someone mentioned to me that you should be able to set the connection string in the ServiceConfiguration.cscfg file instead (or with) the web.config file. That way you can change the connection string in the Azure portal instead of republishing a who app.
Does anyone know how to do this?
In your ServiceConfiguration.cscfg file add:
<ServiceConfiguration ... />
<Role ... />
<ConfigurationSettings>
<Setting name="DatabaseConnectionString" value="put your connection string here" />
</ConfigurationSettings>
</Role>
</ServiceConfiguration>
Now you have a connection string you can change by editing the configuration inside the azure portal.
Then anytime you need to retrieve the connection string you can do it using:
using Microsoft.WindowsAzure.ServiceRuntime;
...
String connString = RoleEnvironment.GetConfigurationSettingValue("DatabaseConnectionString")
You may need to add Microsoft.WindowsAzure.ServiceRuntime.dll to your references.
RoleEnviroment.IsAvailable can be used to test if your are running in Azure, and if not to fall back to your web.config settings.
using System.Configuration;
using Microsoft.WindowsAzure.ServiceRuntime;
...
if (RoleEnvironment.IsAvailable)
{
return RoleEnvironment.GetConfigurationSettingValue("DatabaseConnectionString");
}
else
{
return ConfigurationManager.ConnectionStrings["DatabaseConnectionString"].ConnectionString;
}
This article has a more verbose explanation of the above.
For Entity Framework, you do not need to provide a providerName, it's already inside in the connectionstring. The reason why it does not work when it's in azure settings is, it contains &quot symbol which needs to be transalated back to " before creating a new EntityConnection. You can do it using HttpUtility.HtmlDecode in System.Web.
Basically you need to define these setting in Azure service configuration file. Check here. Once defined these can be changed from Azure portal.

Resources