web.config transform - delete comments from connectionstring section - c#

I store several different connection strings in my web.config for development and testing. All but one is commented out so I can change info as needed.
When I publish, I would like to replace everything (including comments) in the connectionStrings node with this:
<add name="myDb" connectionString="Data Source={SERVER};Initial Catalog=ManEx;User Id={USER};Password={PASSWORD};" providerName="System.Data.SqlClient" />
<!--<add name="myDb" connectionString="Data Source={SERVER};Initial Catalog=ManEx;Integrated Security=True" providerName="System.Data.SqlClient" />-->
I know how to change the active string with this:
<add name="myDb"
connectionString="Data Source={SERVER};Initial Catalog=ManEx;User Id={USER};Password={PASSWORD};"
providerName="System.Data.SqlClient"
xdt:Transform="Add"
xdt:Locator="Match(name)"/>
But I don't know how to clear out the comments I don't want and add the comment I do want.
Any ideas?

Instead of transforming the string, or using "Remove" and "Insert" clean the section try using "Replace".
For example:
<connectionStrings xdt:Transform="Replace">
<add name="myDb"
connectionString="Data Source={SERVER};Initial Catalog=ManEx;User Id={USER};Password={PASSWORD};"
providerName="System.Data.SqlClient" />
</connectionStrings>
You can configure this section exactly how you want it, even if that means you add new comments.

What I did based on this answer was the following:
Removed the existing connectStrings section in Web.config which contains commented out connection strings used during debug time;
Re-added the connectionStrings section with the correct connection string to be used when the app is deployed.
So in your Web.config transform file you have something like this:
<!-- Removes the existing connectionStrings section which contains internal connection strings used for debugging -->
<connectionStrings xdt:Transform="Remove">
</connectionStrings>
<!-- Re-adding the existing connectionStrings section -->
<connectionStrings xdt:Transform="Insert">
<add name="MyConnectionStringName" connectionString="Data Source=CLUSTERSQL;Initial Catalog=MyDatabase;Integrated Security=True;multipleactiveresultsets=True" providerName="System.Data.SqlClient" xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
</connectionStrings>

In Visual Studio 2013, you can have several Web.config files.
Also, when you create a new project, VS creates 2 for you : Web.Debug.config and Web.Release.config. That way, you can have a different Web.Config for your debug project and for your release project

If you need to Add/Insert/Setattributes inside a replaced connectionstring (for example if you use deployments) you can nest the transformations to remove the comments and replace the attributes:
<connectionStrings xdt:Transform="Replace">
<add name="connectionDatabase"
connectionString="#{ConnectionString}"
xdt:Transform="SetAttributes"
xdt:Locator="Match(name)" />
</connectionStrings>

Related

Multiple Groups of ConnectionStrings in App Config

Using ConnectionStrings in App.config, is it possible to have multiple groups/sections of connectionstrings? Some way to delineate between one set of connections and another. Either something like;
<configuration>
<connectionStrings>
<clear />
<add name="ConA" connectionString="Data Source=..."
<add name="ConB" connectionString="Data Source=..."
</connectionStrings>
<otherConnectionStrings>
<clear />
<add name="ConC" connectionString="Data Source=..."
<add name="ConD" connectionString="Data Source=..."
</otherConnectionStrings>
</configuration>
OR
<configuration>
<connectionStrings>
<clear />
<add name="ConA" Group="1" connectionString="Data Source=..."
<add name="ConB" Group="1" connectionString="Data Source=..."
<add name="ConC" Group="2" connectionString="Data Source=..."
<add name="ConD" Group="2" connectionString="Data Source=..."
</connectionStrings>
</configuration>
I know there are <configSections> which you can use to split up the config file, but I want to use ConnectionStringSettingsCollection settings = ConfigurationManager.ConnectionStrings; to access the connectionStrings if possible.
NEED
I have two dropdown boxes. One is populated with a list of possible connectionStrings. Selecting an option will populate the second dropdown with a sublist of the remaining connectionStrings based on the option selected in dropdown 1. How would you cleanly populate both? Perhaps I'll just need to create connectionStringName lists in code for each group of connections I could potentially need and have all my connections in a the single section in my config?
Thanks for the comments. It seems having separate connectionStrings sections isn't possible. In order to hold onto that functionality for all my connections I conceded to having them all together but prefixing their names based on the grouping (as per #Igor's suggestion), then in code using Linq to select only the connections I needed.
Note: In order to use Linq on ConnectionStringSettingsCollection you need to .Cast<ConnectionStringSettings>() as per; https://stackoverflow.com/a/26419656/1365650

