<?xml version="1.0" encoding="utf-8"?><rss xmlns:a10="http://www.w3.org/2005/Atom" version="2.0"><channel><title>Ron's Blog</title><description /><a10:link href="http://www.isi-net.com/Blogs/Ron-Muth" /><item><guid isPermaLink="true">http://www.isi-net.com/Blogs/Ron-Muth/MVC-Routes-and-Magic-Strings--No-Good</guid><link>http://www.isi-net.com/Blogs/Ron-Muth/MVC-Routes-and-Magic-Strings--No-Good</link><category>MVC</category><category>Magic Strings</category><category>Routing</category><title>MVC Routes and Magic Strings == “No Good”</title><description>&lt;p&gt;I live and breathe with ASP.NET MVC, but from the very beginning I’ve been very uncomfortable with the magic string nature of routes, controllers, and actions. I long ago stopped using the various “action” extensions because they are way too prone to fat finger screw ups and moved nearly 100% to using route extensions and putting my routes names into constants so as not to have any chance of fat finger issues, but recently, after reviewing the source code for MVC2, specifically the “LabelFor” extension, I realized there was even another way to limit fat finger screw ups via routing extensions and lambdas.&lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000" size="5"&gt;Note: After some remarks from readers, I have modified the original post&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;a. Add extensions for enabling the new MapRoute extension&lt;/p&gt;  &lt;pre class="brush: csharp;"&gt;public static class RouteCollectionExtensions
{
  public static System.Web.Routing.Route MapRoute&amp;lt;TController&amp;gt;(this System.Web.Routing.RouteCollection routes, string name, string url, Expression&amp;lt;Func&amp;lt;TController, System.Web.Mvc.ActionResult&amp;gt;&amp;gt; action) where TController : System.Web.Mvc.Controller
  {
    return routes.MapRoute&amp;lt;TController&amp;gt;(name, url, action, (object)null /* defaults */);
  }

  public static System.Web.Routing.Route MapRoute&amp;lt;TController&amp;gt;(this System.Web.Routing.RouteCollection routes, string name, string url, Expression&amp;lt;Func&amp;lt;TController, System.Web.Mvc.ActionResult&amp;gt;&amp;gt; action, object defaults) where TController : System.Web.Mvc.Controller
  {
    return routes.MapRoute&amp;lt;TController&amp;gt;(name, url, action, defaults, (object)null /* constraints */);
  }

  public static System.Web.Routing.Route MapRoute&amp;lt;TController&amp;gt;(this System.Web.Routing.RouteCollection routes, string name, string url, Expression&amp;lt;Func&amp;lt;TController, System.Web.Mvc.ActionResult&amp;gt;&amp;gt; action, object defaults, object constraints) where TController : System.Web.Mvc.Controller
  {
    if (routes == null) throw new ArgumentNullException(&amp;quot;routes&amp;quot;);
    if (url == null) throw new ArgumentNullException(&amp;quot;url&amp;quot;);

    System.Web.Routing.RouteValueDictionary defaultValues = new System.Web.Routing.RouteValueDictionary(defaults);

    Type type = typeof(TController);

    #region controllerName
    string controllerName = type.Name;

    if (controllerName.EndsWith(&amp;quot;Controller&amp;quot;, StringComparison.InvariantCultureIgnoreCase)) controllerName = controllerName.Substring(0, controllerName.Length - &amp;quot;Controller&amp;quot;.Length);

    defaultValues[&amp;quot;controller&amp;quot;] = controllerName;
    #endregion

    #region actionName
    System.Reflection.MethodInfo methodInfo = ((MethodCallExpression)action.Body).Method;

    string actionName = methodInfo.Name;

    ActionNameAttribute[] actionNameAttributes = (ActionNameAttribute[])methodInfo.GetCustomAttributes(typeof(ActionNameAttribute), false);

    if ((actionNameAttributes != null) &amp;amp;&amp;amp; (actionNameAttributes.Length &amp;gt; 0)) actionName = actionNameAttributes[0].Name;

    defaultValues[&amp;quot;action&amp;quot;] = actionName;
    #endregion

    System.Web.Routing.Route route = new System.Web.Routing.Route(url, new MvcRouteHandler())
    {
      Defaults = defaultValues,
      Constraints = new System.Web.Routing.RouteValueDictionary(constraints),
      DataTokens = new System.Web.Routing.RouteValueDictionary()
    };

    #region controllerNamespace
    string controllerNamespace = type.FullName;

    controllerNamespace = controllerNamespace.Substring(0, controllerNamespace.Length - (type.Name.Length + 1));

    route.DataTokens[&amp;quot;Namespaces&amp;quot;] = new string[] { controllerNamespace };
    #endregion

    routes.Add(name, route);

    return route;
  }
}&lt;/pre&gt;

&lt;p&gt;b. Create a routes class:&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;public partial class Routes
{
  public static void RegisterRoutes(RouteCollection routes)
  {
    routes.IgnoreRoute(&amp;quot;{resource}.axd/{*pathInfo}&amp;quot;);

    Account.RegisterRoutes(routes);
    Home.RegisterRoutes(routes);
  }
}&lt;/pre&gt;

&lt;p&gt;c. Create a routes class for the HomeController&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;public partial class Routes
{
  public partial class Home
  {
    public class RouteNames
    {
      public static readonly string Index = Guid.NewGuid().ToString(&amp;quot;D&amp;quot;);
      public static readonly string About = Guid.NewGuid().ToString(&amp;quot;D&amp;quot;);
    }

    protected static readonly string URLRoot = &amp;quot;&amp;quot;;

    public static void RegisterRoutes(RouteCollection routes)
    {
      routes.MapRoute&amp;lt;Controllers.HomeController&amp;gt;(RouteNames.About, URLRoot + &amp;quot;About&amp;quot;, controller =&amp;gt; controller.About());
      routes.MapRoute&amp;lt;Controllers.HomeController&amp;gt;(RouteNames.Index, URLRoot, controller =&amp;gt; controller.Index());
    }
  }
}&lt;/pre&gt;

&lt;p&gt;Note: The route names are totally random because they are just meant to be unique keys pointing to specific routes &lt;/p&gt;

&lt;p&gt;d. Create a routes class for the AccountController&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;public partial class Routes
{
  public partial class Account
  {
    public class RouteNames
    {
      public static readonly string LogOn = Guid.NewGuid().ToString(&amp;quot;D&amp;quot;);
      public static readonly string LogOff = Guid.NewGuid().ToString(&amp;quot;D&amp;quot;);
      public static readonly string Register = Guid.NewGuid().ToString(&amp;quot;D&amp;quot;);
      public static readonly string ChangePassword = Guid.NewGuid().ToString(&amp;quot;D&amp;quot;);
      public static readonly string ChangePasswordSuccess = Guid.NewGuid().ToString(&amp;quot;D&amp;quot;);
    }

    protected static readonly string URLRoot = &amp;quot;Account&amp;quot;;

    public static void RegisterRoutes(RouteCollection routes)
    {
      routes.MapRoute&amp;lt;Controllers.AccountController&amp;gt;(RouteNames.LogOn, URLRoot + &amp;quot;LogOn&amp;quot;, c =&amp;gt; c.LogOn());
      routes.MapRoute&amp;lt;Controllers.AccountController&amp;gt;(RouteNames.LogOff, URLRoot + &amp;quot;LogOff&amp;quot;, c =&amp;gt; c.LogOff());
      routes.MapRoute&amp;lt;Controllers.AccountController&amp;gt;(RouteNames.Register, URLRoot + &amp;quot;Register&amp;quot;, c =&amp;gt; c.Register());
      routes.MapRoute&amp;lt;Controllers.AccountController&amp;gt;(RouteNames.ChangePassword, URLRoot + &amp;quot;ChangePassword&amp;quot;, c =&amp;gt; c.ChangePassword());
      routes.MapRoute&amp;lt;Controllers.AccountController&amp;gt;(RouteNames.ChangePasswordSuccess, URLRoot + &amp;quot;ChangePasswordSuccess&amp;quot;, c =&amp;gt; c.ChangePasswordSuccess());
    }
  }
}&lt;/pre&gt;

