Feature Preview: Client Settings


One of the new Whidbey features Joe Stegman talked about
at the PDC was Client Settings. This is a feature I have spent a lot of time
on in Whidbey, so I thought I would talk a little bit about it.

Very often, if you are writing a client app (also for web apps, but let me focus on
client for now), you need the ability to store some settings. These settings
are often user preferences, like Form size and location, look and feel of
various controls, toolbar positions, last read entry etc. etc. These could
also be more application specific things like connection strings and resource paths. In
.NET Framework v1.0 and v1.1, there are several ways to achieve this – using dynamic
properties
, writing your own configuration
section
to store stuff into the application config file or storing the settings
in a separate file, possibly in XML format, and parsing the content yourself. Ofcourse,
then there is the traditional store for application settings – the Windows registry.

Each of these, however, has some limitations. Dynamic properties support a limited
range of types and are read only. Writing a configuration section isn’t very easy
– you need to do all the parsing, merging between levels and validation yourself.
Storing settings into an independent file means you need to management the deployment
of that file yourself, besides, ofcourse, having to do the parsing, defining
what schema to use and so on. The registry too isn’t the right place to store settings
in many cases.

So, if you want to store settings today, you need to put in considerable effort to
do it right. The Configuration
Management Application Block
solves some of these problems for you today, and
is pretty cool, but in Whidbey, we are taking a big step forward and are trying
to design a model which makes it super easy to consume settings in your application.
What’s more, the core parts of this model are common to web and client apps, so there
is more consistency in how you store and access settings across different kinds of
applications.

At the core of the new settings infrastructure are two abstract classes – SettingsBase
and SettingsProvider. SettingsBase hides the storage details way from the application
developer and exposes an easy mechanism to read, write and save settings. The SettingsProvider
is actually responsible for persisting these settings. How it persists them is its
own choice – SettingsBase doesn’t really care. It could store them in a local file, a
database or retrieve them through a web service, for example. In each case, the
way the application consumes the settings remains the same.

The ApplicationSettingsBase class Joe talked about adds value to SettingsBase and
makes it even more easier to create your own settings. Essentially, in this model,
settings are nothing but properties on classes that are decorated with a bunch of
attributes that describe them.

Here is a how a simple settings class would look:

public class MySettings : ApplicationSettingsBase {

   [UserScopedSetting]  // varies by user

   [DefaultSettingValue(“Blue”)]  // use this if no value is stored

   public Color MyFormColor { 

       get {

             return
(Color) this[“MyFormColor”];

        }

        set {

              this[“MyFormColor”]
= value;

         }

   }

   [ApplicationScopedSetting] //shared by all users

   [SettingsProvider(“MyWebServiceProvider.blahblah”)]

   public Point FooLocation {

       get {

             return
(Point) this[“FooLocation”];

        }

        set {

              this[“FooLocation”]
= value;

         }

   }

}

and then consuming these settings is equally staightforward:

myForm1.BackColor = MySettings.MyFormColor;



MySettings.FooLocation = myControl1.Location;



MySettings.Save();

Its as simple as that! You can read/write settings of arbitrary types (which the provider can
serialize, ofcourse) with just a few simple lines of code. By default, for client
apps, we will ship a provider that can store settings into the application configuration
files (we are extending the configuration system to store user specific stuff too)
without any extra effort on the application developer’s part!

That’s not it, though. This model is also powerful for those who have more requirements.
You can write your own custom provider that stores settings wherever it wants. You
can exercise more control over how the default provider serializes its settings. You
can define your own attributes that only your provider understands – ApplicationSettingsBase
will pass the metadata over to the provider. You can group your settings into a bunch
of different classes, map settings to different providers, bind the settings to properties
of your UI/business objects through data binding and so on and so forth. If you wish
to write your own configuration section, the ASP.NET team has made that much easier
too.

That’s not all we have planned – there is more, including great design time support
in Visual Studio and the concept of component settings.

More on all this as we approach Whidbey Beta!


Comments (17)

  1. Steve says:

    Very Cool! I love the provider model you guys are taking for all the new stuff in Whidbey!

  2. milbertus says:

    Yeah, very cool indeed. It’ll be great not to have to write the same/similar parsing and saving code for every app that I write, just to get some settings saved to disk.

  3. bryan says:

    Better than the precedent but over engineered. Dynamic properties should have one of three options associated with them: 1 – don’t persist (sames as 1.1); 2 – persist for user; and 3 persist for machine. Yes, it can be that simple and should have been all along. You add a dynamic property, specify the key (default generated for you), and select a persistance option. Is it possible that VS could do this for you using the model above? I don’t want to add even that little bit of code for every form that I want to save the user’s last entries on.

  4. Bryan: Yes, we are working on design time support in VS for this feature. In typical cases, you won’t need to write a single line of code to create settings and bind them to properties. Creating settings will be as simple as specifying a few things about each setting (like name, type and scope) through a UI.

  5. GregW says:

    This all sounds great. I just wrote an application to migrate registry settings from one release to another…what a pain. So will this make exporting settings and reimporting them more efficient? Particularly we have difficulty classifying/identifying which settings should persist from release to release and which should not. I assume it would be possible to assign an attribute to settings to control whether they should be exported or not? If you support exporting what format would the export be in?

  6. GregW:

    We will provide functionality that lets you easily "upgrade" your settings when you release a new version of your settings class/app. And there will be a declarative way of specifying whether you want to upgrade a particular setting or not. I will blog more about this in the future.

    Is this the functionality you need? I am not sure what exactly you mean by "export" in this context. Can you explain further? Why do you need this?

  7. GregW says:

    Our users often want to standardize settings in our application across a whole office. So on one hand we need to be able to export application settings so that others can import them throughout an office. Some settings are currently saved in the registry, but not all of them by any means. We really need to consolidate where we store settings and we need to make it easier for our users to export and import them.

    This works hand-in-hand with upgrades. You could easily make the argument that an upgrade is just an export of settings from one release and an import into another. Although we try to provide a more "automatic" UI for the upgrade, many of our same problems exist. We need to track down all the registry entries as well as various files (many in different formats) that we need to migrate.

    We really need to consolidate all of these settings but still remain flexible enough to store a wide variety of data.

  8. I think the Whidbey model for settings gives you the flexibility you want. With the default provider that we ship, you can have application scoped settings and user scoped settings. You can also set defaults for the user scoped settings that apply to all users.

    Also, if for some reason the default provider doesn’t meet your needs, it shouldn’t be very difficult to implement a custom provider. That way, you can store settings how you want and still fit in with the same object model.

    If you get early access to Whidbey builds, do let us know whether the feature meets your needs!