Publishing Web.Config to Azure removes Azure storage connection string - azure

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.

Related

Does Azure Web App support string/token replacement in config files?

I have a Web App that I deploy via YAML pipeline, but would like to see if it can be done via web app's Deployment Center.
I need to transform the IP address and userPrincipalName in the endpoint element, but it does not fall under AppSettings or connectionstring element. Is it possible to transform this kind of element via Web App, or am I stuck with YAML pipeline?
Here is snippet of my config file:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="API_AUTH_MODE" value="2" />
</appSettings>
<system.serviceModel>
<client>
<endpoint address="net.tcp://10.0.0.0:99/App1/Services/Service1"
binding="netTcpBinding" bindingConfiguration="NetTcpBinding_Service1"
contract="Service1" name="NetTcpBinding_Service1">
<identity>
<userPrincipalName value="user#domain.local" />
</identity>
</endpoint>
<endpoint address="net.tcp://10.0.0.0:99/App1/Services/Service2"
binding="netTcpBinding" bindingConfiguration="NetTcpBinding_Service2"
contract="Service2" name="NetTcpBinding_Service2">
<identity>
<userPrincipalName value="user#domain.local" />
</identity>
</endpoint>
</client>
</system.serviceModel>
</configuration>
Is it possible to transform this kind of element via Web App, or am I stuck with YAML pipeline?
AFAIK, I am afraid you could not transform this kind of element via Web App at this mpment.
That because the IP address and userPrincipalName does not fall under AppSettings or connectionstring element.
So, we could not use the Application settings or connection strings to replace it. We have to resolve this issue with YAML pipeline.
BTW, we could use the Replace Tokens in the YAML pipeline to resolve it.
Hope this helps.
While it was answered correctly above - Web App cannot transform anything other than Appsettings or 'connectionstring`, I ended up doing the following:
Use XML Transform files to replace the strings needed, since there is dependency on build type
Use YAML file to access vault to do password replacements.
I could have used Web App to do the password replacements, but it is much easier to manage the pipeline/deployment/release via a single YAML file rather than split YAML and Web App.

Azure Storage connection string How to implement to applicate

I need to create access to the Azure storage from application. Application requires storage, where to put file. This code below, I am trying to put where application requires path to store file. Am I doing right? How can I implement this into XML of Application, so then it starts to write files to cloud storage.
<connectionStrings>
<add name= "DefaultConnection" connectionString="DefaultEndpointsProtocol=https;AccountName=;AccountKey=;/>
</connectionStrings>
Please take a look at this doc for example.
In your app.config, please add:
<appSettings>
<add key="StorageConnectionString" value="DefaultEndpointsProtocol=https;AccountName=account-name;AccountKey=account-key" />
</appSettings>
And in your code, please use:
// Parse the connection string and return a reference to the storage account.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
CloudConfigurationManager.GetSetting("StorageConnectionString"));
Then you can take use of azure storage.
if you login to the Blob image storage on Azure. it should populate the connection string by default. PFB Reference

Azure config - not connection string or app setting

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).

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()

Configure Redis Session State on Azure

I've got the Redis Session State Provider working fine locally with my ASP.Net site and in Azure with my Azure Website. But I've got a question about configuration...
Is there any way to store the configuration for that in the Azure Website itself using the App Settings (or Configuration Strings) section in the Website Properties screen?
That would be very convenient because it would mean that I don't have to modify the web.config file when I publish. I already do this for connection strings and app settings, but I just don't see a way to do that for anything in the <system.web> node of the web.config file, like the <sessionState> node.
There isn't a way to change the behaviour of the provider-based session state from utilising the web.config file.
You could write your own provider and modify where it finds the connection details from so you can publish those details somewhere other than in the web.config, but this wouldn't be standard behaviour.
This question has the way to make this work.
<appSettings>
<add key="REDIS_CONNECTION_STRING" value="[your dev connection string]" />
</appSettings>
<system.web>
<sessionState mode="Custom" customProvider="RedisProvider">
<providers>
<add name="RedisProvider" type="Microsoft.Web.Redis.RedisSessionStateProvider" connectionString="REDIS_CONNECTION_STRING" />
</providers>
</sessionState>
</system.web>
Then, in the portal, you can create an app setting with the name 'REDIS_CONNECTION_STRING' with the correct connection string. You cannot use connection strings section of web.config or azure portal. It must be app settings. Not sure why, but connection strings just uses whatever is in the web.config and is not replaced with what is in the portal.

Resources