&lt;p&gt;e. Replace the register routes in Global.asax.cs:&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;public class MvcApplication : System.Web.HttpApplication
{
  protected void Application_Start()
  {
    AreaRegistration.RegisterAllAreas();

    Routes.RegisterRoutes(RouteTable.Routes);
  }
}&lt;/pre&gt;

&lt;p&gt;f. Change all usages of “Action” extensions to “Route” extensions 
  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; In LogOnUserControl.ascx change: 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Html.ActionLink(&amp;quot;Log Off&amp;quot;, &amp;quot;LogOff&amp;quot;, &amp;quot;Account&amp;quot;) 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; To 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Html.RouteLink(&amp;quot;Log Off&amp;quot;, Routes.Account.RouteNames.LogOff) 

  &lt;br /&gt;

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; In AccountController.cs change: 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return RedirectToAction(&amp;quot;Index&amp;quot;, &amp;quot;Home&amp;quot;); 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; To 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return RedirectToRoute(Routes.Home.RouteNames.Index); 

  &lt;/p&gt;</description><pubDate>Mon, 01 Mar 2010 16:35:09 -0500</pubDate></item><item><guid isPermaLink="true">http://www.isi-net.com/Blogs/Ron-Muth/Extending-Enumerations</guid><link>http://www.isi-net.com/Blogs/Ron-Muth/Extending-Enumerations</link><title>Extending Enumerations (fun with Enum&lt;enum&gt; and Attributes)</title><description>&lt;p&gt;&lt;font size="2"&gt;Enums are just great, but not very user friendly once you get past simple one word names. In this article I will show you how to make them far more usable via Attributes. We will be able to give them a user friendly name, parse strings to enum based on the enum’s value, member description, and user friendly description, and created orders lists and dictionaries.&lt;/font&gt;&lt;/p&gt;  &lt;pre class="brush: csharp;"&gt;public enum enRates
{
  Main = 0, //Hourly
  OffSiteFullDay = 22, //Off Site Full Day
  OnSiteFullDay = 21, //On Site Full Day
  OffSite = 202, //Off Site Hourly
  OnSite = 201, //On Site Hourly
}&lt;/pre&gt;

&lt;p&gt;&lt;font size="2"&gt;Notice how the values are not orders the way I want them and the names don’t match the user descriptions.&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font size="2"&gt;Now lets see what we can do by extending them through attributes:&lt;/font&gt;&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;public enum enRates
{
  [EnumInformation(&amp;quot;Hourly&amp;quot;, true, 1)] Main = 0,
  [EnumInformation(&amp;quot;Off Site Full Day&amp;quot;, true, 4)] OffSiteFullDay = 22,
  [EnumInformation(&amp;quot;On Site Full Day&amp;quot;, true, 5)] OnSiteFullDay = 21,
  [EnumInformation(&amp;quot;Off Site Hourly&amp;quot;, true, 2)] OffSite = 202,
  [EnumInformation(&amp;quot;On Site Hourly&amp;quot;, true, 3)] OnSite = 201,
}&lt;/pre&gt;

&lt;p&gt;&lt;font size="2"&gt;Now lets see what we can do with these attributes&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font size="2"&gt;a. Get a user friendly description for an enum&lt;/font&gt;&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;Console.WriteLine(&amp;quot;Enum&amp;lt;enRates&amp;gt;.Description(enRates.Main) = {0}&amp;quot;, Enum&amp;lt;enRates&amp;gt;.Description(enRates.Main));&lt;/pre&gt;

&lt;p&gt;&lt;font size="2"&gt;gets:&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;pre style="background-color: black"&gt;&lt;font color="#ffffff" size="2" face="Courier New"&gt;&lt;strong&gt;Enum&amp;lt;enRates&amp;gt;.Description(enRates.Main) = Hourly&lt;/strong&gt;&lt;/font&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;font size="2"&gt;b. Parse values to get enum&lt;/font&gt;&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;Console.WriteLine(&amp;quot;Enum&amp;lt;enRates&amp;gt;.Parse(\&amp;quot;Main\&amp;quot;, enRates.OnSiteFullDay) = {0}&amp;quot;, Enum&amp;lt;enRates&amp;gt;.Parse(&amp;quot;Main&amp;quot;, enRates.OnSiteFullDay));
Console.WriteLine(&amp;quot;Enum&amp;lt;enRates&amp;gt;.Parse(\&amp;quot;Hourly\&amp;quot;, enRates.OnSiteFullDay) = {0}&amp;quot;, Enum&amp;lt;enRates&amp;gt;.Parse(&amp;quot;Hourly&amp;quot;, enRates.OnSiteFullDay));
Console.WriteLine(&amp;quot;Enum&amp;lt;enRates&amp;gt;.Parse(\&amp;quot;0\&amp;quot;, enRates.OnSiteFullDay) = {0}&amp;quot;, Enum&amp;lt;enRates&amp;gt;.Parse(&amp;quot;0&amp;quot;, enRates.OnSiteFullDay));
Console.WriteLine(&amp;quot;Enum&amp;lt;enRates&amp;gt;.Parse(\&amp;quot;On Site Full Day\&amp;quot;, enRates.OnSiteFullDay) = {0}&amp;quot;, Enum&amp;lt;enRates&amp;gt;.Parse(&amp;quot;On Site Full Day&amp;quot;, enRates.OnSiteFullDay));
Console.WriteLine(&amp;quot;Enum&amp;lt;enRates&amp;gt;.Parse(\&amp;quot;OnSiteFullDay\&amp;quot;, enRates.OnSiteFullDay) = {0}&amp;quot;, Enum&amp;lt;enRates&amp;gt;.Parse(&amp;quot;OnSiteFullDay&amp;quot;, enRates.OnSiteFullDay));
Console.WriteLine(&amp;quot;Enum&amp;lt;enRates&amp;gt;.Parse(\&amp;quot;UnKnown\&amp;quot;, enRates.OnSiteFullDay) = {0}&amp;quot;, Enum&amp;lt;enRates&amp;gt;.Parse(&amp;quot;UnKnown&amp;quot;, enRates.OnSiteFullDay));&lt;/pre&gt;

