Site Archive (Complete)
Windows/.NET
Practicing .NET

Improving developer productivity and software quality

by Mark M. Baker

October 2006


October 24, 2006

Zen of Settings: Part 4


We're now ready to take a look at how to use the System.Configuration. ApplicationSettingsBase class in a .NET 2.0 application. Unlike many .NET classes that you can instantiate and use, the ApplicationSettingsBase class is meant to be derived from and the derivation used in your application. The reason for this requirement is ApplicationSettingsBase's reliance on attributes to designate what settings are to be persisted, their data types, persistence types, and default values. Attributes form the communication channel between a .NET application and ApplicationSettingsBase providing context about the settings that are being manipulated.

Let's take a closer look.

The first concept to absorb when using ApplicationSettingsBase (and one that I touched on earlier) is that settings come in two flavors - a per-user, read/write variety, and a per-application, read-only variety. The former is typically referred to by engineers as user.config after the typical storage location, and the latter as app.config. It's likely that in your early readings on .NET you became acquainted with app.config as an XML formatted file containing interesting directives, commands and other values used by an application. It replaced the concept of a .INI file in earlier technologies with a more robust and maintainable structure by using XML.

However, app.config has a serious drawback you may have picked up on from the description; it is inherently read-only and as such is not a place that you should (although technically possible) write user data into. Even settings which are application (not per-user) specific but which are runtime generated should not be placed in app.config. This led a lot of .NET developers to plead for some place to store such per-user data and undoubtably led to the creation of ApplicationSettingsBase.

Fortunately, ApplicationSettingsBase hides the notion of per-user and per-application settings by the use of two attributes - UserScopedSetting and ApplicationScopedSetting. The former as you might guess is the one used for per-user settings and the latter for per-application settings. To mark a setting as either (but not both) per-user or per-application, you add the attribute to the setting declaration in a class that derives from ApplicationSettingsBase. Let's look at an example:


public class MySettings : ApplicationSettingsBase
{
[UserScopedSetting]
public string MyUserSetting
{
get { return (string)this["MyUserSetting"];
set { (string)this["MyUserSetting"];
}

[ApplicationScopedSetting]
public string MyAppSetting
{
get { return (string)this["MyAppSetting"];
}
}

In this example, I created two settings named MyUserSetting and MyAppSetting - the names are just ones I picked but could be anything desired. Each setting is defined as a typical accessor/mutator method but instead of accessing a local variable as would be typical, they access a dictionary of items provided by the base class (ApplicationSettingsBase). Since the dictionary deals in the base object type, the value has to be casted on return.

Notice the use of the UserScopedSetting and ApplicationScopedSetting value. The ApplicationSettingsBase class will use reflection to interrogate the derived class to find properties which contain either of these attributes. It is interesting to note that you could have tag-along properties and methods in the derived class that don't persist and this is perfectly acceptable.

Since I'm using the default storage provider (XML persistence to user.config) you may notice that I don't have anything yet that indicates where the settings will be stored, or loaded. And I won't as I mentioned last time since this is handled by the default storage provider automatically. The goal with this class was to make your life as a .NET developer as easy as possible when working with settings and much of the plumbing is hidden from you be default.

Now, it may be the case that each of my properties has a value that I would like to be used if the setting does not yet exist (such as after initial installation of my application). Again, this is accomplished with an attribute called DefaultSettingValue. Let's update our example with this new attribute:


public class MySettings : ApplicationSettingsBase
{
[UserScopedSetting]
[DefaultSettingValue("foouser")
public string MyUserSetting
{
get { return (string)this["MyUserSetting"];
set { (string)this["MyUserSetting"];
}

[ApplicationScopedSetting]
[DefaultSettingValue("fooapp");
public string MyAppSetting
{
get { return (string)this["MyAppSetting"];
}
}

The rule is that if the setting cannot be located in storage, ApplicationSettingsBase will call the setter for the property with the default value. This ensures that your properties have some base value when created, but the attribute is not required.

Interestingly, you might be wondering what if the property isn't a string? Well, you can think of the DefaultSettingValue "value" as though the property's ToString() method was called. So an "int" property would have a default value formatted as "5", and a complex data type like "Size" would have a default value formatted as "100,100".

Finally, you might have noticed that the MyAppSetting setting declared with the ApplicationScopedSetting attribute does not have a setter. This is intentional since the value cannot be persisted with the default storage provider; the value is assumed to come from app.config which by definition is intended to be read-only.

Next time, we'll continue looking at this derived class and how to handle custom validation for values loaded at startup, and why you really want to create a base class for all of your settings classes.

Posted by Mark M. Baker at 10:11 AM  Permalink |


October 17, 2006

Zen of Settings: Part 3


Round three on managing settings in a .NET 2.0 application using System.Configuration. ApplicationSettingsBase. We're now at the point of talking about how this class supports migration of settings within your project.

The challenge with any implementation of application settings is how to manage the evolution of those settings over time. You may find the need to add, remove, update and adjust settings as time passes and your application evolves. Using the default storage provider in .NET 2.0, ApplicationSettingsBase writes out the settings and their values into an XML file similiar to app.config but called user.config. Your next question undoubtably is "where does .NET put this file?".

The answer is fascinating.

First, you have to remember that since settings are likely to be per-user based items, they need to go someplace guaranteed to be accessible to even a user with a low rights account (ie. User security group). The stipulated location for this kind of information is the "Documents and Settings" folder typically found in the root of your C: drive. This is also where the MyDocuments folder is located. However, ApplicationSettingsBase doesn't store (by default) its data in MyDocuments. It chose instead to place this information in Local Settings\Application Data. These is a sibling folder to MyDocuments and is intended for per-user data that is non-roaming (ie that is computer dependent).

As an aside, if you regularly deal with issues such as where to place files, what folders you should use for specific purposes, how to respond to environmental changes in the operating system, etc, I highly recommend getting a copy of Microsoft's Designed for Windows XP spec v2.3 which is in Word document format. This handy little tome will help you resolve and dispense with the interminable discussions that sometimes take place among developers trying to decide these issues.

Back to ApplicationSettingsBase. Although the Local Settings\Application Data folder is used, ApplicationSettingsBase doesn't stop there. It proceeds to create a sub folder named with the name of the company assigned to your application EXE file properties. If the name has spaces, those are substituted with underscores. Not sure why Microsoft does this, but they do. Next, the class creates a sub folder under the company name folder with the name of your EXE plus a bunch of ugly looking characters you can think of as a unique identifier of sorts. In this folder, it creates yet another sub folder with the version of your EXE. In that folder goes the user.config with your settings. It's important to note that the version number includes the full version number down to the build and revision octets.

Each time you build your application (by default) Visual Studio .NET 2005 helpfully updates your version number (actually build number)incrementing it each time. When this happens, ApplicationSettingsBase will automatically create a new sub folder in that location I described earlier with the new version number. Over time as you develop an application on a machine, you can end up with hundreds or thousands of these little sub folders each containing a version of the user.config file that existed for that build.

Now for the really interesting (and helpful) part.

When ApplicationSettingsBase is created when your application runs, it offers (but doesn't require) the ability to migrate older settings values to the new structure using ApplicationSettingsBase.Upgrade(). This is one of those auto-magical methods that makes your life as a .NET developer really sweet. This method will upgrade and copy values from an older build/version of your application into the new user.config. So you don't lose settings between builds and neither do your users. Which will make them very happy indeed.

Next time we'll look at how you can derive a class from ApplicationSettingsBase and use as a base for all settings work you do in .NET 2.0. I use something similiar in shipping .NET 2.0 software.

P.S. - A reader asked if I would cover how to get ApplicationSettingsBase to work in a multi-assembly project. Answer = Sure will. In fact, I'm coming off of a .NET 2.0 Smart Client/Composite UI App Block based application which is inherently multi-module and we use multiple distinct settings classes per module. And it works great.

See you next time.

Posted by Mark M. Baker at 05:02 PM  Permalink |


October 11, 2006

Zen of Settings: Part 2


Last time we started looking at the issue of saving application (and user) settings in a .NET 2.0 application. I briefly mentioned a new namespace called System.Configuration and a class in that namespace called ApplicationSettingsBase that will be your new friend when dealing with this issue.

Before we dive into this topic more, a word here from experience with this class - it's remarkably easy and convienent to use as long as you take a few extra steps yourself. I don't give the issue of creating settings a moments thought anymore since this class was released in .NET 2.0.

Now, let's see why...

The first conundrum that a developer faces (and has always faced) when dealing with settings is where to put the data that needs persisting. In the Win32 world and even .NET 1.x, it was common to resort to the in-famous Registry to store application data. You basically have a choice - store it in the per-user area (Current User), or the per-machine area (Local Machine). The latter has additional restrictions in that you need read/write access to the registry keys that you want to edit there and a low rights user account may not have such access. It also can be problematic since there is one set of data there for all users which can complicate data that needs to be per-user.

The Registry also has another glaring deficiency (besides being easily corrupted and hard to edit) - there is no support for format changes to the data being stored. Imagine v1.0 of your glorious application shipped and had several setting entries. A few months go by and you ready v1.1 to ship to customers. You found the need to add some entries to your set and remove a few. You also decide to store these entries in a different registry subfolder. It's pretty much left to you to spend time writing a conversion/migration routine. Even worse, as versions of your application proliferate, you have to continue to update that conversion code to handle everything back to v1.0 so that any stragglers in your user base and get up to your latest version.

What a pain.

This is a place the Microsoft thought long and hard about when they devised ApplicationSettingsBase (which rumor has it derived from some excellent work done in the Microsoft Patterns & Practices group in the famous code "blocks"). ApplicationSettingsBase is one of those swiss army knives that allows a developer to handle how settings are stored, or leave it to the class to handle it on behalf of the developer. The latter is by far the most common and likely approach for most teams. Why spend time writing plumbing code when you can leave it to Microsoft? By default, ApplicationSettingsBase generates a .config file containing the settings stored in a XML format and stored deep down in the MyDocuments area. It's a known safe place to store application and user data and all users will have access to their own MyDocuments area.

Next time we'll continue looking at how ApplicationSettingsBase manages migration issues between versions of an application.

Posted by Mark M. Baker at 11:13 AM  Permalink |


October 05, 2006

Zen of Settings: Part 1


Few if any applications are developed that don't find some need for storing state in a storage location of some type. It's been that way under Windows going back to Windows 16 when all we had was .INI files as a convienent place to put data that didn't fit into the notion of a data file. .INI files were easy to understand, easy to edit, and without any significant structure. Trying to store hierarchical data or binary items was difficult at best.

Along comes Windows 95 and with it the concept of the Registry. This storage vehicle was part of the operating system (unlike .INI files) and provide both for structured and data type based storage. Initially it was greeted with a lot of enthusiasm and the registry is handy for data that might have gone into a .INI file in the past. However, it had a soon-to-be-realized and now commonly understood weakness; it was susceptible to corruption that was hard to fix. Whereas the .INI files of the Win16 years could be edited by a user with Notepad, the registry required launching a specialized application (RegEdit) and navigating a tree structure of data. Delete or edit the wrong thing and your computer might not boot the next time, or applications might behave badly or crash.

Not the kind of thing you want to have your end users modify while talking with your Tech Support team on the phone.

But the registry and INI files were all we had up until .NET 2.0 unless you wanted to roll your own. Many did just that by embracing XML as a file format that combined the easy to edit features of INI files with the structured and hierarchical layout of the registry. Of course, it also meant spending time writing essentially plumbing/infrastructure code to read/write the XML, validate its format, handle migrations of older to newer formats, and so on.

But what about app.config in .NET 1.x? Isn't that a replacement for INI files and the registry?

Yes and no. Yes because it is XML based and there was some support built into .NET to allow a developer to read data from the file for an executable. Its downside and it's a whopper is that app.config files are intended to be read-only. They're great for storing switches, configurations, commands and other static items that control how an application launches and operates. They're terrible at handling dynamic, runtime data generated as the application runs. Some developers resorted to storing the runtime data in the app.config by rewriting it on the fly. But Microsoft didn't recommend this and most developers decided not to go down that road.

With .NET 2.0, Microsoft unveiled a new technology in the System.Configuration namespace wrapped in the ApplicationSettingsBase class. This system was designed to allow developers to create XML based (by default) settings objects that could be read from/written to, interact with app.config and amazingly support upgrades of the underlying file from version to version automatically.

You'd have thought it would have been one of the top touted features of .NET 2.0. Sadly, and for some unknown reason, it was buried inside the framework and only intrepid souls stumbled onto it. To make matter worse, the documentation around the classes is thin and it left many questions unanswered.

I'll take you on a walk through the ApplicationSettingsBase class over the next few posts. Stick around and you'll be a Zen master.. er.. Settings master by the time we finish.

Posted by Mark M. Baker at 11:26 PM  Permalink |



March 2008
Sun Mon Tue Wed Thu Fri Sat
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31          


BLOGROLL
 
INFO-LINK


Related Sites: DotNetJunkies, SD Expo, SqlJunkies