EF code-first to create local database in ASP.NET MVC and C#

I am new to ASP.NET MVC. While going through this tutorial https://learn.microsoft.com/en-us/aspnet/mvc/overview/getting-started/getting-started-with-ef-using-mvc/creating-an-entity-framework-data-model-for-an-asp-net-mvc-application
I am getting error
CREATE FILE encountered operating system error 123 (the filename, directory name, or volume label syntax is incorrect.) while attempting to open or create the physical file 'C:\Users\AMIT & AKASH\ContosoUniversity2 AttachDBFilename=|DataDirectory|_ContosoUniversity2.mdf.mdf'.
CREATE DATABASE failed. Some file names listed could not be created. Check related errors.
My connection string
<connectionStrings>
<add name="SchoolContext"
connectionString="Data Source=(LocalDb)\v12.0;Initial Catalog=ContosoUniversity2 AttachDBFilename=|DataDirectory|\ContosoUniversity2.mdf;Integrated Security=SSPI;"
providerName="System.Data.SqlClient" />
</connectionStrings>
SchoolInitializer.cs
StudentContext.cs
You most likely just forgot a semicolon after specifying the initial catalog:
<connectionStrings>
<add name="SchoolContext"
connectionString="Data Source=(LocalDb)\v12.0;Initial Catalog=ContosoUniversity2;AttachDBFilename=|DataDirectory|\ContosoUniversity2.mdf;Integrated Security=SSPI;"
providerName="System.Data.SqlClient" />
</connectionStrings>
So change:
Initial Catalog=ContosoUniversity2
to
Initial Catalog=ContosoUniversity2;
^
|
add this semicolon!

Web.config transform not transforming VS 2017

I have literally uncommented the boilerplate code and tried to publish to the file system to check if the "transform" works.
However, it does not transform the web.config file. I have look at the some articles and answers on here but cannot get it to work.
Things I tried:
Removing the namespace from the configuration node(complains about xdt missing)
Creating a new transform file(production)
Creating a new configuration(production)
Here is the web.Release.config:
<?xml version="1.0"?>
<!-- For more information on using Web.config transformation visit https://go.microsoft.com/fwlink/?LinkId=301874 -->
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<!--
In the example below, the "SetAttributes" transform will change the value of
"connectionString" to use "ReleaseSQLServer" only when the "Match" locator
finds an attribute "name" that has a value of "MyDB".
<connectionStrings>
<add name="MyDB"
connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True"
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
</connectionStrings>
-->
<connectionStrings>
<add name="MyDB"
connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True"
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
</connectionStrings>
<system.web>
<compilation xdt:Transform="RemoveAttributes(debug)" />
<!--
In the example below, the "Replace" transform will replace the entire
<customErrors> section of your Web.config file.
Note that because there is only one customErrors section under the
<system.web> node, there is no need to use the "xdt:Locator" attribute.
<customErrors defaultRedirect="GenericError.htm"
mode="RemoteOnly" xdt:Transform="Replace">
<error statusCode="500" redirect="InternalError.htm"/>
</customErrors>
-->
</system.web>
</configuration>
I get the following error:
No element in the source document matches '/configuration/connectionStrings/add[#name='MyDB']'
But as you can see it is present in the add node.
Any suggestions what to do? I am confused why it isn't working.
Edit:
web.config connection string
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=.\SQLExpress;database=smartDB;Integrated Security=True" providerName="System.Data.SqlClient" />
</connectionStrings>
The value of the name attribute needs to match between your web.config and web.release.config, since you are specifying Match(name) in the transformation config.
In your web.config you have: name="DefaultConnection"
In your web.release.config: name="MyDB"