&lt;p&gt;&lt;font size="2"&gt;gets:&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;pre style="background-color: black"&gt;&lt;font color="#ffffff" size="2" face="Courier New"&gt;&lt;strong&gt;Enum&lt;enrates&gt;.Parse(&amp;quot;Main&amp;quot;, enRates.OnSiteFullDay) = Main
Enum&lt;enrates&gt;.Parse(&amp;quot;Hourly&amp;quot;, enRates.OnSiteFullDay) = Main
Enum&lt;enrates&gt;.Parse(&amp;quot;0&amp;quot;, enRates.OnSiteFullDay) = Main
Enum&lt;enrates&gt;.Parse(&amp;quot;On Site Full Day&amp;quot;, enRates.OnSiteFullDay) = OnSiteFullDay
Enum&lt;enrates&gt;.Parse(&amp;quot;OnSiteFullDay&amp;quot;, enRates.OnSiteFullDay) = OnSiteFullDay
Enum&lt;enrates&gt;.Parse(&amp;quot;UnKnown&amp;quot;, enRates.OnSiteFullDay) = OnSiteFullDay&lt;/strong&gt;&lt;/font&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;font size="2"&gt;c. Get an ordered list for an enum (notice the order its ordered by the third value in the attribute, not the value of the member)&lt;/font&gt;&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;Console.WriteLine(&amp;quot;ToList:&amp;quot;);
List&amp;lt;enRates&amp;gt; list = Enum&amp;lt;enRates&amp;gt;.ToList();
foreach (enRates rate in list)
{
  Console.WriteLine(&amp;quot;  {0}&amp;quot;, rate);
}&lt;/pre&gt;

&lt;p&gt;&lt;font size="2"&gt;gets:&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;pre style="background-color: black"&gt;&lt;font color="#ffffff" size="2" face="Courier New"&gt;&lt;strong&gt;ToList:
  Main
  OffSite
  OnSite
  OffSiteFullDay
  OnSiteFullDay&lt;/strong&gt;&lt;/font&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;font size="2"&gt;d. Get an ordered user friendly list of descriptions for an enum&lt;/font&gt;&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;Console.WriteLine(&amp;quot;ToStringList:&amp;quot;);
List&amp;lt;string&amp;gt; stringList = Enum&amp;lt;enRates&amp;gt;.ToStringList();
foreach (string rate in stringList)
{
  Console.WriteLine(&amp;quot;  {0}&amp;quot;, rate);
}&lt;/pre&gt;

&lt;p&gt;&lt;font size="2"&gt;gets:&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;pre style="background-color: black"&gt;&lt;font color="#ffffff" size="2" face="Courier New"&gt;&lt;strong&gt;ToStringList:
  Hourly
  Off Site Hourly
  On Site Hourly
  Off Site Full Day
  On Site Full Day&lt;/strong&gt;&lt;/font&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;font size="2"&gt;e. Get an ordered user friendly dictionary with the member string value and user friendly value&lt;/font&gt;&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;Dictionary&amp;lt;string, string&amp;gt; stringDictionary = Enum&amp;lt;enRates&amp;gt;.ToStringDictionary();
foreach (KeyValuePair&amp;lt;string, string&amp;gt; rate in stringDictionary)
{
  Console.WriteLine(&amp;quot;  {0} = {1}&amp;quot;, rate.Key, rate.Value);
}&lt;/pre&gt;

&lt;p&gt;&lt;font size="2"&gt;gets:&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;pre style="background-color: black"&gt;&lt;font color="#ffffff" size="2" face="Courier New"&gt;&lt;strong&gt;ToStringDictionary:
  Main = Hourly
  OffSite = Off Site Hourly
  OnSite = On Site Hourly
  OffSiteFullDay = Off Site Full Day
  OnSiteFullDay = On Site Full Day&lt;/strong&gt;&lt;/font&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;font size="2"&gt;f. Get an ordered user friendly dictionary with the int value of the member and user friendly value&lt;/font&gt;&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;Dictionary&amp;lt;int, string&amp;gt; dictionary = Enum&amp;lt;enRates&amp;gt;.ToDictionary();
foreach (KeyValuePair&amp;lt;int, string&amp;gt; rate in dictionary)
{
  Console.WriteLine(&amp;quot;  {0} = {1}&amp;quot;, rate.Key, rate.Value);
}&lt;/pre&gt;

&lt;p&gt;&lt;font size="2"&gt;gets:&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;pre style="background-color: black"&gt;&lt;font color="#ffffff" size="2" face="Courier New"&gt;&lt;strong&gt;ToDictionary:
  0 = Hourly
  202 = Off Site Hourly
  201 = On Site Hourly
  22 = Off Site Full Day
  21 = On Site Full Day&lt;/strong&gt;&lt;/font&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;font size="2"&gt;g. Get an ordered user friendly dictionary with the member and user friendly value&lt;/font&gt;&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;Dictionary&amp;lt;enRates, string&amp;gt; valueDictionary = Enum&amp;lt;enRates&amp;gt;.ToValueDictionary();
foreach (KeyValuePair&amp;lt;enRates, string&amp;gt; rate in valueDictionary)
{
  Console.WriteLine(&amp;quot;  {0} = {1}&amp;quot;, rate.Key, rate.Value);
}&lt;/pre&gt;

&lt;p&gt;&lt;font size="2"&gt;gets:&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;pre style="background-color: black"&gt;&lt;font color="#ffffff" size="2" face="Courier New"&gt;&lt;strong&gt;ToValueDictionary:
  Main = Hourly
  OffSite = Off Site Hourly
  OnSite = On Site Hourly
  OffSiteFullDay = Off Site Full Day
  OnSiteFullDay = On Site Full Day&lt;/strong&gt;&lt;/font&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;font size="2"&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font size="2"&gt;Here’s the source code:&lt;/font&gt;&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
public class EnumInformationAttribute : Attribute
{
  public string Description { get; internal set; }
  public bool Active { get; internal set; }
  public int? Order { get; internal set; }

  public EnumInformationAttribute(string description, bool active, int? order)
  {
    Description = description;
    Active = active;
    Order = order;
  }

  public EnumInformationAttribute(string description, bool active, int order) : this(description, active, (int?)order) { }

  public EnumInformationAttribute(string description, bool active) : this(description, active, null) { }

  public EnumInformationAttribute(string description) : this(description, true, null) { }
}

public class EnumParseException : Exception
{
  public EnumParseException() : base() { }
  public EnumParseException(string message) : base(message) { }
  public EnumParseException(string message, Exception innerException) : base(message, innerException) { }
}

public static class Enum&amp;lt;T&amp;gt;
{
  #region EnumInformation
  public class EnumInformation
  {
    public T Value { get; internal set; }
    public string DefaultDescription { get; internal set; }
    public string WithSpaces { get; internal set; }
    public bool Active { get; internal set; }
    public int Order { get; internal set; }

    internal EnumInformation(T value, string defaultDescription, string withSpaces, bool active, int order)
    {
      Value = value;
      DefaultDescription = defaultDescription;
      WithSpaces = withSpaces;
      Active = active;
      Order = order;
    }

    internal EnumInformation(T value) : this(value, value.ToString(), RemoveTitleCase(value.ToString()), true, Convert.ToInt32(value)) { }
  }
  #endregion

  #region Static Constructor
  internal static List&amp;lt;EnumInformation&amp;gt; _List = null;
  internal static Dictionary&amp;lt;T, EnumInformation&amp;gt; _Descriptions = null;
  internal static Dictionary&amp;lt;string, T&amp;gt; _LookupValues = null;

