I have a class where I retrieve certain settings from a database (usernames and passwords). This database is sitting on a network, and it means that if the passwords are changed, I can simply change it in the database, and all the applications that use this class will still work.
I am fully aware of the pros and cons of storing usernames and passwords in a database and in a separate location. I don't want to discuss those, please.
The class has a hard-coded static string that is the path to the database. It is a fully qualified network name (not just the drive letter). I did this because we had an issue where our network DNS got screwed up, and drive letter mappings stopped working, and some people have different drive mappings anyway.
We recently had our server moved, so I now need to go through and change these hard-coded strings.
I was thinking that I should store the path in a settings / configuration file instead. I considered "application.settings", but it is not an application setting; its specific to the class. Is there a preferred way of doing this in the existing .Net framework (this is a C# issue)?
I could simply have a small text or XML file that sits in the application directory, which is probably fine... is there an existing framework namespace or open-source code snippet that someone knows of that I can use?
I think, if you want class specific configuration, you should try to have those class instances, configuration driven. Another way of thinking but; Defining a something in a configuration file, will create an instance of the defined classname.
For example: Create a section, and call it, <Modules> and create items in like: <module type="<namespace>.DBConvertor" param="username=root;passwd=whatever"> This type will be created at startup (you need some coding here). And it's even possible to create more than one instance simultaneously with it's specific configurations.
This kind of configuration is already implemented:
You might take a look at this: "How to: Create Custom Configuration Sections Using ConfigurationSection" https://msdn.microsoft.com/en-us/library/2tw134k3.aspx
And creating instances from typenames, use the Activator class.
Besides that, there are many module/plugin libraries, (like Managed Extensibility Framework (MEF) https://msdn.microsoft.com/en-us/library/dd460648(v=vs.110).aspx but could be a little over the top in this case).
Related
I have an app.config which is working fine.
But I also have a tool for automated testing, that runs some tests in environment without any file access. So I have to read a config file from string (or memory stream), but without mapping it physically because there is no access to file system from this automatic testing process.
In real life, of course, config file is stored somewhere, but for automated testing purposes I need some workaround to read a config file from string stored in memory. Is it even possible? I googled a lot, but the only thing I found is Save it as temp file and then read, but it's not my case.
Avoid a direct dependency from your class on app.config or any other file. Your class doesn't need app.config or Properties.Settings. It needs the values contained in the those files..
If you create a workaround for testing purposes then you're testing a different version of your class. That's the inherent problem - direct dependency on these files isn't testable. It doesn't mean that they're bad in some way or that we shouldn't use them, only that the class that requires the values should not read them from the file.
An ideal solution is constructor injection, a form of dependency injection. Provide the value to the class in its constructor and store it as a field. That way when the class is created it always has the values it needs.
At runtime you can use a dependency injection container - here's a walkthrough on setting one up for WCF. You're likely in a different project type, but the concepts still apply.
But for testing, it's as easy as creating a class and passing whatever value you want to use into the constructor. It's impossible to test with different values when the class reads from settings but it's easy using constructor injection.
Without the configuration file you'll have the default settings. You may override the default values:
Properties.Settings.Default["PropertyName"] = NewPropertyValue";
(Set the correct access modifier on your Settings class and use the correct namespace if it is in a library)
As first option I would go for Settings file in your case.
Even your user won't be ablle to access settings file content. Then it will return a default value for a particualr property.
You can try creaty a silly console app
static void Main(string[] args)
{
Console.WriteLine(Settings.Default.MyProperty);
Console.ReadLine();
}
were you set the your value for MyProperty on the Settings Tab of you Project Properties.
Then you can build your solution, open the binaries folder and delete your exe.config file and you will see that the app will be use default values.
As second option you can use command line arguments. could also be an option for you. (Here the article about some tricky case for command line arguments Backslash and quote in command line arguments )
Third option could be placing your file at c:\users\your app user \AppData\Roaming\YourAppName folder. here you should be granted for file access even for restricted user
For education reason I would also reccomend to look at this article: https://msdn.microsoft.com/query/dev11.query?appId=Dev11IDEF1&l=EN-US&k=k(ApplicationSettingsOverview);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.5)&rd=true
Maybe you find the "Load Web Settings" option nice.
Another palce for investigation could be
I have a newb question. I have a winforms application that has a number of classes that referenced a number of UNC network paths. I started to notice I had a bunch of string duplication and then started trying to weed them out by consolidating them into the classes that just make more sense to have them. I was then referencing the class with the string I needed each time I needed to get the value of the string but I'm sure this was a sloppy way to do it.
Now I've settled on making a single class ("StringLibrary") and am referencing that class in each class I need to pull strings from. This seems much more efficient than what I was doing before, however, I'm still not sure if this is a good way to do it in general.
Is there a better way (i.e. more standardized way) to consolidate a group of strings or values in c#?
It depends on whether the strings are configuration or more permanent. For network paths, you may want to put them in your app.config file (see What is App.config in C#.NET? How to use it?), since they may change from time to time, or differ between deployments (and you do not want to recompile your code for every site) Depending on the nature of the data, you may alternatively want to store it in the registry or in a database.
If it is something more tightly tied to your code, like names of controls on a form, or names of columns in your database. Then you may want to centralise their definitions as you suggest, and reference them all from there. When there are a lot of them, your may want to split your StringLibrary into more classes with more relevant names (e.g. if you are speficying names of columns in your database, then you may want to create such a static class for each table in your database) If you take this approach, and since you are new to C# it may also help to read Static readonly vs const to decide if you want them to be const or static readonly.
These could be added to an application config file/ web config file,
resource files and/or settings files.
This way you can administer these strings, should they change, without having to re-build your application and also apply transformations (if in an app.config/web.config) when performing releases to different environments/deployments.
In an MVC web application I want to override connection strings based on the development machine I'm using. I can use Web.config transformations, but I also need to override connection strings in various non-web config files. I can use the SlowCheetah extension, but then I will end up creating the same transformation for every project that accesses the database. This is a hassle to maintain when the project becomes bigger and has more developers.
What I would like to do is modify the way Entity Framework or ASP.NET look for connection strings, adding a class of my own that looks for connection strings, and only implement the transformation logic once. I would hopefully use Ninject to inject it only when relevant.
Is there such an "IConnectionStringProvider" interface I can implement and register, and automagically have ASP.NET and EF use it?
EDIT. I have found this, but it seems real nasty. If there's no cleaner way, I'll just use multiple identical configuration translations, and maybe let the source control system duplicate them properly.
You can tell Entity Framework to use a different connection string - it doesn't have to use the default one in web.config.
Here is an example: http://www.codeproject.com/Tips/234677/Set-the-connection-string-for-Entity-Framework-at
Here is another: http://msdn.microsoft.com/en-us/library/bb738533.aspx
It's up to you how you architect the rest of it.
Personally I use an app setting in web.config to tell my code which connection string to use for a particular part of the system, e.g.
var connectionStringNameForMyFeature = ConfigurationManager.AppSettings["connectionStringNameForMyFeature"];
myFeature.ConnectionString = ConfigurationManager.ConnectionStrings[connectionStringName];
OK, so this is not the most useful question since I can't remember the feature in .net that does this. Basically, that's what I'm asking; what feature is this?
A year or so ago, I was working on a project and we used configuration files that mapped directly to a class using the specific attributes on the class members. This is not the standard app.config, but assemblyname.dll.xml instead.
Perhaps it's a feature within the unity framework? Just a stab in the dark.
It is not critical I figure this out today, but it is just weighing on my brain and annoys me that i can't remember!
thanks!
It's not the standard XML config, but it is built into .NET. Basically, XML serialization allows you to project an XML document from a hydrated class instance, that will map 1:1 to the class it came from and can be used to re-hydrate a new instance of that class.
This can, in the majority of cases, be done without much effort on your part. All that's usually necessary for XML serialization to work is that the object must have a public default constructor, and that all the state information you want to serialize must be public and read-write. In a few cases, some attributes are necessary to define certain behaviors, like derived classes in arrays of their parent class, and defining non-default names for field and property element tags.
One of the major uses of this is for custom configuration files as you stated; you can load the configuration from a persistent state by simply deserializing the file into an instance of the configuration object.
Article: MSDN How To Serialize an Object
This isn't part of the .Net bcl or Unity as far as I am aware. Perhaps it's some other third party or open source component? That being said, it wouldn't be too difficult to build something like this on your own using XmlSerialization.
.net allows for multi layered configuration.
Every machine has the machine.config file. each application has the app.config file (which gets renamed to applicationname.exe.config upon building), but each dll can also have it's own config file. so, if I have the following binaries in my executable folder:
flexitris.exe
flexitrisHelpers.dll
thirdPartyContent.dll
each of them can have their own config file:
flexitris.exe.config
flexitrisHelpers.dll.config
thirdPartyContent.dll.config
and all of them will be read at runtime and accessible using the normal System.Configuration namespace.
I have a Solution with 3 projects in, each project needs access to certain settings. I'm looking for a way to have these setting values available to any project from 1 distinct source. I cant use the .Config file as that is relevent to that particular project.
I could use the database but have been told this is not good practice (Without an reason)
Any ideas?
You could do this:
create a solution.config in your solution folder
in each project's app.config, add this to your <appSettings> node:
<appSettings file="solution.config">
....
</appSettings>
You would have to put symbolic links to your common solution.config in each project folder - but you could have one single physical file that you share amongst the projects.
The <appSettings> node is the only one that allows that sort of "cummulative" settings - those from the file specified in the file= will be added to your app settings, but potentially overwritten by anything you specify explicitly in your app.config.
On the other hand, yes, of course, you could use the database. We do that, too, in most of our projects, since we typically do have access to the database, but not to the file system in the client's server machines. I don't see why that should necessarily be a bad thing - we have settings for DEV, TEST and PROD in a table - so you have all your settings in one place - and we pick those settings we need when we need them. Works just fine - of course, some settings like the connection strings to the database cannot be stored there - but the bulk of our config info is. Again: I really don't see any reason why this should be a bad choice per se - so unless your source can back his/her statement up with some facts and reasons, I'd ignore it.
You can define configSource attribute in a defined configSection, to reference an external file from which to load your properties.
Here you can find an example:
Is there any way for an App.config file to reference another full config file? (.NET)
You can also use a DB of course, but that would probably involve developing some kind of configuration console, since it's not a good practice to manage config attributes directly into DB.
Otherwise you can create your config file (an xml, or yaml for example) and create your own shared config parser.
I create a class to hold system-wide settings using either a Singleton pattern, or a Global instance (whichever you preference is).
If another project is in the solution, it can see the class (when references are added).
This also decouples the presentation of the settings from the storage mechanism (database, config file, custom XML file, whatever), and if you design to the interface, it makes unit testing more flexible, too.
You could add an entry into each projects .config file that points to the global one. You would need to read that in three places though.
Another solution that springs to mind is to put your common settings into their own assembly with it's own .config file. You then include that assembly in each of your projects. The .config file is read in the assembly and you can read out those values you need.
What kinds of settings?
You can use the system wide machine.config and web.config files for settings that apply across an entire machine.
\Windows\Microsoft.NET\Framework[64]\[version]\config\machine.config
\Windows\Microsoft.NET\Framework[64]\[version]\config\web.config
You could use the registry if you have access to it. Then all you would need is a class to read them out (and possiblty one to put them in) and each project could use that class to read them.
The major downside though is that you would have to add the settings to each machines registry that you run your solution on.