web deploy parameters.xml settings not making their way into the web.config file - asp.net

I've created a parameters.xml and verified that the xpath works with an online tool http://www.xpathtester.com/
<?xml version="1.0" encoding="utf-8" ?>
<parameters>
<parameter name="Website URL" description="Please provide the base web address for the external part of the application" defaultValue="https://someOtherSite.com">
<paramterEntry kind="XmlFile" scope="\\web.config$" match="/configuration/appSettings/add[#key='ExternalSiteBaseUrl']/#value" />
</parameter>
<parameter name="Authentication Service URL" description="Please provide the web address for the authentication service" defaultValue="http://someOtherSite.com/auth">
<paramterEntry kind="XmlFile" scope="\\web.config$" match="/configuration/appSettings/add[#key='AuthServiceAddress']/#value" />
</parameter>
</parameters>
When I import the zip file through IIS I get to the settings page with the connection strings, and these two options appear as expected. No matter what I set the values to though, they're just ignored. The value that is in the web.config remains unchanged. The connection string changes however are applied. In the summary that pops up afterwards there are a couple of lines saying that the connection strings were in scope, but there is nothing related to these two values. Is there a step I'm missing?

So the magic answer is that the scope declared here will find the first web.config which just happened to be an area in my MVC site. Because the parameter didn't exist there it was skipping and carrying on as normal

Related

How to transform mailSettings in web.config, without having credentials in source control

I have a web app that I deploy to an Azure App Service, using VSTS. So far, I have managed to successfully use config transforms and variable substitutions to be able to not have any sensitive information in source control, but I can't get my head around how to do it for the smtp credentials in system.net/mailSettings/smtp/network.
Anyone have any ideas?
OK, after digging a bit, and asking around, it seems as using WebDeploy and parameters.xml is working.
This is what I did:
I added the addon Replace Tokens to my VSTS account.
I added a parameters.xml to my web site project, and it looks like this:
<?xml version="1.0" encoding="utf-8"?>
<parameters>
<parameter name="Mail.Username" description="The username used for smtp authentication" defaultValue="#{Mail.UserName}#" tags="">
<parameterEntry kind="XmlFile" scope="obj\\Release\\Package\\PackageTmp\\Web\.config$" match="/configuration/system.net/mailSettings/smtp/network/#userName" />
</parameter>
<parameter name="Mail.Password" description="The password used for smtp authentication" defaultValue="#{Mail.Password}#" tags="">
<parameterEntry kind="XmlFile" scope="obj\\Release\\Package\\PackageTmp\\Web\.config$" match="/configuration/system.net/mailSettings/smtp/network/#password" />
</parameter>
</parameters>
My build step was already set to output a package, but these are the MSBuild parameters needed for the build step. /p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /p:PackageLocation=”$(build.artifactstagingdirectory)\\” if you, like me, are doing config transforms of connection strings, you might want to add /p:AutoParameterizationWebConfigConnectionStrings=false to that list of parameters as well.
In the Release Configuration, before the Deploy to Azure App Service step, add a step using the afore mentioned Replace Tokens addon. I stuck with the default syntax for replacement values, but those could be changed. Since I'm using all default values, I run the task in Root directory $(System.DefaultWorkingDirectory)/$(Build.DefinitionName)/drop and Target files *.SetParameters.xml
Then in the Deploy to Azure App Service step I selected the option Publish using Web Deploy and for the SetParameters file I used $(System.DefaultWorkingDirectory)/$(Build.DefinitionName)/drop/<Name of Web Project>.SetParameters.xml
Under Post Deployment Action, set Deployment script type to Inline script, and add the following script.
#echo off
del parameters.xml
This is because .config files aren't served by default, but .xml files are, and otherwise your parameters.xml would sit in your web root unprotected, with your smtp username and password in plain text.
Next add Release Variables named Mail.Username and Mail.Password, and fill in their values. I made Mail.Password a secret.
Check in everything, and trigger a build and release!

Using VSTS web transformations with third party web services

I am trying to implement the web transformations in VSTS. Is there a way to add third party web services to my parameters and setparameters xml files?
You can add elements to config file through parameters.xml:
Config xml file:
<books>
<book name="book1" author="author1" />
<book name="book2" author="author2" />
</books>
parameters.xml:
<parameters>
<parameter name="MyTestParam" description="My Test Param" defaultValue="<price />">
<parameterEntry kind="XmlFile" scope="books\.xml" match="//book[#name='book1']" />
</parameter>
</parameters>
Then it will add new price element after transforming.
Related articles: Web Deploy XML File Parameterization
Use Web Deploy Parameters in a Web Deployment Package

Overriding other parts of the web.config rather than the appSettings and connectionString when deploying web apps to Azure

