How to specify IIS Web Application Name in Parameters.xml used with MSDeploy - 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.

Related

How to get web.config transformation to include external secrets file?

Is there a way to get a web.config transformation in Visual Studio 2015+ to include the contents of an externally-referenced secrets file as described here?
This works well when developing locally, and doesn't include the file in source control, but when I go to deploy the web app to the server, I want it to include the username and password for another web service which it connects to. If I enter the settings manually in IIS on the server, they are lost each time I publish the app.
If I omit the keys in the appSettings block in my web.config (so that they are only referred to in the secrets file), the manually-entered settings in IIS on the server are removed completely whenever I publish the app.
Being able to refer to certain things in an external file for the sake of better security and not checking in passwords to source control isn't turning out to be a very good idea IMHO because my deployment is now a nightmare. I don't want to manually enter the passwords in the web.config file on the server after every deployment.
I'd rather not look into encryption, either, because I would have to do that for each server I deploy to so that the relevant machine key is used for each web.config file.
I've only recently thought about removing this password from source control, in response to a recent push to improve security practises at work - which I well understand and agree with - but I can also see why security is so poorly considered because the life of the ordinary developer becomes extremely unpleasant if there the tools available don't make it easy.
Surely there's a way without resorting to encryption?
Thanks.
Without a CI system I think your best option is probably a pre/post build action that executes a script?
I'd suggest you replace the actual values with tokens for your sensitive web.config values (something unique/easy to find like MY_PRODUCT_DATABASE_PASSWORD etc). Your web.config can then be checked into source control safely.
In VS you can add a build action to run a custom powershell or exe to basically perform a find-and-replace on the tokens with actual values before you zip & deploy as normal.
Exactly how/where you store the real values and how the script works is up to you. you could easily find a file on your deployment machine or a row in some database based on data passed to the script/exe from vs or from data within web.config itself (or embedded as a comment in web.config even).
Here's details of the variables available from vs you could pass to your exe or script in a build action: https://msdn.microsoft.com/en-us/library/42x5kfw4.aspx
It you wanted to use PowerShell you could read/replace/write values to a web.config(or any text file) like this answer: How can I replace every occurrence of a String in a file with PowerShell?
Following the Microsoft Docs example you've linked to, putting this XDT transformation inside Web.Release.config should do the trick:
<appSettings file="..\..\AppSettingsSecrets.config" xdt:Transform="SetAttributes">
<add key="mailAccount" xdt:Locator="Match(key)" xdt:Transform="Remove" />
<add key="mailPassword" xdt:Locator="Match(key)" xdt:Transform="Remove" />
<add key="TwilioSid" xdt:Locator="Match(key)" xdt:Transform="Remove" />
<add key="TwilioToken" xdt:Locator="Match(key)" xdt:Transform="Remove" />
<add key="TwilioFromPhone" xdt:Locator="Match(key)" xdt:Transform="Remove" />
<add key="GoogClientID" xdt:Locator="Match(key)" xdt:Transform="Remove" />
<add key="GoogClientSecret" xdt:Locator="Match(key)" xdt:Transform="Remove" />
</appSettings>
You dont need xdt:Locator attribute on <appSettings> element itself, because there is only one appSettings.
Edit: I've misunderstood the original question. The goal is to include contents of referenced file, which is not possible using XDT. There has to be another way.

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!

Build .Net Web application based on environment

There are 3 environments through which my .Net web application goes namely Development, Release and Production with each having their own config and project setting files.
Assuming that the setting and config files for different environments are in one system, I want to create a small script or an application where the developer just mentions the environment type and the related setting and config files get loaded and then the application builds.
Can anyone guide me on this?
You can create config transforms and use them in publish profiles. For each configuration (Debug, Release, YourOwnConfig ...) there will be a file named by its configuration (Web.Debug.config, Web.Release.Config, Web.YourOwn.Config, ...)
The trick is that you have one complete config file, the original Web.Config, and the transforms just mention the differences to this file via XSLT transform syntax (once you create a new transform, there will be some examples in the file itself showing the syntax). For example, adding a transform for an appSettings key looks like:
<configuration>
<appSettings>
<add key="ClientSessionTimeout" value="100"
xdt:Transform="SetAttributes" xdt:Locator="Match(key)" />
</appSettings>
</configuration>
That example will replace an existing ClientSessionTimeout setting by the one specified (with value="100"). Notice how the xdt:locator specifies that the key attribute will be used to localize the setting, and xdt:Transform specifies that the attributes mentioned (here: value) will be set.
If you have applicationSettings, you need to replace the setting itself:
<applicationSettings>
<WebApplication2.Properties.Settings>
<setting name="Setting" serializeAs="String"
xdt:Transform="Replace" xdt:Locator="Match(key)">
<value>Some value</value>
</setting>
</WebApplication2.Properties.Settings>
</applicationSettings>
The differences will be for example the data source settings, other environment specific settings such as URLs to web services etc.
To create those, select a configuration such as "Debug", then right-click on the Web.Config file and you will see a context menu item "Add config transform" - click it and the Web.Debug.Config transform file will be created underneath the Web.Config. Adapt it as mentioned before; copy the entire key or setting to the transform file, then add the appropriate xdt attributes as shown above.
Finally, you can use the "Publish" function (Right-Click on the web prroject to select it). A wizard opens where you can set up a publish profile. There you can mention a configuration - like "Debug", "Release", and the ones you've created earlier.
A file publish will put the files together needed to deploy the web project and additionally perform the transformation of the Web.Config by applying the appropriate transform file (e.g. Web.Release.Config). The published config will be named "Web.Config" and contains all changes.
For trouble-shooting, and to find out more about the topic, I recommend the following links:
asp net web application: add config transform grayed out
web.config transform not working
Notice also the side-bar of Stack overflow showing more related links.

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.

Changing web.config file based on an Environment Variable in ASP.NET

I need to change my connection string in the web.config file based on an environment variable (for different enviornments, like dev/staging/production, etc). I have seen other solutions that use build tasks to accomplish changing different configurations, but haven't been able to find something that will let me change my connection string based on an environment variable. Does anyone know of any way to do this?
We make use of the configSource attribute for the appSettings and connectionStrings elements in the web.config.
Basically, we have the same web.config file for all of our environments: dev, qa and production.
Then we utilize seperate "environment specific" files.. For example...
In web.config:
<?xml version="1.0"?>
<configuration>
<appSettings configSource="local.appsettings.config" />
<connectionStrings configSource="local.connectionstrings.config" />
</configuration>
Then we maintain the following files:
local.appsettings.config.development
local.appsettings.config.qa
local.appsettings.config.production
local.connectionstrings.config.development
local.connectionstrings.config.qa
local.connectionstrings.config.production
Since we pre-compile all of our asp.net applications before deployment, we've got a custom msBuild task utilized by our CI solution that copies the right configuration files (based on the target environment) to the proper .config file...
So, if we are deploying to dev, local.appsettings.config.development -> local.appsettings.config
If we are deploying to qa, local.appsettings.config.qa -> local.appsettings.config
This allows us to keep the core web.config the same across all of our environments.
How about having two connection strings and another variable, like "isTesting" in your web.config, then based on the value of isTesting pick which connection string to use?
you can also use config sections, and based upon server name switch between sections. this way you can have keys named the same.
link text
You can set a web.config for each environment in the configuration manager using prebuild events. I have tried this with excellent results.
http://www.hanselman.com/blog/ManagingMultipleConfigurationFileEnvironmentsWithPreBuildEvents.aspx
When you have debug and build you can have local/preproduction/production... etc

Resources