  static Enum()
  {
    string key;
    Type type = typeof(T);
    EnumInformationAttribute[] enumInformationAttributes = null;

    EnumInformation enumInformation = null;

    _List = new List&amp;lt;EnumInformation&amp;gt;();
    _Descriptions = new Dictionary&amp;lt;T, EnumInformation&amp;gt;();
    _LookupValues = new Dictionary&amp;lt;string, T&amp;gt;();

    if (type.IsGenericType &amp;amp;&amp;amp; type.GetGenericTypeDefinition().Equals(typeof(Nullable&amp;lt;&amp;gt;))) type = (new System.ComponentModel.NullableConverter(type)).UnderlyingType;

    if (!(type.IsEnum)) throw new Exception(&amp;quot;Cannot create Enum&amp;lt;T&amp;gt; when T is not a Enum&amp;quot;);

    foreach (T value in Enum.GetValues(type))
    {
      enumInformation = new EnumInformation(value);
      enumInformationAttributes = (EnumInformationAttribute[])(type.GetField(value.ToString()).GetCustomAttributes(typeof(EnumInformationAttribute), false));

      if (enumInformationAttributes.Length &amp;gt; 0)
      {
        enumInformation.DefaultDescription = enumInformationAttributes[0].Description;
        enumInformation.WithSpaces = enumInformationAttributes[0].Description;
        enumInformation.Active = enumInformationAttributes[0].Active;
        enumInformation.Order = enumInformationAttributes[0].Order ?? enumInformation.Order;
      }

      _List.Add(enumInformation);
      _Descriptions.Add(value, enumInformation);

      key = Convert.ToInt32(value).ToString().ToLower(); if (!_LookupValues.ContainsKey(key)) _LookupValues.Add(key, value);
      key = enumInformation.Value.ToString().ToLower(); if (!_LookupValues.ContainsKey(key)) _LookupValues.Add(key, value);
      key = enumInformation.DefaultDescription.ToLower(); if (!_LookupValues.ContainsKey(key)) _LookupValues.Add(key, value);
      key = enumInformation.WithSpaces.ToLower(); if (!_LookupValues.ContainsKey(key)) _LookupValues.Add(key, value);
    }

    _List.Sort((x, y) =&amp;gt; x.Order.CompareTo(y.Order));
  }
  #endregion

  #region RemoveTitleCase
  private static string RemoveTitleCase(string value)
  {
    string result = value;

    result = System.Text.RegularExpressions.Regex.Replace(result, @&amp;quot;(?&amp;lt;begin&amp;gt;(\w*?))(?&amp;lt;end&amp;gt;[A-Z]+)&amp;quot;, string.Format(@&amp;quot;${{begin}}{0}${{end}}&amp;quot;, &amp;quot; &amp;quot;)).Trim();

    return result;
  }
  #endregion

  #region Description
  public static string Description(T value)
  {
    return Description(value, true);
  }
  public static string Description(T value, bool addSpaceBetweenWords)
  {
    string result = string.Empty;

    if (_Descriptions.ContainsKey(value)) result = (addSpaceBetweenWords ? _Descriptions[value].WithSpaces : _Descriptions[value].DefaultDescription);

    return result;
  }
  #endregion

  #region Count
  public static int Count()
  {
    return _Descriptions.Count;
  }
  #endregion

  #region Parse
  public static T Parse(string value)
  {
    T result;

    value = (value ?? string.Empty).ToLower();

    if (_LookupValues.ContainsKey(value))
    {
      result = _LookupValues[value];
    }
    else
    {
      throw new EnumParseException(string.Format(&amp;quot;No Match for \&amp;quot;{0}\&amp;quot; in \&amp;quot;{1}\&amp;quot;&amp;quot;, value, typeof(T).Name));
    }

    return result;
  }

  public static T Parse(string value, T defaultValue)
  {
    T result;

    value = (value ?? string.Empty).ToLower();

    if (_LookupValues.ContainsKey(value))
      result = _LookupValues[value];
    else
      result = defaultValue;

    return result;
  }

  public static bool TryParse(string value, out T parsedValue)
  {
    bool result = false;

    value = (value ?? string.Empty).ToLower();

    if (_LookupValues.ContainsKey(value))
    {
      parsedValue = _LookupValues[value];
      result = true;
    }
    else
    {
      parsedValue = default(T);
    }

    return result;
  }
  #endregion

  #region ToList
  public static List&amp;lt;T&amp;gt; ToList()
  {
    return ToList(false);
  }

  public static List&amp;lt;T&amp;gt; ToList(bool activeOnly)
  {
    List&amp;lt;T&amp;gt; result = new List&amp;lt;T&amp;gt;();

    foreach (EnumInformation enumInformation in _List)
    {
      if (!activeOnly || enumInformation.Active) result.Add(enumInformation.Value);
    }

    return result;
  }
  #endregion

  #region ToStringList
  public static List&amp;lt;string&amp;gt; ToStringList()
  {
    return ToStringList(true);
  }

  public static List&amp;lt;string&amp;gt; ToStringList(bool addSpaceBetweenWords)
  {
    return ToStringList(addSpaceBetweenWords, false);
  }

  public static List&amp;lt;string&amp;gt; ToStringList(bool addSpaceBetweenWords, bool activeOnly)
  {
    List&amp;lt;string&amp;gt; result = new List&amp;lt;string&amp;gt;();

    foreach (EnumInformation enumInformation in _List)
    {
      if (!activeOnly || enumInformation.Active) result.Add((addSpaceBetweenWords ? enumInformation.WithSpaces : enumInformation.DefaultDescription));
    }

    return result;
  }
  #endregion

  #region ToStringDictionary
  public static Dictionary&amp;lt;string, string&amp;gt; ToStringDictionary()
  {
    return ToStringDictionary(true);
  }

  public static Dictionary&amp;lt;string, string&amp;gt; ToStringDictionary(bool addSpaceBetweenWords)
  {
    return ToStringDictionary(addSpaceBetweenWords, false);
  }

  public static Dictionary&amp;lt;string, string&amp;gt; ToStringDictionary(bool addSpaceBetweenWords, bool useDescriptionAsKey)
  {
    return ToStringDictionary(addSpaceBetweenWords, useDescriptionAsKey, false);
  }

  public static Dictionary&amp;lt;string, string&amp;gt; ToStringDictionary(bool addSpaceBetweenWords, bool useDescriptionAsKey, bool activeOnly)
  {
    Dictionary&amp;lt;string, string&amp;gt; result = new Dictionary&amp;lt;string, string&amp;gt;();

    foreach (EnumInformation enumInformation in _List)
    {
      string description = (addSpaceBetweenWords ? enumInformation.WithSpaces : enumInformation.DefaultDescription);
      string key = (useDescriptionAsKey ? description : enumInformation.Value.ToString());

      if (!activeOnly || enumInformation.Active) result.Add(key, description);
    }

    return result;
  }
  #endregion

  #region ToDictionary
  public static Dictionary&amp;lt;int, string&amp;gt; ToDictionary()
  {
    return ToDictionary(true);
  }

  public static Dictionary&amp;lt;int, string&amp;gt; ToDictionary(bool addSpaceBetweenWords)
  {
    return ToDictionary(addSpaceBetweenWords, false);
  }

  public static Dictionary&amp;lt;int, string&amp;gt; ToDictionary(bool addSpaceBetweenWords, bool activeOnly)
  {
    Dictionary&amp;lt;int, string&amp;gt; result = new Dictionary&amp;lt;int, string&amp;gt;();

    foreach (EnumInformation enumInformation in _List)
    {
      if (!activeOnly || enumInformation.Active) result.Add(Convert.ToInt32(enumInformation.Value), (addSpaceBetweenWords ? enumInformation.WithSpaces : enumInformation.DefaultDescription));
    }

    return result;
  }
  #endregion

