Storing Custom Settings in Dynamics CRM 2011
While browsing the Dynamics CRM 2011 Development forum I came across a post asking where people store their settings for ISV extensions. The way I’ve done this is by creating a custom entity called “Settings” with 3 fields, Key, Value and Encrypted (yes/no).
Example:
Then we have a helper class that gets these values. Here’s an example
Inside a Plugin
IOrganizationService ios = factory.CreateOrganizationService(…);
Setting settings = new Setting(ios);
int defaultDays = settings.Get<int>("complaint.default.acknowledgementdeadlinedays");
The Settings.cs file
Couple of things to note, the EncryptDecrypt method is blanked out, you’ll need to implement your own encryption and decryption routine.
The Get
public class Setting
{
private IOrganizationService _sdk = null;
public Setting(IOrganizationService context)
{
_sdk = context;
}
#region encryption
internal static string EncryptDecrypt(string textToEncrypt)
{
return textToEncrypt; // up to you to implement encryption
}
#endregion
// some common type castings, you can add more if required
public T Get<T>(string key)
{
string value = this[key];
if (!string.IsNullOrEmpty(value))
{
if (typeof(T) == typeof(string))
{
return (T)Convert.ChangeType(value, typeof(string));
}
if (typeof(T) == typeof(int))
{
return (T)Convert.ChangeType(int.Parse(value), typeof(int));
}
if (typeof(T) == typeof(decimal))
{
return (T)Convert.ChangeType(decimal.Parse(value), typeof(decimal));
}
if (typeof(T) == typeof(DateTime))
{
return (T)Convert.ChangeType(DateTime.Parse(value), typeof(DateTime));
}
}
return default(T);
}
#region settings storage
private Dictionary<string, string> _values = new Dictionary<string, string>();
private Dictionary<string, Guid> _cached = new Dictionary<string, Guid>();
internal string this[string key]
{
get
{
if (_values == null || _values.Count == 0) { Refresh(); }
if (_values.Keys.Contains(key))
{
return _values[key];
}
return "";
}
set
{
}
}
#endregion
#region helper methods
public void Refresh()
{
_cached.Clear();
// get all the settings and parse it into a collection first
QueryExpression qe = new QueryExpression("mag_setting") { ColumnSet = new ColumnSet(true) };
var results = _sdk.RetrieveMultiple(qe);
if (results != null && results.Entities != null && results.Entities.Count > 0)
{
results.Entities.ToList().ForEach(setting =>
{
var current = setting as Entity;
Guid id = current.Get<Guid>("mag_settingid");
bool encrypted = current.Get<bool>("mag_encrypted");
string key = current.Get<string>("mag_key");
string value = current.Get<string>("mag_value");
if (encrypted) { value = EncryptDecrypt(value); } // decrypt if the setting is encrypted
// make sure we don't double up on the settings, otherwise .net will throw an error
if (!_cached.Keys.Contains(key)) { _cached.Add(key, id); }
if (!_values.Keys.Contains(key)) { _values.Add(key, value); }
});
}
}
#endregion
}