When deploying web apps to Azure you can override the connection strings and app settings by setting these in the portal for the particular web app you are deploying. Is there any way you can override other parts of the web.config from the portal. I am using a plugin for the Umbraco CMS that requires connection strings in the web.config that are not in the appSetting section of the file. (they usually hold them in another file, but I have placed them in the web.config so I can hopefully set them from the portal)
Here is a sample of the configuration section of the web.config with only the relevant section I am referring to:
<configuration>
...A lot of other web.config stuff
<imageProcessor>
<caching currentCache="AzureBlobCache">
<caches>
<cache name="AzureBlobCache" type="ImageProcessor.Web.Plugins.AzureBlobCache.AzureBlobCache, ImageProcessor.Web.Plugins.AzureBlobCache" maxDays="365">
<settings>
<!--Azure Cache Provider-->
<setting key="CachedStorageAccount" value="Azure blob storage key" />
<setting key="CachedBlobContainer" value="cache" />
<setting key="UseCachedContainerInUrl" value="false" />
<setting key="CachedCDNRoot" value="Azure storage account" />
<setting key="CachedCDNTimeout" value="1000" />
<setting key="SourceStorageAccount" value="name=Azure storage account" />
<setting key="SourceBlobContainer" value="media" />
<setting key="StreamCachedImage" value="false" />
</settings>
</cache>
</caches>
</caching>
</imageProcessor>
</configuration>
What I would like to do is set the setting keys in the cache section above. If I am not able to refer directly to this section in the Azure portals appSettings section then can I put these settings in the appSettings section of the web.config as keys and refer to them from this section of the web.config file?
I know I can use web.config transforms to achieve this but this will still require me to check the connection strings into source control under web.config.release etc and I would prefer not to do this.
Is there another solution that I am overlooking that will perform the tasks I want? (The solution is hosted in VSTS so I could always add another build step with the settings keys there) That way they would end up associated with the build configuration rather than in source control.
You can add PowerShell Script as one of the steps in your build definition. If you use inline script option you don't need to have this script in your repo.
Script can look like this (I added a correct XPath as stated in your example).
$path = ".\web.config"
$xml = [xml](Get-Content $path)
$dictionary = #{
CachedCDNTimeout = '9000'
}
foreach ($key in $dictionary.Keys)
{
if (($addKey = $xml.SelectSingleNode("//configuration/imageProcessor/caching/caches/cache/settings/setting[#key = '$key']")))
{
$addKey.SetAttribute('value', $dictionary[$key])
}
}
$xml.Save($path)
(I've tested it only locally)

How to specify IIS Web Application Name in Parameters.xml used with MSDeploy

I have found out how to set the application pool and default value
<parameter name="applicationPool" defaultValue="MyDefaultValue" >
<parameterEntry kind="DeploymentObjectAttribute" scope="application"
match="application/#applicationPool" />
</parameter>
Does anyone know how to set the "IIS Web Application Name"? It gets generated in the SetParameters.xml file as
<setParameter name="IIS Web Application Name" value="Default Web Site/MySite_deploy" />
I can overwrite the SetParameters.xml file, but I would rather set it up in the Parameters.xml file, but I can't find the parameterEntry type.
Thanks
You should be able to override the default value stored in the package by defining a DeployIisAppPath property when you generate the package
Alternatively, you can declare DisableAllVSGeneratedMSDeployParameter=true and Visual Studio will no longer automatically generate any parameters for you, you'll have to declare them all yourself.
If you're declaring the web site parameter yourself, the kind will be ProviderPath. The scope will either be iisApp or contentPath depending on what provider is being used. Tear open a package and look in the archive.xml file, the value will be an immediate child of the root manifest element.

How to create generic web.config file for different web servers in .net web application?

I want to create a generic web.config file for different web servers in VB.NET. So, depending on the server configuration requirements, applications can retrieve all values from that generic configuration file.
Is this possible? How would I do this?
This is just a random idea, it may not fit your needs though. You could create a configuration section for each server named by the name of the server. Create a helper class for reading configuration values that checks for any values in the section named after the server's name first, if it doesn't exist read it from a default configuration section.
I'm still not sure if this would be a wise decision, its just an option.
Technically, there's the machine.config which includes settings that apply to the entire machine.
web.config files can override some settings from it.
For everything that stays the same, use the a single web.config.
For everything that changes, use a reference to an external file.
<configuration>
<appSettings file="ExternalWeb.config">
<add key="MyKey" value="MyValue" />
</appSettings>
...
</configuration>
http://www.devx.com/vb2themax/Tip/18880
This way when things change in the main web.config, few things must be updated.
You may also consider using templates and code generation techniques to generate a web.config for each server.
How about a "mode" appsetting key/value. This "mode" can be set to "dev", "testing", "prod", etc. Then, set the mode of the current configuration file and prefix all the settings that would change with the mode.
Example:
<add key="mode" value="test" /> <!-- possible values: dev, test, prod -->
<add key="dev.dbconnstr" value="data source=DB;userid=ABC;password=DEF" />
<add key="test.dbconnstr" value="data source=DB;userid=ABC;password=DEF" />
<add key="prod.dbconnstr" value="data source=DB;userid=###;password=###" />
Then, use a configuration class to read the setting depending on the mode.
Example:
mode = ConfigurationManager.AppSettings("mode");
CongifurationManager.AppSettings(mode + ".dbconnstr");
Doing it this way, you can have the same config file deployed to all servers, and never have to worry about tweaking each server (except of course updating the "mode" value when deploying). I would also recommend not saving the production credentials in the other configuration files, instead replace it with a placeholder.
You could create a deployment script in something like nant which loads in a web.config containing placeholders for the configuration options. This could then replace the placeholders for the appropriate environments.

Resources