lance
lance

Reputation: 16342

AppSettings fallback/default value?

ASP.NET

For each appSetting I use, I want to specify a value that will be returned if the specified key isn't found in the appSettings. I was about to create a class to manage this, but I'm thinking this functionality is probably already in the .NET Framework somewhere?

Is there a NameValueCollection/Hash/etc-type class in .NET that will let me specify a key and a fallback/default value -- and return either the key's value, or the specified value?

If there is, I could put the appSettings into an object of that type before calling into it (from various places).

Upvotes: 5

Views: 17802

Answers (6)

Theobald Beyer
Theobald Beyer

Reputation: 174

ASP.NET's ConfigurationManager provides that functionality. You can bind your configuration section (retrieved with .GetSection("MySection")) to an object with either .Get<MySectionType>() or .Bind(mySectionTypeInstance). This also has the benefit, that it does conversion for you (see integers in the example).

Example (NET 6)

appsettings.json

{
  "MySection": {
    "DefinedString": "yay, I'm defined",
    "DefinedInteger": 1337
  }
}

MySection.cs

// could also be a struct or readonly struct
public class MySectionType
{
  public string DefinedString { get; init; } = "default string";
  public int DefinedInteger { get; init; } = -1;
  public string OtherString { get; init; } = "default string";
  public int OtherInteger { get; init; } = -1;

  public override string ToString() => 
    $"defined string :   \"{DefinedString}\"\n" +
    $"defined integer:   {DefinedInteger}\n" +
    $"undefined string : \"{OtherString}\"\n" +
    $"undefined integer: {OtherInteger}";
}

Program.cs

ConfigurationManager configuration = GetYourConfigurationManagerHere();

// either
var mySection = configuration.GetSection("MySection").Get<MySectionType>();

// or
var mySection = new MySectionType();
configuration.GetSection("MySection").Bind(mySection);

Console.WriteLine(mySection);

// output:
// defined string :   "yay, I'm defined"
// defined integer:   1337
// undefined string : "default string"
// undefined integer: -1

Upvotes: 5

Tore Aurstad
Tore Aurstad

Reputation: 3826

You can build logic around ConfigurationManager to get a typed way to retrieve your app setting value. Using here TypeDescriptor to convert value.

/// <summary>
/// Utility methods for ConfigurationManager
/// </summary>
public static class ConfigurationManagerWrapper
{
    /// <summary>
    /// Use this extension method to get a strongly typed app setting from the configuration file.
    /// Returns app setting in configuration file if key found and tries to convert the value to a specified type. In case this fails, the fallback value
    /// or if NOT specified - default value - of the app setting is returned
    /// </summary>
    public static T GetAppsetting<T>(string appsettingKey, T fallback = default(T))
    {
        string val = ConfigurationManager.AppSettings[appsettingKey] ?? "";
        if (!string.IsNullOrEmpty(val))
        {
            try
            {
                Type typeDefault = typeof(T);
                var converter = TypeDescriptor.GetConverter(typeof(T));
                return converter.CanConvertFrom(typeof(string)) ? (T)converter.ConvertFrom(val) : fallback;
            }
            catch (Exception err)
            {
                Console.WriteLine(err); //Swallow exception
                return fallback;
            }
        }
        return fallback;
    }
}

Upvotes: 1

Carter Medlin
Carter Medlin

Reputation: 12485

This is what I do.

WebConfigurationManager.AppSettings["MyValue"] ?? "SomeDefault")

For Boolean and other non-string types...

bool.Parse(WebConfigurationManager.AppSettings["MyBoolean"] ?? "false")

Upvotes: 5

Heretic Monkey
Heretic Monkey

Reputation: 12114

I don't believe there's anything built into .NET which provides the functionality you're looking for.

You could create a class based on Dictionary<TKey, TValue> that provides an overload of TryGetValue with an additional argument for a default value, e.g.:

public class MyAppSettings<TKey, TValue> : Dictionary<TKey, TValue>
{
    public void TryGetValue(TKey key, out TValue value, TValue defaultValue)
    {
        if (!this.TryGetValue(key, out value))
        {
            value = defaultValue;
        }
    }
}

You could probably get away with strings instead of keeping in generic.

There's also DependencyObject from the Silverlight and WPF world if those are options.

Of course, the simplest way is something like this with a NameValueCollection:

string value = string.IsNullOrEmpty(appSettings[key]) 
    ? defaultValue 
    : appSettings[key];

key can be null on the string indexer. But I understand it's a pain to do that in multiple places.

Upvotes: 3

Richard Anthony Hein
Richard Anthony Hein

Reputation: 10650

You can make a custom configuration section and provide default values using the DefaultValue attribute. Instructions for that are available here.

Upvotes: 1

Dave Swersky
Dave Swersky

Reputation: 34810

I think the machine.config under C:\%WIN%\Microsoft.NET will do this. Add keys to that file as your default values.

http://msdn.microsoft.com/en-us/library/ms228154.aspx

Upvotes: 0

Related Questions