Wednesday, October 31, 2007

Since learning about the SubSonic project last week, I have spent a bit of time reading up on it, watching screencasts about it, playing with it, and reading the blog of its creator, Rob Conery. In his post "How MVC, jQuery, and SubSonic Will Make You Smile," Rob talks about the use of .NET 3.5's extension methods, in particular extending a Dictionary<string, string> to return HTML for a drop down list (HTML select); here is what his version of the extension method looks like:

 

 1: public static string ToHtmlSelect(this Dictionary<string, string> listItems, string name,
object selectedValue, object attributes)
 2: {
 3:  // input formats
 4:  string selectFormat = "<select name='{0}' id='{0}' {1}>\r\n{2}\r\n </select>";
 5:  string optionFormat = "\t<option value='{0}' {1}>{2}</option>\r\n";
 6:  
 7:  // output
 8:  StringBuilder sb = new StringBuilder();
 9:  
 10:  foreach (string s in listItems.Keys)
 11:  {
 12:  string selectedFlag = "";
 13:  string text = listItems[s];
 14:  string value = s;
 15:  if (value.ToLower().Equals(selectedValue.ToString().ToLower()))
 16:  selectedFlag = "selected=true";
 17:  sb.AppendFormat(optionFormat, s.ToString(), selectedFlag, text);
 18:  }
 19:  string result = string.Format(selectFormat, name, attributes.ToAttributeList(), sb.ToString());
 20:  return result;
 21: }



 

He also mentions that (on line 19) there is another extension method that "hangs off the object class" which basically enumerates all of the properties of an object, creating a name/value pair attribute list. He doesn't give the code of that extension method, which he states "is ScottGu magic at work and something he shows in his MVC demos." I have yet to watch those demos myself, but the code is probably something akin to this:

 

 1: public static string ToAttributeList(this object attributes) 
 2: {
 3:  StringBuilder sb = new StringBuilder();
 4:  foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(attributes)) 
 5:  {
 6:  sb.AppendFormat("{0}='{1}' ", property.Name, property.GetValue(attributes).ToString());
 7:  }
 8:  return sb.ToString();
 9: }

 

This allows you to pass anonymous types, specifying what might normally be optional parameters, a la something I have been doing in JavaScript for a while using MochiKit (other JavaScript libs exploit the same literal JavaScript object notation in their function signatures). The idea is that you don't need to have a structured method signature that accepts all possible options - you can pass in what you want to specify as a part of an anonymous object. This will make more sense if you have spent any time doing this in JavaScript or want to wait a moment and read on.

Anyway, the whole reason I was even posting on this subject is because of a comment made on Rob's post by one Joe Chung, wherein he states:

"Seeing StringBuilder-generated HTML makes me sad for the future of ASP.NET. Object-oriented ASP spaghetti code is still spaghetti code."

He is referring to the string hacking done in the ToHtmlSelect extension method. I too don't care for it, and simply wanted to show a nicer way of doing this, which leverages objects we already have access to in ASP.NET which do that grunt work for us.

Here is my version of Rob's method (which I still have issues with, but for now we will let those go for the sake of staying on topic) - note, there are no literal strings for those that despise them:

 1: public static string ToHtmlSelect(this Dictionary<string, string> listItems, object selectedValue,
object attributes)
 2: {
 3:  DropDownList htmlSelect = new DropDownList();
 4:  htmlSelect.Attributes.AddAttributes(attributes);
 5:  foreach (string key in listItems.Keys)
 6:  {
 7:  ListItem item = new ListItem(listItems[key], key);
 8:  item.Selected = (key.ToLower().Equals(selectedValue.ToString().ToLower()));
 9:  htmlSelect.Items.Add(item);
 10:  }
 11:  return htmlSelect.ToHtml();
 12: }

 

Now, my version does not use the ToAttributeList() extension method hanging off of  object - mine uses something a bit different, but an extension method nonetheless (although a bit naive, it will suffice for our purposes):

 

 1: public static void AddAttributes(this System.Web.UI.AttributeCollection attributeCollection,
object attributes)
 2: {
 3:  foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(attributes))
 4:  {
 5:  attributeCollection.Add(property.Name, property.GetValue(attributes).ToString());
 6:  }
 7: }

 

My extension method hangs instead off of System.Web.UI.AttributeCollection because my version of the ToHtmlSelect() method works with the System.Web.UI.DropDownList object, which uses that as the place to store its attributes.

The other key to mine is the following extension method which wraps a technique I have been using for over 2 years to create HTML (I didn't figure it out on my own, but can't remember where I saw this exactly - I think in the Google Group for the AjaxPro.NET component back when it was simply Ajax.NET):

 

 1: public static string ToHtml(this Control control)
 2: {
 3:  StringWriter sw = new StringWriter();
 4:  HtmlTextWriter htw = new HtmlTextWriter(sw);
 5:  control.RenderControl(htw);
 6:  return sw.ToString();
 7: }

 

Note - this can be used for all sorts of Control-derived ASP.NET HTML wrapper objects to get you some HTML without string hacking in your layers of code:

 

 1: Calendar c = new Calendar();
 2: string calendarHtml = c.ToHtml();

 

Notice Joe - no literal strings! That should make you happy (I know it makes me happy!).

Now, I love hacking JavaScript as much as the next guy (been doing it hardcore for the last 2.5 years even with ASP.NET because it is too much fun!), but hacking strings to create HTML is still not that fun. Even in JavaScript I don't do it if I don't have to, preferring to use functions that handle that for me (MochiKit has some simple DOM functions for handling HTML creation).

Anyway, hope this is of some use to someone out there!

 

Technorati Tags: , , , ,

posted on Wednesday, October 31, 2007 12:38:37 PM (Mountain Standard Time, UTC-07:00)  #    Comments [11] Trackback
 Tuesday, February 27, 2007

 

The company I work for is hiring -  whether you are a project manager, senior-level Java developer, Microsoft application developer or a web design/usability expert, Software Technology Group has something for you.

I have worked for STG for over 2 years now and can tell you that, without a doubt, working for STG has been one of the highlights of my career.


posted on Tuesday, February 27, 2007 9:28:28 AM (Mountain Standard Time, UTC-07:00)  #    Comments [0] Trackback
 Friday, October 17, 2003
Just basic info on my 'new' job

posted on Thursday, October 16, 2003 11:06:36 PM (Mountain Standard Time, UTC-07:00)  #    Comments [0] Trackback