Need changable App.config file in WPF - c#

I have a desktop WPF application which uses Entity Framework 4.1 Code First approach to manage data.
EF adds a connection string to the App.config file and I wan't to be able to change this connection string at runtime.
Scenario is like this:
When I deploy the application it has a default connection string in the App.config file. The user runs the application and since the connection string will probably be invalid for the user (because of server name, user id and password) I will display a server configuration window.
Here user will enter the valid information about his connection and press OK. I will then be able to change the App.config file and save the user's new valid information to the file.
Problems:
If I change it using ConfigurationManager, the changes will be temporary meaning that the file is not saved, changes are made in memory.
If I read the App.config file into a stream, make required changes in the memory, delete physical file and save the in memory stream as App.config again, Windows will not let me make changes to files under ProgramFiles folder.
What is would be the best approach here?
EDIT: Problem Again!
After I modify the App.config file with this method:
private void ApplyChangesToConnectionString()
{
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
var connectionStringsSection = (ConnectionStringsSection)config.GetSection("connectionStrings");
connectionStringsSection.ConnectionStrings["SomeUniqueName"].ConnectionString = GetChangesAppliedConnectionString(connectionStringsSection.ConnectionStrings["SomeUniqueName"].ConnectionString);
config.Save(); // This line throws an exception
ConfigurationManager.RefreshSection("connectionStrings");
}
config.Save(); method call throws an error saying
"Access to "C:\Program Files (x86)\MyCompany\MyApp\MyApp.exe.config"
is denied."
I know that files under "Program files" are immutable, so how can I handle this?

I couldn't modify ConfigurationManager.ConnectionStrings["key"] object, because it is readonly.
So I decided to add a new connection string to my App.config file so it looks like this:
<connectionStrings>
<add name="SomeUniqueName" connectionString="Data Source=(local)\SQLExpress;Initial Catalog=MyDb;User Id=sa;Password=password; MultipleActiveResultSets=True" providerName="System.Data.SqlClient" />
and then changed my DbContext constructor to take newly added connection string like this:
public MyContext()
: base("name=SomeUniqueName")
{
}
Here, the value of name attribute at connection string and constructor must match.
Then to change this newly added connection string at runtime I used a method like this:
private void ApplyChangesToConnectionString()
{
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
var connectionStringsSection = (ConnectionStringsSection)config.GetSection("connectionStrings");
connectionStringsSection.ConnectionStrings["SomeUniqueName"].ConnectionString = GetChangesAppliedConnectionString(connectionStringsSection.ConnectionStrings["SomeUniqueName"].ConnectionString);
config.Save();
ConfigurationManager.RefreshSection("connectionStrings");
}

App.config is not the proper place to do this since it's a global configuration used by the application.
I recommend you to save the settings per user. See this related question : c# - approach for saving user settings in a WPF application?

App.config is the correct approach in my opinion, however I wouldn't rely on writing the file physically yourself. Instead, allow the framework to do the heavy lifting for you.
Check out the sample here.
EDIT: Glad Sandeep's comment above has helped you. Feel free to check out that link too if you want a bit more information!

Related

Getting a connection string

The program I'm writing accesses a database. So when I use the SqlConnection() class, I hard code the actual connection string as a parameter. Eventually I'd like o deploy this program to different users. So my question is:
When a user installs a program on their computer, how does the new connection string get created, where is it stored, and how can I access it?
Thanks for the help
You need to out it in a configuration file and load it from there. For an ASP.NET application it would be in the web.config file;
<connectionStrings>
<add name="MyConnection" connectionString="MyConnectionString" />
</connectionStrings>
and then use
string connectionString = ConfigurationManager.ConnectionStrings["MyConnection"].ConnectionString
in your application.
The for each installation it would be configured for the local requirements.
For a desktop application the details are different but the principle is the same.
See references in answer from Luis Sagasta
As explained in MSDN, you should save the connection string in the configuration file:
MSDN: Connection Strings and Configuration Files
In the same article you will find information about encrypting the configuration section:
MSDN:Encrypting Configuration File Sections Using Protected Configuration
Regards.

connectionstring declare in iis without declaring in web.config