Entity Framework unable to find connection string in nested web.config

I'm new to .NET, but I'm using EntityFramework 5.0 and .NET 4.5
I have a website where the connectionStrings in the web.config are maintained in a configSource as follows:
<connectionStrings configSource="ConfigOverrides\overrideConnectionStrings.config">
</connectionStrings>
My website has modules with nested web.config files. These modules specify their own connectionStrings in the nested web.config. Everything was fine until I put a System.Data.EntityClient connection in my ConfigOverrides\overrideConnectionStrings file. After I did this I would get an error from the module:
No connection string named 'WebsiteEntities' could be found in the application config file.
If I copy the module's connectionString to the one in ConfigOverrides I get an error that there is already a connection string with that name. If I remove the connection string from their nested web.config and just put it in my overrides, it works. However I'm not wanting to maintain all module's connectionSettings in that global override.
Contents of overrideConnectionStrings.config:
<connectionStrings>
<add name="SqlServices" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=my_db;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\my_db.mdf;" />
<add name="TermsEntities" providerName="System.Data.EntityClient" connectionString="metadata=res://*/Terms.csdl|res://*/Terms.ssdl|res://*/Terms.msl;provider=System.Data.SqlClient;provider connection string='data source=(LocalDb)\v11.0;Initial Catalog=my_db;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\my_db.mdf;connect timeout=30;MultipleActiveResultSets=True;App=EntityFramework'" />
<add name="ADServer" connectionString="LDAP://ldap.localdomain:389/DC=company,DC=com" />
</connectionStrings>
Contents of module's nested Web.config connectionStrings:
<connectionStrings>
<add name="WebsiteEntities" connectionString="metadata=res://*/WSE.csdl|res://*/WSE.ssdl|res://*/WSE.msl;provider=System.Data.SqlClient;provider connection string="data source=.;initial catalog=WSE_DB;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
<add name="RoutingConn" providerName="System.Data.SqlClient" connectionString="data source=.;initial catalog=WSE_DB;integrated security=True;" />
</connectionStrings>
I should note that the module worked fine until I added my TermsEntities to the main site's web.config (via the ConfigOverrides).
I am still unable to figure out what in my application setup is causing the connectionString to not be found. While debugging I could view the connectionStrings available to the path of the request and I would see all connectionStrings (those in the nested web.config and those in the root web.config).
My workaround is to just use the ConfigurationManager from System.Configuration and read in the connection string :
public partial class WebsiteEntities : DbContext
{
public WebsiteEntities()
: base(ConfigurationManager.ConnectionStrings["WebsiteEntities"].ConnectionString ?? "name=WebsiteEntities")
{
}
...
This seems to be working.

How to declare a variable in the app.config file?

I am working on a Windows application.
I have a form with labels like
HOST:
UserName:
Password:
How I can declare the connection string in the app.config file so that it takes the initial catalog, userID and password as variables that I can use in further to check the user whether which database the user wants to get connected with the entered userID and password.
I am using SQL Server 2008 and Visual C# 2008 Express Edition.
As I'm reading your question, you want to have a generic connection string that you want to inject username/password variables into. To do that you would need to have a key with this format:
<add name="myDBKey" connectionString="Data Source=myDB;Initial Catalog={0};Persist Security Info=True;User ID={1};Password={2}" providerName="System.Data.SqlClient"/>
Then in your code, you would need to have these variables declared and assigned, and then use String.Format to complete it.
string dbCatalog = "myCatalog";
string dbUser = "myUser";
string dbPW = "myPW";
string myDBConnectionString = String.Format(
ConfigurationManager.ConnectionStrings["myDBKey"].ConnectionString,
dbCatalog, dbUser, dbPW);
This will inject your variables into the string.
There is a <connectionString> section to the app.config file.
<connectionStrings>
<add name="MyDatabase" connectionString="Data Source=sqlserver,1433;Network Library=DBMSSOCN;Initial Catalog=MyDatabase;User ID=xxx;Password=xxxx;" />
</connectionStrings>
For your Host, User ID and Password, you can define these in the <appSettings> section.
Try this
<connectionStrings>
<add name="ConString" connectionString="Server=Servernae;Database=DBName;User Id=username;password=yourpassword"/>
</connectionStrings>
For more information try Connection Strings
Start by declaring the variables by going to your project's property tab, then going to the Settings tab (on the left), declaring your variables by mentioning the name, default value, and scope (which will be Application).
In your code, to fetch the values:
using System.Configuration;
//....
ConfigurationSettings.AppSettings["ConnectionString"].ToString();
// or
ConfigurationSettings.AppSettings.ConnectionString;
Please note that you can't change the value in code for an Application setting.
EDIT:
Alternately, there is also the connectionStrings node which can be set (but it must be done in the app.config file itself. See MSDN for documentation.
Example of XML:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<connectionStrings>
<add name="ConnStr1" connectionString="LocalSqlServer: data source=127.0.0.1 Integrated Security=SSPI;Initial Catalog=aspnetdb"
providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>
In C#, you will get a System.Coonfiguration.ConnectionStrings, which is a collection of ConnectionStringSettings.
Example of usage in C# code: http://msdn.microsoft.com/en-us/library/system.configuration.configurationmanager.connectionstrings.aspx
You can do some thing like this,
<appSettings>
<add key="SettingName" value="SettingValue" />
</appSettings>
or go to "Variables within app.config/web.config".
My library Expansive is designed with this as a primary use-case.
Moderate Example (using AppSettings as default source for token expansion)
In app.config:
<configuration>
<appSettings>
<add key="Domain" value="mycompany.com"/>
<add key="ServerName" value="db01.{Domain}"/>
</appSettings>
<connectionStrings>
<add name="Default" connectionString="server={ServerName};uid=uid;pwd=pwd;Initial Catalog=master;" provider="System.Data.SqlClient" />
</connectionStrings>
</configuration>
Use the .Expand() extension method on the string to be expanded:
var connectionString = ConfigurationManager.ConnectionStrings["Default"].ConnectionString;
connectionString.Expand() // returns "server=db01.mycompany.com;uid=uid;pwd=pwd;Initial Catalog=master;"
or
Use the Dynamic ConfigurationManager wrapper "Config" as follows (Explicit call to Expand() not necessary):
var serverName = Config.AppSettings.ServerName;
// returns "db01.mycompany.com"
var connectionString = Config.ConnectionStrings.Default;
// returns "server=db01.mycompany.com;uid=uid;pwd=pwd;Initial Catalog=master;"
Advanced Example 1 (using AppSettings as default source for token expansion)
In app.config:
<configuration>
<appSettings>
<add key="Environment" value="dev"/>
<add key="Domain" value="mycompany.com"/>
<add key="UserId" value="uid"/>
<add key="Password" value="pwd"/>
<add key="ServerName" value="db01-{Environment}.{Domain}"/>
<add key="ReportPath" value="\\{ServerName}\SomeFileShare"/>
</appSettings>
<connectionStrings>
<add name="Default" connectionString="server={ServerName};uid={UserId};pwd={Password};Initial Catalog=master;" provider="System.Data.SqlClient" />
</connectionStrings>
</configuration>
Use the .Expand() extension method on the string to be expanded:
var connectionString = ConfigurationManager.ConnectionStrings["Default"].ConnectionString;
connectionString.Expand() // returns "server=db01-dev.mycompany.com;uid=uid;pwd=pwd;Initial Catalog=master;"

Categories

Resources