  #region ToValueDictionary
  public static Dictionary&amp;lt;T, string&amp;gt; ToValueDictionary()
  {
    return ToValueDictionary(true);
  }

  public static Dictionary&amp;lt;T, string&amp;gt; ToValueDictionary(bool addSpaceBetweenWords)
  {
    return ToValueDictionary(addSpaceBetweenWords, false);
  }

  public static Dictionary&amp;lt;T, string&amp;gt; ToValueDictionary(bool addSpaceBetweenWords, bool activeOnly)
  {
    Dictionary&amp;lt;T, string&amp;gt; result = new Dictionary&amp;lt;T, string&amp;gt;();

    foreach (EnumInformation enumInformation in _List)
    {
      if (!activeOnly || enumInformation.Active) result.Add(enumInformation.Value, (addSpaceBetweenWords ? enumInformation.WithSpaces : enumInformation.DefaultDescription));
    }

    return result;
  }
  #endregion
}&lt;/pre&gt;</description><pubDate>Thu, 22 Oct 2009 21:35:15 -0400</pubDate></item><item><guid isPermaLink="true">http://www.isi-net.com/Blogs/Ron-Muth/How-to-use-an-ASPNET-SiteMapProvider-to-produce-a-XML-SiteMap-for-Google-Yahoo-Bing-etc</guid><link>http://www.isi-net.com/Blogs/Ron-Muth/How-to-use-an-ASPNET-SiteMapProvider-to-produce-a-XML-SiteMap-for-Google-Yahoo-Bing-etc</link><category>Google SiteMap</category><category>MvcSiteMapProvider</category><category>Bing SiteMap</category><category>Yahoo SiteMap</category><category>MvcSiteMap</category><category>SiteMap</category><category>SiteMapProvider</category><title>How to use an ASP.NET SiteMapProvider to produce a XML SiteMap for Google, Yahoo, Bing, etc</title><description>&lt;p&gt;More often I’m being asked to provide “SiteMap.xml”s for sites we work on, and up until recently we had been hand rolling the xml and placing them in static documents on our sites. This is fine but seemed a little silly because ASP.NET has a built in SiteMap mechanism. So we decided to do something about using it for auto generating the SiteMap.xml.&lt;/p&gt;  &lt;p&gt;My example is using Maarten Balliauw’s awesome MvcSiteMap available at &lt;a title="http://mvcsitemap.codeplex.com/" href="http://mvcsitemap.codeplex.com/"&gt;http://mvcsitemap.codeplex.com/&lt;/a&gt; but the conversion code works perfectly fine with the built in SiteMapProvider in ASP.NET.&lt;/p&gt;  &lt;p&gt;Using the following class we can generate the XML object representing the SiteMap. &lt;/p&gt;  &lt;pre class="brush: csharp;"&gt;  public class SiteMapXMLNode
  {
    public enum enChangeFrequency
    {
      NoneGiven,
      Always,
      Hourly,
      Daily,
      Weekly,
      Monthly,
      Yearly,
      Never
    }

    [System.Xml.Serialization.XmlElement(ElementName = &amp;quot;loc&amp;quot;)]
    public string URL;

    #region Last Modified
    [System.Xml.Serialization.XmlIgnore]
    public DateTime LastModified;
    [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
    [System.Xml.Serialization.XmlElement(ElementName = &amp;quot;lastmod&amp;quot;)]
    public string __LastModified
    {
      get { return (LastModified == DateTime.MinValue ? null : string.Format(&amp;quot;{0:yyyy-MM-dd}&amp;quot;, LastModified)); }
      set { LastModified = DateTime.MinValue; } //Note: This property will never be deserialized
    }
    #endregion

    #region Change Frequency
    [System.Xml.Serialization.XmlIgnore]
    public enChangeFrequency ChangeFrequency;
    [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
    [System.Xml.Serialization.XmlElement(ElementName = &amp;quot;changefreq&amp;quot;)]
    public string __ChangeFrequency
    {
      get { return (ChangeFrequency == enChangeFrequency.NoneGiven ? null : ChangeFrequency.ToString().ToLower()); }
      set { ChangeFrequency = enChangeFrequency.NoneGiven; } //Note: This property will never be deserialized
    }
    #endregion

    #region Priority
    [System.Xml.Serialization.XmlIgnore]
    public decimal? Priority;
    [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
    [System.Xml.Serialization.XmlElement(ElementName = &amp;quot;priority&amp;quot;)]
    public string __Priority
    {
      get { return (!Priority.HasValue ? null : string.Format(&amp;quot;{0:0.0}&amp;quot;, Priority)); }
      set { Priority = null; } //Note: This property will never be deserialized
    }
    #endregion

    public SiteMapXMLNode()
    {
      URL = null;
      LastModified = DateTime.MinValue;
      ChangeFrequency = enChangeFrequency.NoneGiven;
      Priority = null;
    }

    public SiteMapXMLNode(System.Web.SiteMapNode node)
      : this()
    {
      UriBuilder uriBuilder = new UriBuilder(System.Web.HttpContext.Current.Request.Url);
      uriBuilder.Path = node.Url;
      URL = uriBuilder.ToString();
    }
  }

  [System.Xml.Serialization.XmlRootAttribute(Namespace = &amp;quot;http://www.sitemaps.org/schemas/sitemap/0.9&amp;quot;, IsNullable = false, ElementName = &amp;quot;urlset&amp;quot;)]
  public class SiteMapXML
  {
    private List&amp;lt;SiteMapXMLNode&amp;gt; Nodes;

    #region &amp;quot;urls&amp;quot;
    [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
    [System.Xml.Serialization.XmlElementAttribute(&amp;quot;url&amp;quot;)]
    public SiteMapXMLNode[] __Nodes
    {
      get
      {
        return Nodes.ToArray();
      }
      set
      {
        Nodes.Clear();
        Nodes.AddRange(value);
      }
    }
    #endregion

    public SiteMapXML()
    {
      Nodes = new List&amp;lt;SiteMapXMLNode&amp;gt;();
    }

    public SiteMapXML(System.Web.SiteMapNode rootNode)
      : this()
    {
      Add(rootNode);
    }

    public void Add(System.Web.SiteMapNode rootNode)
    {
      Nodes.Add(new SiteMapXMLNode(rootNode));

      if (rootNode.HasChildNodes)
      {
        foreach (System.Web.SiteMapNode node in rootNode.ChildNodes)
        {
          if (node.IsAccessibleToUser(System.Web.HttpContext.Current)) Add(node);
        }
      }
    }
  }&lt;/pre&gt;

&lt;p&gt;Then we use this action for MVC&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;    public ActionResult SiteMapXML()
    {
      ActionResult result = null;

      SiteMapXML siteMapXML = new SiteMapXML(System.Web.SiteMap.RootNode);

      using (System.IO.MemoryStream oStream = new System.IO.MemoryStream())
      {
        System.Xml.Serialization.XmlSerializer xmlSerializer = new System.Xml.Serialization.XmlSerializer(typeof(SiteMapXML));
        xmlSerializer.Serialize(oStream, siteMapXML);
        oStream.Flush();
        xmlSerializer = null;

        System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding(false);

        result = new ContentResult() { ContentType = &amp;quot;text/xml&amp;quot;, Content = UTF8.GetString(oStream.ToArray()), ContentEncoding = UTF8 };
      }

      return result;
    }&lt;/pre&gt;

&lt;p&gt;Or this code behind for ASP.NET&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;    protected void Page_Load(object sender, EventArgs e)
    {
      Response.Clear();

      Response.ContentType = &amp;quot;text/xml&amp;quot;;

      SiteMapXML siteMapXML = new SiteMapXML(System.Web.SiteMap.RootNode);

      System.Xml.Serialization.XmlSerializer xmlSerializer = new System.Xml.Serialization.XmlSerializer(typeof(SiteMapXML));
      xmlSerializer.Serialize(Response.OutputStream, siteMapXML);
      xmlSerializer = null;

      Response.Flush();

      Response.End();
    }&lt;/pre&gt;

&lt;p&gt;It’s really that simple&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;ToDo: add Attributes and elements to the SiteMap definition so we can take advantage of the additional Attributes in the SiteMap XSD (“lastmod”, “changefreq” and “priority”)&lt;/p&gt;</description><pubDate>Fri, 16 Oct 2009 15:47:54 -0400</pubDate></item><item><guid isPermaLink="true">http://www.isi-net.com/Blogs/Ron-Muth/NAnt-task-for-Code-Signing</guid><link>http://www.isi-net.com/Blogs/Ron-Muth/NAnt-task-for-Code-Signing</link><category>Code Signing</category><category>SignTool</category><category>NAnt</category><title>NAnt task for Code Signing</title><description>&lt;p&gt;At ISI we like to sign our assemblies for many reasons, but chief among them is so that we know and can prove that we compiled the assembly. The vast majority of our clients purchase the source code to the applications we work on for them, thus, from time to time, we’ve had problems where a deployed app doesn’t work but the assemblies we delivered work perfectly, and later find out that some one on the client side made a “minor” code change and deployed their own assemblies ……&lt;/p&gt;  &lt;p&gt;Thus comes in one of the great reasons for code signing ……&lt;/p&gt;  &lt;p&gt;We are also big fans of NAnt for builds, so below is the code to our NAnt task for signing assemblies:&lt;/p&gt;  &lt;pre class="brush: csharp;"&gt;using System;
using System.Collections.Generic;
using System.Text;

namespace ISI.NAnt.Contrib.Tasks
{
  [global::NAnt.Core.Attributes.TaskName(&amp;quot;ISI.SignTool&amp;quot;)]
  public class SignTool : global::NAnt.Core.Tasks.ExternalProgramBase
  {
    [global::NAnt.Core.Attributes.BuildElement(&amp;quot;Assemblies&amp;quot;, Required = true)]
    public virtual global::NAnt.Core.Types.FileSet Assemblies { get; set; }

    [global::NAnt.Core.Attributes.TaskAttribute(&amp;quot;CertificateFileName&amp;quot;, Required = true)]
    public string CertificateFileName { get; set; }

    [global::NAnt.Core.Attributes.TaskAttribute(&amp;quot;CertificatePasswordFileName&amp;quot;, Required = true)]
    public string CertificatePasswordFileName { get; set; }

    [global::NAnt.Core.Attributes.TaskAttribute(&amp;quot;TimeServerUrl&amp;quot;, Required = false)]
    public string TimeServerUrl { get; set; }

    public SignTool()
    {
      using (Microsoft.Win32.RegistryKey regKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@&amp;quot;SOFTWARE\Microsoft\Microsoft SDKs\Windows&amp;quot;))
      {
       if (regKey != null)
        {
          string installRoot = regKey.GetValue(&amp;quot;CurrentInstallFolder&amp;quot;).ToString();
          if (!string.IsNullOrEmpty(installRoot)) base.ExeName = System.IO.Path.Combine(installRoot, @&amp;quot;bin\signtool.exe&amp;quot;);
        }
      }

      TimeServerUrl = @&amp;quot;http://timestamp.comodoca.com/authenticode&amp;quot;;
    }

    public override string ProgramArguments
    {
      get { return string.Empty; }
    }

    protected override void ExecuteTask()
    {
      bool doSignCode = true;

      Log(global::NAnt.Core.Level.Info, &amp;quot;Code Sign&amp;quot;);

      if (string.IsNullOrEmpty(CertificateFileName) || !System.IO.File.Exists(CertificateFileName))
      {
        Log(global::NAnt.Core.Level.Error, &amp;quot;Missing Certificate: {0}&amp;quot;, CertificateFileName);
        doSignCode = false;
      }

      if (string.IsNullOrEmpty(CertificatePasswordFileName) || !System.IO.File.Exists(CertificatePasswordFileName))
      {
        Log(global::NAnt.Core.Level.Error, &amp;quot;Missing Certificate Password: {0}&amp;quot;, CertificatePasswordFileName);
        doSignCode = false;
      }

      if (string.IsNullOrEmpty(base.ExeName) || !System.IO.File.Exists(base.ExeName))
      {
        Log(global::NAnt.Core.Level.Error, &amp;quot;Missing Sign Tool: {0}&amp;quot;, base.ExeName);
        doSignCode = false;
      }

      if (doSignCode)
      {
        string certificatePassword = null;
        using (System.IO.StreamReader streamReader = new System.IO.StreamReader(CertificatePasswordFileName)) certificatePassword = streamReader.ReadLine();

        base.Arguments.Clear();
        base.Arguments.Add(new global::NAnt.Core.Types.Argument(&amp;quot;sign&amp;quot;));
        base.Arguments.Add(new global::NAnt.Core.Types.Argument(string.Format(&amp;quot;/f \&amp;quot;{0}\&amp;quot;&amp;quot;, CertificateFileName)));
        base.Arguments.Add(new global::NAnt.Core.Types.Argument(string.Format(&amp;quot;/p \&amp;quot;{0}\&amp;quot;&amp;quot;, certificatePassword)));
        base.Arguments.Add(new global::NAnt.Core.Types.Argument(string.Format(&amp;quot;/t \&amp;quot;{0}\&amp;quot;&amp;quot;, TimeServerUrl)));

        doSignCode = false;
        foreach (string assemblyFileName in Assemblies.FileNames)
        {
          Log(global::NAnt.Core.Level.Info, &amp;quot;  Signing '{0}'.&amp;quot;, assemblyFileName);

          global::NAnt.Core.Types.Argument fileArgument = new global::NAnt.Core.Types.Argument();
          base.Arguments.Add(fileArgument);
          fileArgument.File = new System.IO.FileInfo(assemblyFileName);

          doSignCode = true;
        }

        if (doSignCode)
          base.ExecuteTask();
        else
          Log(global::NAnt.Core.Level.Error, &amp;quot;No Files Found&amp;quot;);
      }
    }
  }
}&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;and add it to your build script:&lt;/p&gt;

&lt;pre class="brush: xml;"&gt;    &amp;lt;loadtasks assembly=&amp;quot;/path_to/ISI.NAnt.Contrib.dll&amp;quot; /&amp;gt;
    &amp;lt;ISI.SignTool CertificateFileName=&amp;quot;/path_to/Certificate.pfx&amp;quot;
                  CertificatePasswordFileName=&amp;quot;/path_to/Certificate.pwd&amp;quot;
      &amp;gt;
      &amp;lt;Assemblies basedir=&amp;quot;${publish.dir}&amp;quot;&amp;gt;
        &amp;lt;include name=&amp;quot;ISI.*.dll&amp;quot; /&amp;gt;
        &amp;lt;include name=&amp;quot;ISI.*.exe&amp;quot; /&amp;gt;
      &amp;lt;/Assemblies&amp;gt;
    &amp;lt;/ISI.SignTool&amp;gt;&lt;/pre&gt;

&lt;p&gt;Certificate.pfx is the code signing certificate 
  &lt;br /&gt;Certificate.pwd is the plain text password for that certificate&lt;/p&gt;

&lt;p&gt;If these files do not exist, the SignTool task just skips itself&lt;/p&gt;

&lt;p&gt;Note, the Certificate.pfx and Certificate.pwd files only exists on our official release build system.&lt;/p&gt;</description><pubDate>Fri, 19 Jun 2009 20:35:45 -0400</pubDate></item><item><guid isPermaLink="true">http://www.isi-net.com/Blogs/Ron-Muth/Multiple-configuration-section-for-different-developers</guid><link>http://www.isi-net.com/Blogs/Ron-Muth/Multiple-configuration-section-for-different-developers</link><category>web.config</category><category>app.config</category><category>AppSettings</category><category>System.Configuration</category><title>Multiple configuration section for different developers</title><description>&lt;p&gt;Building on my last post &lt;a href="/Blogs/Ron-Muth/Custom-Configuration-section"&gt;Custom Configuration section&lt;/a&gt;….&lt;/p&gt;  &lt;p&gt;We often have multiple developers working on the same project but want to be running under different configurations. We do this by adding their machine name to custom config section and replacing the static constructor of the custom config section:&lt;/p&gt;  &lt;pre class="brush: csharp;"&gt;    static Configuration()
    {
      const string ConfigurationSectionName = &amp;quot;ISI.HAPP.API.Configuration&amp;quot;;

      Current = null;
      if (Current == null) Current = (Configuration)(System.Configuration.ConfigurationManager.GetSection(string.Format(&amp;quot;{0}.{1}&amp;quot;, ConfigurationSectionName, System.Environment.MachineName.ToLower())));
      if (Current == null) Current = (Configuration)(System.Configuration.ConfigurationManager.GetSection(ConfigurationSectionName));
      if (Current == null) throw new Exception(string.Format(&amp;quot;Missing {0} Configuration Section&amp;quot;, ConfigurationSectionName));
    }&lt;/pre&gt;

&lt;p&gt;and adding a new config section in the app/web.config:&lt;/p&gt;

&lt;pre class="brush: xml;"&gt;  &amp;lt;ISI.HAPP.API.Configuration.ronmuth&amp;gt;
    &amp;lt;CompanyName&amp;gt;ISI Ron Muth&amp;lt;/CompanyName&amp;gt;
    &amp;lt;Authenication&amp;gt;
      &amp;lt;UseNTPermissions&amp;gt;true&amp;lt;/UseNTPermissions&amp;gt;
      &amp;lt;DefaultNTDomain&amp;gt;ISI&amp;lt;/DefaultNTDomain&amp;gt;
    &amp;lt;/Authenication&amp;gt;
  &amp;lt;/ISI.HAPP.API.Configuration.ronmuth&amp;gt;&lt;/pre&gt;</description><pubDate>Fri, 19 Jun 2009 20:20:24 -0400</pubDate></item><item><guid isPermaLink="true">http://www.isi-net.com/Blogs/Ron-Muth/Custom-Configuration-section</guid><link>http://www.isi-net.com/Blogs/Ron-Muth/Custom-Configuration-section</link><category>web.config</category><category>app.config</category><category>AppSettings</category><category>System.Configuration</category><title>Custom Configuration section</title><description>&lt;p&gt;I HATE “ConfigurationSettings.AppSettings” !!!!&lt;/p&gt;  &lt;p&gt;That being said, .NET gives us a great alternative that no one talks about, custom configuration sections. It gives us a fully nestable and strongly typed config section.&lt;/p&gt;  &lt;p&gt;Add a new class:&lt;/p&gt;  &lt;pre class="brush: csharp;"&gt;using System;
using System.Configuration;

namespace ISI.HAPP.API
{
  public sealed partial class Configuration : ConfigurationSection
  {
    public class AuthenicationParameters : ConfigurationElement
    {
      #region UseNTPermissions
      /// &amp;lt;summary&amp;gt;
      /// Gets or sets the UseNTPermissions.
      /// &amp;lt;/summary&amp;gt;
      [ConfigurationProperty(&amp;quot;UseNTPermissions&amp;quot;, IsRequired = true)]
      public bool UseNTPermissions
      {
        get
        {
          return (bool)base[&amp;quot;UseNTPermissions&amp;quot;];
        }
        set
        {
          base[&amp;quot;UseNTPermissions&amp;quot;] = value;
        }
      }
      #endregion

      #region DefaultNTDomain
      /// &amp;lt;summary&amp;gt;
      /// Gets or sets the DefaultNTDomain.
      /// &amp;lt;/summary&amp;gt;
      [ConfigurationProperty(&amp;quot;DefaultNTDomain&amp;quot;, IsRequired = false)]
      public string DefaultNTDomain
      {
        get
        {
          return (string)base[&amp;quot;DefaultNTDomain&amp;quot;];
        }
        set
        {
          base[&amp;quot;DefaultNTDomain&amp;quot;] = value;
        }
      }
      #endregion
    }

    #region Current
    public static readonly Configuration Current;
    static Configuration()
    {
      const string ConfigurationSectionName = &amp;quot;ISI.HAPP.API.Configuration&amp;quot;;

      Current = null;
      if (Current == null) Current = (Configuration)(System.Configuration.ConfigurationManager.GetSection(ConfigurationSectionName));
      if (Current == null) throw new Exception(string.Format(&amp;quot;Missing {0} Configuration Section&amp;quot;, ConfigurationSectionName));
    }
    #endregion

    public Configuration() : base() { }

    #region CompanyName
    [ConfigurationProperty(&amp;quot;CompanyName&amp;quot;, IsRequired = false)]     public string CompanyName
    {
      get
      {
        return (string)base[&amp;quot;CompanyName&amp;quot;];
      }
      set
      {
        base[&amp;quot;CompanyName&amp;quot;] = value;
      }
    }
    #endregion

    #region Authenication
    public AuthenicationParameters Authenication
    {
      get
      {
        return (AuthenicationParameters)base[&amp;quot;Authenication&amp;quot;];
      }
    }
    #endregion
  }
}&lt;/pre&gt;

&lt;p&gt;and add the following to the “configSections” of your app/web.config:&lt;/p&gt;

&lt;pre class="brush: xml;"&gt;    &amp;lt;section name=&amp;quot;ISI.HAPP.API.Configuration&amp;quot; type=&amp;quot;ISI.HAPP.API.Configuration, ISI.HAPP.API.Core&amp;quot; requirePermission=&amp;quot;false&amp;quot;/&amp;gt;&lt;/pre&gt;

&lt;p&gt;and the following after the “configSections”&lt;/p&gt;

&lt;pre class="brush: xml;"&gt;  &amp;lt;ISI.HAPP.API.Configuration&amp;gt;
    &amp;lt;CompanyName&amp;gt;ISI&amp;lt;/CompanyName&amp;gt;
    &amp;lt;Authenication&amp;gt;
      &amp;lt;UseNTPermissions&amp;gt;true&amp;lt;/UseNTPermissions&amp;gt;
      &amp;lt;DefaultNTDomain&amp;gt;ISI&amp;lt;/DefaultNTDomain&amp;gt;
    &amp;lt;/Authenication&amp;gt;
  &amp;lt;/ISI.HAPP.API.Configuration&amp;gt;&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;It’s that simple …….&lt;/p&gt;</description><pubDate>Fri, 19 Jun 2009 20:19:50 -0400</pubDate></item><item><guid isPermaLink="true">http://www.isi-net.com/Blogs/Ron-Muth/Serialization-In-ASPNET-MVC</guid><link>http://www.isi-net.com/Blogs/Ron-Muth/Serialization-In-ASPNET-MVC</link><category>JSON</category><category>Serialization</category><category>MVC</category><category>ActionResult</category><category>DataContract</category><title>Serialization In ASP.NET MVC</title><description>&lt;p&gt;I’ve been doing a lot more with jQuery in ASP.NET MVC than I ever have before. One of the biggest problems I’ve had is in the sending back of JSON to jQuery ajax calls, it seems that the built in MVC action result is not to friendly with dates and/or forms submitted with uploaded files, so with some help of an article @ &lt;a title="http://msmvps.com/blogs/omar/archive/2008/10/03/create-rest-api-using-asp-net-mvc-that-speaks-both-json-and-plain-xml.aspx" href="http://msmvps.com/blogs/omar/archive/2008/10/03/create-rest-api-using-asp-net-mvc-that-speaks-both-json-and-plain-xml.aspx"&gt;http://msmvps.com/blogs/omar/archive/2008/10/03/create-rest-api-using-asp-net-mvc-that-speaks-both-json-and-plain-xml.aspx&lt;/a&gt; I’ve come up with my own &lt;span style="color: #2b91af"&gt;SerializeResult&lt;/span&gt;&amp;lt;T&amp;gt; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Usage:&lt;/p&gt;  &lt;p&gt;To send back JSON for a ajax submit without a file upload:&lt;/p&gt; &lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;  &lt;pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 2; toolbar: true;"&gt;result = new SerializeResult&amp;lt;Models.CheckPassword.Response&amp;gt;(model.Result, enSerializeResultFormat.Json);&lt;/pre&gt;

&lt;div class="csharpcode"&gt;&amp;#160;&lt;/div&gt;

&lt;p&gt;To Send back JSON for an ajax submit with a file upload:&lt;/p&gt;

&lt;pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 2; toolbar: true;"&gt;result = new SerializeResult&amp;lt;Models.UploadFile.ReceiveFile.Response&amp;gt;(model.Result, enSerializeResultFormat.JsonTextArea);&lt;/pre&gt;
&lt;style type="text/css"&gt;









.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;All you have to do is decorate your classes with “[DataContract]” and “[DataMember]” attributes&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;ex:&lt;/p&gt;

&lt;pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 2; toolbar: true;"&gt;    [DataContract]
    public class Client
    {
      [DataMember] public int? ClientID;
      [DataMember] public string CompanyName;

      [DataMember] public decimal PriorPriorYearSalesTotal;
      [DataMember] public decimal PriorYearSalesTotal;
      [DataMember] public decimal CurrentYearSalesTotal;
      [DataMember] public decimal SalesTotal;

      public Client()
      {
        ClientID = null;
        CompanyName = string.Empty;

        PriorPriorYearSalesTotal = 0;
        PriorYearSalesTotal = 0;
        CurrentYearSalesTotal = 0;
        SalesTotal = 0;
      }
    }&lt;/pre&gt;

&lt;p&gt;Here is the &lt;/p&gt;
Code: 

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;pre class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 2; toolbar: true;"&gt;using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Security.Principal;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Runtime.Serialization.Json;

//http://msmvps.com/blogs/omar/archive/2008/10/03/create-rest-api-using-asp-net-mvc-that-speaks-both-json-and-plain-xml.aspx

namespace ISI.Libraries.MVC
{
  public enum enSerializeResultFormat
  {
    Auto,
    Xml,
    JavaScript,
    Json,
    JsonTextArea
  }

  [AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
  [AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
  public class SerializeResult&amp;lt;T&amp;gt; : ActionResult
  {
    private static UTF8Encoding UTF8 = new UTF8Encoding(false);

    public T Data { get; set; }
    public Type[] IncludedTypes = new Type[] { typeof(object) };
    public enSerializeResultFormat SerializeFormat = enSerializeResultFormat.Auto;


    public SerializeResult(T data, Type[] extraTypes, enSerializeResultFormat serializeFormat)
    {
      this.Data = data;
      this.IncludedTypes = extraTypes;
      this.SerializeFormat = serializeFormat;
    }
    public SerializeResult(T data, enSerializeResultFormat serializeFormat) : this(data, new Type[] { typeof(object) }, serializeFormat) { }
    public SerializeResult(T data, Type[] extraTypes) : this(data, extraTypes, enSerializeResultFormat.Auto) { }
    public SerializeResult(T data) : this(data, new Type[] { typeof(object) }) { }


    public override void ExecuteResult(ControllerContext filterContext)
    {
      if(SerializeFormat == enSerializeResultFormat.Auto)
      {
        SerializeFormat = ((filterContext.HttpContext.Request.Headers[&amp;quot;Content-Type&amp;quot;] ?? string.Empty).ToLower().Contains(&amp;quot;application/json&amp;quot;) ? enSerializeResultFormat.Json : enSerializeResultFormat.Xml);
      }

      switch (SerializeFormat)
      {
        case enSerializeResultFormat.Xml:
          using (System.IO.MemoryStream oStream = new System.IO.MemoryStream())
          {
            ISI.Libraries.XML.Serialize&amp;lt;T&amp;gt;(this.Data, oStream);

            new ContentResult { ContentType = &amp;quot;text/xml&amp;quot;, Content = UTF8.GetString(oStream.ToArray()), ContentEncoding = UTF8 }.ExecuteResult(filterContext);
          }
          break;

        case enSerializeResultFormat.Json:
          using (System.IO.MemoryStream oStream = new System.IO.MemoryStream())
          {
            new DataContractJsonSerializer(typeof(T)).WriteObject(oStream, this.Data);

            new ContentResult { ContentType = &amp;quot;application/json&amp;quot;, Content = UTF8.GetString(oStream.ToArray()), ContentEncoding = UTF8 }.ExecuteResult(filterContext);
          }
          break;

        case enSerializeResultFormat.JsonTextArea:
          using (System.IO.MemoryStream oStream = new System.IO.MemoryStream())
          {
            new DataContractJsonSerializer(typeof(T)).WriteObject(oStream, this.Data);

            new ContentResult { ContentType = &amp;quot;text/html&amp;quot;, Content = string.Format(&amp;quot;&amp;lt;textarea&amp;gt;{0}&amp;lt;/textarea&amp;gt;&amp;quot;, UTF8.GetString(oStream.ToArray())), ContentEncoding = UTF8 }.ExecuteResult(filterContext);
          }
          break;

        case enSerializeResultFormat.JavaScript:
          new JsonResult { Data = this.Data }.ExecuteResult(filterContext);
          break;
      }
    }
   
  }
}&lt;/pre&gt;
&lt;style type="text/css"&gt;









.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;</description><pubDate>Mon, 01 Jun 2009 15:12:09 -0400</pubDate></item></channel></rss>