I want to declare my connection string in IIS and get it from there. I don't want to declare it in web.config page. Rather I need to know if is it possible to get the string from iis in web.config or read it from code file. I am using asp.net 4.0.,coding in c# and server is IIS7.5
According to this article you can use the IIS UI, or the command line to modify your connection string, but this will just write into the <connectionString> element in the web.config file any way (unless you've set it up to save elsewhere).
Also, you can store it in another .config file if you wish, and pull it into your web.config like so
<appSettings file="../VirtualDirectory/config/Env.config">
</appSettings>
You could then call it like so in your code:
System.Configuration.ConfigurationManager.AppSettings["DefaultConn"]
This can be quite useful if you want the location of your connection string to not be under your site (i.e. in a virtual directory).
You should put your connection string in the web.config. Putting your connection string elsewhere might not be portable, like moving from machine to machine. You also have the machine.config
In all, put in the web.config and you can encrypt it if you care about the secrecy
You can also have a separate config file e.g. db.config referenced from your web.config using the configSource attribute.
<connectionStringss configSource="Configuration\db.config" />

How to Override a Value in Web.config Programatically

I am developing a web app with a group of people and we all have different connection strings to our database.
The connection string is stored in our web.config which is source controlled, and sometimes people check in their web.config with their connection string which messes up my environment.
I want to use an environment variable that if exists will override the connection string in my web.config. How can I do that?
As others have noted in your comments there is no easy way to stop people from changing any file that is under source-control. However, what you could do is change your web.config file to have:
<connectionStrings configSource="Configs\ConnectionStrings.config" > </connectionStrings>
Then have a folder called Configs and in there a file named ConnectionStrings.config with content like:
<connectionStrings>
<add name="YourVersionHere" ... />
</connectionStrings>
That way you can check the web.config file in / out without it altering your connection string (it is now held in a separate file). Of course, this doesn't get you out of jail because they can then overwrite the ConnectionStrings.config file but it does allow you to break your config out so you can always be up to date with all the settings but never do a GET on your ConnectionStrings.config file.
The same applies to AppConfig etc. Basically allows you to manage your config in smaller chunks rather than all in one place.
You can get more information here: http://msdn.microsoft.com/en-us/library/system.configuration.sectioninformation.configsource.aspx
Is it possible for you to move your connection strings from your application-level web.config down to your system-level machine.config file?

How To Change Connection String at runtime using CTP5

all
I am trying to change the connection string at runtime, i am using CTP5,
when i change the connection string and the folder is empty EF throws:
Database 'C:...\bin\Debug\db.mdf' already exists. Choose a different database name.
Cannot attach the file 'C:...\bin\Debug\DB\db.mdf' as database 'DB'.
when the folder has db.ldf (The Log File) and db.mdf EF throws the same exception
Please Help...
In Entity Framework 4 you can create an ObjectContext with a connection string as constructor argument. So you're free to use any connection string any time. If course it would help if the database structure matched the context :).
You can change the app config and reload changes.
// Open App.Config of executable
System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
// Copy the value of new connection string
config.AppSettings.Settings["ConnectionString"].Value = "New Connection String";
// Save the configuration file.
config.Save(ConfigurationSaveMode.Modified);
// Force a reload of a changed section.
ConfigurationManager.RefreshSection("appSettings");

Establishing database connection

First, forgive my english.
My group and I are planning to do an application. This application can be installed to other machines, and should connect to a server and the database is password protected.
As a student, we always do this in a naive way:
SqlConnection myConnection = new SqlConnection("user id=username;" +
"password=password;server=serverurl;" +
"database=database; " +
"connection timeout=30");
Always hardcoded.
What if we change the password of the database, or chage our server?
We have also to change the values in our code, recompile and reinstall the application in the pc. Is there something dynamic way of doing these?
We are thinking that in the first run of the application, the user will be prompted for the connection details and save that data into a file where the application will fetch it everytime it starts and use it for database connection, but there's a password involved.
Any suggestion, ideas, concepts, samples, etc...? How to do it in more professional way? Please help... Thanks.
You could store the database settings in app.config
http://www.ezzylearning.com/tutorial.aspx?tid=8067328
you could store your credentials in the config file - that way no need to recompile the project every time the password changes.
The config file can be encrypted too, so you could only change the password via the application you're making.
Windows lets you encrypt files, so that only processes running as the owner can read them. You could store the passwords in a file and encrypt it. See File.Encrypt on MSDN.
This would only be one factor in the security model. You probably also want to encrypt the file at the application level so malicious software that the users run doesn't sniff around for passwords.
There are several ways to do this. First off all you may save your connectionString in an app.Config/web.config file. Your connection objects may access this string by using
PROJECTNAME.Properties.Settings.Default.YOURCONNECTIONSTRINGNAME
Your app.config file may look something like this
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
</configSections>
<connectionStrings>
<add name="Winforms_Demo.Properties.Settings.dbNordwindConnectionString"
connectionString="Data Source=(local)\SQLEXPRESS;Initial Catalog=dbNordwind;User ID=sa"
providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>
As you can see this possibility still saves any user credentials hardcoded (although you may change them by manually editing the config.file (even after compiling). You may create such a config file by adding a new datasource to your project (e.g. sql server datasource). The wizard will then ask where to save your connectionString.
Another possibility will be connectionStringBuilder. This class offers some properties:
SqlConnectionStringBuilder conbuild = new SqlConnectionStringBuilder();
conbuild.InitialCatalog = "dbNordwind"; // database name
conbuild.IntegratedSecurity = false; // true if you use winAuthent
conbuild.UserID = "sa"; // e.g get this info by showing a authent form
conbuild.Password = "123";
conbuild.DataSource = "servername";
SqlConnection con = new SqlConnection(conbuild.ConnectionString);
Using this method you may even access a file and read any required data. In this case you have to look into security measures for your file!
Securing your file may be done by encrypting it (System.Security namespace) or saving data into any isolatedStorage (user specific - windows security will be used) or by using "aspnet_regiis -pef" to crypt any config-file.

Categories