Wednesday, February 17, 2010

Enum Extensions

If you're a fan of Enums for readability in an application here are some resources for making them more usable.
The first item is used for places where you'd like some enum values to have a space in the name when displayed somewhere. You can use System.ComponentModel.DescriptionAttribute like so:

       [Flags]
       public enum PermissionType
       {

           Select = 1,
           Insert = 2,
           Update = 4,
           Delete = 8,
           Alter = 16,
           Execute = 32,
           [
Description("View Definition")]
           ViewDefinition = 64
       }
 
and here's the extension method to make it easily usable:
 
    using System.ComponentModel;
 
    /// from: http://www.moggoly.me.uk/blog/post/Enum-description-values.asp
    public static string DescriptionOrToString(this T value)
    {

        
var da = (DescriptionAttribute[])(typeof(T).GetField(value.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false));

        
return da.Length > 0 ? da[0].Description : value.ToString();

    }

if you don't like the possible clutter of having every object have a DescriptionOrToString in your intellisense, change the signature to
 
public static string DescriptionOrToString(this T value) where T:struct

This method is for enumerating enum values that are used as [Flags] (where a single value can contain many different values in the same enum)

    
///
    /// Gets all combined items from an enum value.
    /// from: http://stackoverflow.com/questions/105372/c-how-to-enumerate-an-enum
    ///
    ///
    /// The value.
    ///
    public static IEnumerable GetAllSelectedItems(this Enum value)
    {
        
int valueAsInt = Convert.ToInt32(value, CultureInfo.InvariantCulture);

        
foreach (object item in Enum.GetValues(typeof(T)))
        {
            
int itemAsInt = Convert.ToInt32(item, CultureInfo.InvariantCulture);

            
if (itemAsInt == (valueAsInt & itemAsInt))
            {
                
yield return (T)item;
            }
        }
    }

The next post will contain a usage example for GetAllSelectedItems.

Thursday, February 4, 2010

MVC 2 reusable content options

There are 2 main sources of reusable or dynamic page content in Asp.net MVC. Partial Views(using Html.RenderPartial), and HtmlHelpers. Other options include Html.RenderAction, and Ajax calls (for adding content after the page is loaded).  Here's my understanding of them thus far.

Partial views can be strongly typed, but if the type is different from your hosting page(s) you lose the ability to do Html.DisplayFor, Html.TextBoxFor, and have it utilize that type's names. This can all be overcome by designing a custom DTO or ViewModel for the partial view, but that's more steps. Partial views internally work very similar to if they were inside a regular view, however the <%= %> does not seem to come up by default in intellisense. Instead, you get<%@ Assembly= %>. It's nice if you prefer to model your code in a similar way to how a view would look.

Another option is HtmlHelper, which is what you are using when you type Html.TextBox, or Html.TextBoxFor, etc... You write one of these by putting a static class in your project for extension methods. Then writing an Extension method that extends HtmlHelper like so

using System.Web.Mvc;
using BReusable; //For the Member class


public const string JavaScript = " < script type=\"text/javascript\" language=\"javascript\">\n";
public static string JqueryLoadForId(this HtmlHelper helper, Expression<Funcobject>> memberName,
                                  
string function)
{
    
return JavaScript + "$(function() {\n$('#' + '" + Member.Name(memberName) + "')\n." + function +
          
";\n});\n\n";
}

As you can see this code can start to look messy and probably suffers from pre-mature optimization. String.Format suffers a performance penalty, but using that would allow most of this code to sit in a .js or resource file instead of the poor formatting options that string literals leave us.

RenderAction is useful for returning one of the normal controller result types 
  • ViewResult – Represents HTML and markup.
  • EmptyResult – Represents no result.
  • RedirectResult – Represents a redirection to a new URL.
  • JsonResult – Represents a JavaScript Object Notation result that can be used in an AJAX application.
  • JavaScriptResult – Represents a JavaScript script.
  • ContentResult – Represents a text result.
  • FileContentResult – Represents a downloadable file (with the binary content).
  • FilePathResult – Represents a downloadable file (with a path).
  • FileStreamResult – Represents a downloadable file (with a file stream).
Ajax options
  • Ajax class
    • use AjaxOptions parameter to specify many options
      • Example:


        new AjaxOptions { 
                Confirm="Are you sure?",
                HttpMethod="POST",
                UpdateTargetId="divResultText",
                LoadingElementId="divLoading",
                OnSuccess = "myCallback"
            }
    • Ajax.ActionLink
    • using(Ajax.BeginForm()){}
  • javascript or jQuery Ajax calls to web methods