May 18, 2009

 TypeMock Asp.Net Bundle

Unit Testing ASP.NET? ASP.NET unit testing has never been this easy.
Typemock is launching a new product for ASP.NET developers – the ASP.NET Bundle - and for the launch will be giving out FREE licenses to bloggers and their readers.
The ASP.NET Bundle is the ultimate ASP.NET unit testing solution, and offers both Typemock Isolator, a unit test tool and Ivonna, the Isolator add-on for ASP.NET unit testing, for a bargain price.
Typemock Isolator is a leading .NET unit testing tool (C# and VB.NET) for many ‘hard to test’ technologies such as SharePoint, ASP.NET, MVC, WCF, WPF, Silverlight and more. Note that for unit testing Silverlight there is an open source Isolator add-on called SilverUnit.
The first 60 bloggers who will blog this text in their blog and tell us about it, will get a Free Isolator ASP.NET Bundle license (Typemock Isolator + Ivonna). If you post this in an ASP.NET dedicated blog, you'll get a license automatically (even if more than 60 submit) during the first week of this announcement.
Also 8 bloggers will get an additional 2 licenses (each) to give away to their readers / friends.
Go ahead, click the following link for more information on how to get your free license.

 February 21, 2009

 JavaScript Arrays via JQuery Ajax to an Asp.Net WebMethod

Long title, but this is a problem that has haunted me for a while now.  I have an Asp.Net WebMethod that takes a List/IEnumerable/Array of stuff as a parameter, how do I send that stuff to that method using the JQuery Ajax method.

Now, without having to reinvent the wheel, do check out David Ward's articles on JQuery and Asp.Net WebMethods for a primer on how this is done.

But one item not mentioned is how to update methods that take lists.

If you want to know why this is hard, take a look at this sample.  If you have a web method that looks like this:

   1: [WebMethod]


   2: public void SendName(string firstName, string lastName)


   3: {


   4:     


   5: }




You are going to call it with code like this:





   1: $.ajax({


   2:   type: "POST",


   3:   url: "WebService.asmx/SendName",


   4:   data: "{'firstName':'Chris','lastName':'Brandsma'}",


   5:   contentType: "application/json; charset=utf-8",


   6:   dataType: "json",


   7:   success: function(msg) {


   8:   }


   9: });




If you are still wondering where this issue is, look at line 4 of the second sample there.  




data: "{'firstName':'Chris','lastName':'Brandsma'}",




The data that is being passed to the web method has to be converted to string first.  And a JSON compliant string.  Now, while there is a way to take a JSON string and turn that into functioning JavaScript code (via the eval method), there is no built in "turn this JavaScript object into a JSON string for me, m'kay".  For simple data this is no problem, but for complex data this is a daunting task.



But there is a way.



Enter JSON2.js by the most excellent Douglas Crockford (go check out his book, JavaScript the Good Parts) who is one of the for-most luminaries on JavaScript these days.



JSON2.js gives you a method called JSON.stringify. Which takes an object and returns a string.  All this in a class that can be minified to less than 2.5K.



Now, lets put this to work.



I'm going to create a new WebMethod:





   1: [WebMethod] 


   2: public void SendValues(List<string> list)


   3: {


   4:     


   5: }




Here is my JQuery code:





   1: var list = ["a", "b", "c", "d"];


   2: var jsonText = JSON.stringify({ list: list });


   3:  


   4: $.ajax({


   5:   type: "POST",


   6:   url: "WebService1.asmx/SendValues",


   7:   data: jsonText,


   8:   contentType: "application/json; charset=utf-8",


   9:   dataType: "json",


  10:   success: function() { alert("it worked"); },


  11:   failure: function() { alert("Uh oh"); }


  12: });




And it works!  If you are worried that I'm sending too simple an object here (a simple list of strings in this example), I have tested this with much more complex object types as well, and it still works wonderfully.

 February 10, 2009

 Pasting from Word

Warning: this is not a programmer post. 

I had a little bit of text that I wanted to spell check.  I am a particularly bad speller, bad enough that FireFox's built in spell check is rarely helpful enough, as is Google.  My tool of spell checking choice is Microsoft Word.

So I put the paragraph in to Word and found one misspelling.  Copied the corrected word out of Word and into DotNetNuke's WYSIWYG editor.  It looked kind of funny after that.  The font was wrong.

So I checked the source via source view and this is what I saw:

   1: <p>


   2: <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />


   3: <meta content="Word.Document" name="ProgId" />


   4: <meta content="Microsoft Word 12" name="Generator" />


   5: <meta content="Microsoft Word 12" name="Originator" />


   6: <link href="file:///C:\Users\Chris\AppData\Local\Temp\msohtmlclip1\01\clip_filelist.xml" rel="File-List" />


   7: <link href="file:///C:\Users\Chris\AppData\Local\Temp\msohtmlclip1\01\clip_themedata.thmx" rel="themeData" />


   8: <link href="file:///C:\Users\Chris\AppData\Local\Temp\msohtmlclip1\01\clip_colorschememapping.xml" rel="colorSchemeMapping" /></p>


   9: <!--[if gte mso 9]><xml>


  10: <w:WordDocument>


  11: <w:View>Normal</w:View>


  12: <w:Zoom>0</w:Zoom>


  13: <w:TrackMoves />


  14: <w:TrackFormatting />


  15: <w:PunctuationKerning />


  16: <w:ValidateAgainstSchemas />


  17: <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>


  18: <w:IgnoreMixedContent>false</w:IgnoreMixedContent>


  19: <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>


  20: <w:DoNotPromoteQF />


  21: <w:LidThemeOther>EN-US</w:LidThemeOther>


  22: <w:LidThemeAsian>X-NONE</w:LidThemeAsian>


  23: <w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript>


  24: <w:Compatibility>


  25: <w:BreakWrappedTables />


  26: <w:SnapToGridInCell />


  27: <w:WrapTextWithPunct />


  28: <w:UseAsianBreakRules />


  29: <w:DontGrowAutofit />


  30: <w:SplitPgBreakAndParaMark />


  31: <w:DontVertAlignCellWithSp />


  32: <w:DontBreakConstrainedForcedTables />


  33: <w:DontVertAlignInTxbx />


  34: <w:Word11KerningPairs />


  35: <w:CachedColBalance />


  36: </w:Compatibility>


  37: <w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel>


  38: <m:mathPr>


  39: <m:mathFont m:val="Cambria Math" />


  40: <m:brkBin m:val="before" />


  41: <m:brkBinSub m:val="&#45;-" />


  42: <m:smallFrac m:val="off" />


  43: <m:dispDef />


  44: <m:lMargin m:val="0" />


  45: <m:rMargin m:val="0" />


  46: <m:defJc m:val="centerGroup" />


  47: <m:wrapIndent m:val="1440" />


  48: <m:intLim m:val="subSup" />


  49: <m:naryLim m:val="undOvr" />


  50: </m:mathPr></w:WordDocument>


  51: </xml><![endif]--><!--[if gte mso 9]><xml>


  52: <w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true"


  53: DefSemiHidden="true" DefQFormat="false" DefPriority="99"


  54: LatentStyleCount="267">


  55: <w:LsdException Locked="false" Priority="0" SemiHidden="false"


  56: UnhideWhenUsed="false" QFormat="true" Name="Normal" />


  57: <w:LsdException Locked="false" Priority="9" SemiHidden="false"


  58: UnhideWhenUsed="false" QFormat="true" Name="heading 1" />


  59: <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2" />


  60: <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3" />


  61: <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4" />


  62: <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5" />


  63: <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6" />


  64: <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7" />


  65: <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8" />


  66: <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9" />


  67: <w:LsdException Locked="false" Priority="39" Name="toc 1" />


  68: <w:LsdException Locked="false" Priority="39" Name="toc 2" />


  69: <w:LsdException Locked="false" Priority="39" Name="toc 3" />


  70: <w:LsdException Locked="false" Priority="39" Name="toc 4" />


  71: <w:LsdException Locked="false" Priority="39" Name="toc 5" />


  72: <w:LsdException Locked="false" Priority="39" Name="toc 6" />


  73: <w:LsdException Locked="false" Priority="39" Name="toc 7" />


  74: <w:LsdException Locked="false" Priority="39" Name="toc 8" />


  75: <w:LsdException Locked="false" Priority="39" Name="toc 9" />


  76: <w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption" />


  77: <w:LsdException Locked="false" Priority="10" SemiHidden="false"


  78: UnhideWhenUsed="false" QFormat="true" Name="Title" />


  79: <w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font" />


  80: <w:LsdException Locked="false" Priority="11" SemiHidden="false"


  81: UnhideWhenUsed="false" QFormat="true" Name="Subtitle" />


  82: <w:LsdException Locked="false" Priority="22" SemiHidden="false"


  83: UnhideWhenUsed="false" QFormat="true" Name="Strong" />


  84: <w:LsdException Locked="false" Priority="20" SemiHidden="false"


  85: UnhideWhenUsed="false" QFormat="true" Name="Emphasis" />


  86: <w:LsdException Locked="false" Priority="59" SemiHidden="false"


  87: UnhideWhenUsed="false" Name="Table Grid" />


  88: <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text" />


  89: <w:LsdException Locked="false" Priority="1" SemiHidden="false"


  90: UnhideWhenUsed="false" QFormat="true" Name="No Spacing" />


  91: <w:LsdException Locked="false" Priority="60" SemiHidden="false"


  92: UnhideWhenUsed="false" Name="Light Shading" />


  93: <w:LsdException Locked="false" Priority="61" SemiHidden="false"


  94: UnhideWhenUsed="false" Name="Light List" />


  95: <w:LsdException Locked="false" Priority="62" SemiHidden="false"


  96: UnhideWhenUsed="false" Name="Light Grid" />


  97: <w:LsdException Locked="false" Priority="63" SemiHidden="false"


  98: UnhideWhenUsed="false" Name="Medium Shading 1" />


  99: <w:LsdException Locked="false" Priority="64" SemiHidden="false"


 100: UnhideWhenUsed="false" Name="Medium Shading 2" />


 101: <w:LsdException Locked="false" Priority="65" SemiHidden="false"


 102: UnhideWhenUsed="false" Name="Medium List 1" />


 103: <w:LsdException Locked="false" Priority="66" SemiHidden="false"


 104: UnhideWhenUsed="false" Name="Medium List 2" />


 105: <w:LsdException Locked="false" Priority="67" SemiHidden="false"


 106: UnhideWhenUsed="false" Name="Medium Grid 1" />


 107: <w:LsdException Locked="false" Priority="68" SemiHidden="false"


 108: UnhideWhenUsed="false" Name="Medium Grid 2" />


 109: <w:LsdException Locked="false" Priority="69" SemiHidden="false"


 110: UnhideWhenUsed="false" Name="Medium Grid 3" />


 111: <w:LsdException Locked="false" Priority="70" SemiHidden="false"


 112: UnhideWhenUsed="false" Name="Dark List" />


 113: <w:LsdException Locked="false" Priority="71" SemiHidden="false"


 114: UnhideWhenUsed="false" Name="Colorful Shading" />


 115: <w:LsdException Locked="false" Priority="72" SemiHidden="false"


 116: UnhideWhenUsed="false" Name="Colorful List" />


 117: <w:LsdException Locked="false" Priority="73" SemiHidden="false"


 118: UnhideWhenUsed="false" Name="Colorful Grid" />


 119: <w:LsdException Locked="false" Priority="60" SemiHidden="false"


 120: UnhideWhenUsed="false" Name="Light Shading Accent 1" />


 121: <w:LsdException Locked="false" Priority="61" SemiHidden="false"


 122: UnhideWhenUsed="false" Name="Light List Accent 1" />


 123: <w:LsdException Locked="false" Priority="62" SemiHidden="false"


 124: UnhideWhenUsed="false" Name="Light Grid Accent 1" />


 125: <w:LsdException Locked="false" Priority="63" SemiHidden="false"


 126: UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1" />


 127: <w:LsdException Locked="false" Priority="64" SemiHidden="false"


 128: UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1" />


 129: <w:LsdException Locked="false" Priority="65" SemiHidden="false"


 130: UnhideWhenUsed="false" Name="Medium List 1 Accent 1" />


 131: <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision" />


 132: <w:LsdException Locked="false" Priority="34" SemiHidden="false"


 133: UnhideWhenUsed="false" QFormat="true" Name="List Paragraph" />


 134: <w:LsdException Locked="false" Priority="29" SemiHidden="false"


 135: UnhideWhenUsed="false" QFormat="true" Name="Quote" />


 136: <w:LsdException Locked="false" Priority="30" SemiHidden="false"


 137: UnhideWhenUsed="false" QFormat="true" Name="Intense Quote" />


 138: <w:LsdException Locked="false" Priority="66" SemiHidden="false"


 139: UnhideWhenUsed="false" Name="Medium List 2 Accent 1" />


 140: <w:LsdException Locked="false" Priority="67" SemiHidden="false"


 141: UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1" />


 142: <w:LsdException Locked="false" Priority="68" SemiHidden="false"


 143: UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1" />


 144: <w:LsdException Locked="false" Priority="69" SemiHidden="false"


 145: UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1" />


 146: <w:LsdException Locked="false" Priority="70" SemiHidden="false"


 147: UnhideWhenUsed="false" Name="Dark List Accent 1" />


 148: <w:LsdException Locked="false" Priority="71" SemiHidden="false"


 149: UnhideWhenUsed="false" Name="Colorful Shading Accent 1" />


 150: <w:LsdException Locked="false" Priority="72" SemiHidden="false"


 151: UnhideWhenUsed="false" Name="Colorful List Accent 1" />


 152: <w:LsdException Locked="false" Priority="73" SemiHidden="false"


 153: UnhideWhenUsed="false" Name="Colorful Grid Accent 1" />


 154: <w:LsdException Locked="false" Priority="60" SemiHidden="false"


 155: UnhideWhenUsed="false" Name="Light Shading Accent 2" />


 156: <w:LsdException Locked="false" Priority="61" SemiHidden="false"


 157: UnhideWhenUsed="false" Name="Light List Accent 2" />


 158: <w:LsdException Locked="false" Priority="62" SemiHidden="false"


 159: UnhideWhenUsed="false" Name="Light Grid Accent 2" />


 160: <w:LsdException Locked="false" Priority="63" SemiHidden="false"


 161: UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2" />


 162: <w:LsdException Locked="false" Priority="64" SemiHidden="false"


 163: UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2" />


 164: <w:LsdException Locked="false" Priority="65" SemiHidden="false"


 165: UnhideWhenUsed="false" Name="Medium List 1 Accent 2" />


 166: <w:LsdException Locked="false" Priority="66" SemiHidden="false"


 167: UnhideWhenUsed="false" Name="Medium List 2 Accent 2" />


 168: <w:LsdException Locked="false" Priority="67" SemiHidden="false"


 169: UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2" />


 170: <w:LsdException Locked="false" Priority="68" SemiHidden="false"


 171: UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2" />


 172: <w:LsdException Locked="false" Priority="69" SemiHidden="false"


 173: UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2" />


 174: <w:LsdException Locked="false" Priority="70" SemiHidden="false"


 175: UnhideWhenUsed="false" Name="Dark List Accent 2" />


 176: <w:LsdException Locked="false" Priority="71" SemiHidden="false"


 177: UnhideWhenUsed="false" Name="Colorful Shading Accent 2" />


 178: <w:LsdException Locked="false" Priority="72" SemiHidden="false"


 179: UnhideWhenUsed="false" Name="Colorful List Accent 2" />


 180: <w:LsdException Locked="false" Priority="73" SemiHidden="false"


 181: UnhideWhenUsed="false" Name="Colorful Grid Accent 2" />


 182: <w:LsdException Locked="false" Priority="60" SemiHidden="false"


 183: UnhideWhenUsed="false" Name="Light Shading Accent 3" />


 184: <w:LsdException Locked="false" Priority="61" SemiHidden="false"


 185: UnhideWhenUsed="false" Name="Light List Accent 3" />


 186: <w:LsdException Locked="false" Priority="62" SemiHidden="false"


 187: UnhideWhenUsed="false" Name="Light Grid Accent 3" />


 188: <w:LsdException Locked="false" Priority="63" SemiHidden="false"


 189: UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3" />


 190: <w:LsdException Locked="false" Priority="64" SemiHidden="false"


 191: UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3" />


 192: <w:LsdException Locked="false" Priority="65" SemiHidden="false"


 193: UnhideWhenUsed="false" Name="Medium List 1 Accent 3" />


 194: <w:LsdException Locked="false" Priority="66" SemiHidden="false"


 195: UnhideWhenUsed="false" Name="Medium List 2 Accent 3" />


 196: <w:LsdException Locked="false" Priority="67" SemiHidden="false"


 197: UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3" />


 198: <w:LsdException Locked="false" Priority="68" SemiHidden="false"


 199: UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3" />


 200: <w:LsdException Locked="false" Priority="69" SemiHidden="false"


 201: UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3" />


 202: <w:LsdException Locked="false" Priority="70" SemiHidden="false"


 203: UnhideWhenUsed="false" Name="Dark List Accent 3" />


 204: <w:LsdException Locked="false" Priority="71" SemiHidden="false"


 205: UnhideWhenUsed="false" Name="Colorful Shading Accent 3" />


 206: <w:LsdException Locked="false" Priority="72" SemiHidden="false"


 207: UnhideWhenUsed="false" Name="Colorful List Accent 3" />


 208: <w:LsdException Locked="false" Priority="73" SemiHidden="false"


 209: UnhideWhenUsed="false" Name="Colorful Grid Accent 3" />


 210: <w:LsdException Locked="false" Priority="60" SemiHidden="false"


 211: UnhideWhenUsed="false" Name="Light Shading Accent 4" />


 212: <w:LsdException Locked="false" Priority="61" SemiHidden="false"


 213: UnhideWhenUsed="false" Name="Light List Accent 4" />


 214: <w:LsdException Locked="false" Priority="62" SemiHidden="false"


 215: UnhideWhenUsed="false" Name="Light Grid Accent 4" />


 216: <w:LsdException Locked="false" Priority="63" SemiHidden="false"


 217: UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4" />


 218: <w:LsdException Locked="false" Priority="64" SemiHidden="false"


 219: UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4" />


 220: <w:LsdException Locked="false" Priority="65" SemiHidden="false"


 221: UnhideWhenUsed="false" Name="Medium List 1 Accent 4" />


 222: <w:LsdException Locked="false" Priority="66" SemiHidden="false"


 223: UnhideWhenUsed="false" Name="Medium List 2 Accent 4" />


 224: <w:LsdException Locked="false" Priority="67" SemiHidden="false"


 225: UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4" />


 226: <w:LsdException Locked="false" Priority="68" SemiHidden="false"


 227: UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4" />


 228: <w:LsdException Locked="false" Priority="69" SemiHidden="false"


 229: UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4" />


 230: <w:LsdException Locked="false" Priority="70" SemiHidden="false"


 231: UnhideWhenUsed="false" Name="Dark List Accent 4" />


 232: <w:LsdException Locked="false" Priority="71" SemiHidden="false"


 233: UnhideWhenUsed="false" Name="Colorful Shading Accent 4" />


 234: <w:LsdException Locked="false" Priority="72" SemiHidden="false"


 235: UnhideWhenUsed="false" Name="Colorful List Accent 4" />


 236: <w:LsdException Locked="false" Priority="73" SemiHidden="false"


 237: UnhideWhenUsed="false" Name="Colorful Grid Accent 4" />


 238: <w:LsdException Locked="false" Priority="60" SemiHidden="false"


 239: UnhideWhenUsed="false" Name="Light Shading Accent 5" />


 240: <w:LsdException Locked="false" Priority="61" SemiHidden="false"


 241: UnhideWhenUsed="false" Name="Light List Accent 5" />


 242: <w:LsdException Locked="false" Priority="62" SemiHidden="false"


 243: UnhideWhenUsed="false" Name="Light Grid Accent 5" />


 244: <w:LsdException Locked="false" Priority="63" SemiHidden="false"


 245: UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5" />


 246: <w:LsdException Locked="false" Priority="64" SemiHidden="false"


 247: UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5" />


 248: <w:LsdException Locked="false" Priority="65" SemiHidden="false"


 249: UnhideWhenUsed="false" Name="Medium List 1 Accent 5" />


 250: <w:LsdException Locked="false" Priority="66" SemiHidden="false"


 251: UnhideWhenUsed="false" Name="Medium List 2 Accent 5" />


 252: <w:LsdException Locked="false" Priority="67" SemiHidden="false"


 253: UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5" />


 254: <w:LsdException Locked="false" Priority="68" SemiHidden="false"


 255: UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5" />


 256: <w:LsdException Locked="false" Priority="69" SemiHidden="false"


 257: UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5" />


 258: <w:LsdException Locked="false" Priority="70" SemiHidden="false"


 259: UnhideWhenUsed="false" Name="Dark List Accent 5" />


 260: <w:LsdException Locked="false" Priority="71" SemiHidden="false"


 261: UnhideWhenUsed="false" Name="Colorful Shading Accent 5" />


 262: <w:LsdException Locked="false" Priority="72" SemiHidden="false"


 263: UnhideWhenUsed="false" Name="Colorful List Accent 5" />


 264: <w:LsdException Locked="false" Priority="73" SemiHidden="false"


 265: UnhideWhenUsed="false" Name="Colorful Grid Accent 5" />


 266: <w:LsdException Locked="false" Priority="60" SemiHidden="false"


 267: UnhideWhenUsed="false" Name="Light Shading Accent 6" />


 268: <w:LsdException Locked="false" Priority="61" SemiHidden="false"


 269: UnhideWhenUsed="false" Name="Light List Accent 6" />


 270: <w:LsdException Locked="false" Priority="62" SemiHidden="false"


 271: UnhideWhenUsed="false" Name="Light Grid Accent 6" />


 272: <w:LsdException Locked="false" Priority="63" SemiHidden="false"


 273: UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6" />


 274: <w:LsdException Locked="false" Priority="64" SemiHidden="false"


 275: UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6" />


 276: <w:LsdException Locked="false" Priority="65" SemiHidden="false"


 277: UnhideWhenUsed="false" Name="Medium List 1 Accent 6" />


 278: <w:LsdException Locked="false" Priority="66" SemiHidden="false"


 279: UnhideWhenUsed="false" Name="Medium List 2 Accent 6" />


 280: <w:LsdException Locked="false" Priority="67" SemiHidden="false"


 281: UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6" />


 282: <w:LsdException Locked="false" Priority="68" SemiHidden="false"


 283: UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6" />


 284: <w:LsdException Locked="false" Priority="69" SemiHidden="false"


 285: UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6" />


 286: <w:LsdException Locked="false" Priority="70" SemiHidden="false"


 287: UnhideWhenUsed="false" Name="Dark List Accent 6" />


 288: <w:LsdException Locked="false" Priority="71" SemiHidden="false"


 289: UnhideWhenUsed="false" Name="Colorful Shading Accent 6" />


 290: <w:LsdException Locked="false" Priority="72" SemiHidden="false"


 291: UnhideWhenUsed="false" Name="Colorful List Accent 6" />


 292: <w:LsdException Locked="false" Priority="73" SemiHidden="false"


 293: UnhideWhenUsed="false" Name="Colorful Grid Accent 6" />


 294: <w:LsdException Locked="false" Priority="19" SemiHidden="false"


 295: UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis" />


 296: <w:LsdException Locked="false" Priority="21" SemiHidden="false"


 297: UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis" />


 298: <w:LsdException Locked="false" Priority="31" SemiHidden="false"


 299: UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference" />


 300: <w:LsdException Locked="false" Priority="32" SemiHidden="false"


 301: UnhideWhenUsed="false" QFormat="true" Name="Intense Reference" />


 302: <w:LsdException Locked="false" Priority="33" SemiHidden="false"


 303: UnhideWhenUsed="false" QFormat="true" Name="Book Title" />


 304: <w:LsdException Locked="false" Priority="37" Name="Bibliography" />


 305: <w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading" />


 306: </w:LatentStyles>


 307: </xml><![endif]-->


 308: <p><style type="text/css">


 309: <!--


 310:  /* Font Definitions */


 311:  @font-face


 312:     {font-family:"Cambria Math";


 313:     panose-1:2 4 5 3 5 4 6 3 2 4;


 314:     mso-font-charset:1;


 315:     mso-generic-font-family:roman;


 316:     mso-font-format:other;


 317:     mso-font-pitch:variable;


 318:     mso-font-signature:0 0 0 0 0 0;}


 319: @font-face


 320:     {font-family:Calibri;


 321:     panose-1:2 15 5 2 2 2 4 3 2 4;


 322:     mso-font-charset:0;


 323:     mso-generic-font-family:swiss;


 324:     mso-font-pitch:variable;


 325:     mso-font-signature:-1610611985 1073750139 0 0 159 0;}


 326:  /* Style Definitions */


 327:  p.MsoNormal, li.MsoNormal, div.MsoNormal


 328:     {mso-style-unhide:no;


 329:     mso-style-qformat:yes;


 330:     mso-style-parent:"";


 331:     margin-top:0in;


 332:     margin-right:0in;


 333:     margin-bottom:10.0pt;


 334:     margin-left:0in;


 335:     line-height:115%;


 336:     mso-pagination:widow-orphan;


 337:     font-size:11.0pt;


 338:     font-family:"Calibri","sans-serif";


 339:     mso-ascii-font-family:Calibri;


 340:     mso-ascii-theme-font:minor-latin;


 341:     mso-fareast-font-family:Calibri;


 342:     mso-fareast-theme-font:minor-latin;


 343:     mso-hansi-font-family:Calibri;


 344:     mso-hansi-theme-font:minor-latin;


 345:     mso-bidi-font-family:"Times New Roman";


 346:     mso-bidi-theme-font:minor-bidi;}


 347: .MsoChpDefault


 348:     {mso-style-type:export-only;


 349:     mso-default-props:yes;


 350:     mso-ascii-font-family:Calibri;


 351:     mso-ascii-theme-font:minor-latin;


 352:     mso-fareast-font-family:Calibri;


 353:     mso-fareast-theme-font:minor-latin;


 354:     mso-hansi-font-family:Calibri;


 355:     mso-hansi-theme-font:minor-latin;


 356:     mso-bidi-font-family:"Times New Roman";


 357:     mso-bidi-theme-font:minor-bidi;}


 358: .MsoPapDefault


 359:     {mso-style-type:export-only;


 360:     margin-bottom:10.0pt;


 361:     line-height:115%;}


 362: @page Section1


 363:     {size:8.5in 11.0in;


 364:     margin:1.0in 1.0in 1.0in 1.0in;


 365:     mso-header-margin:.5in;


 366:     mso-footer-margin:.5in;


 367:     mso-paper-source:0;}


 368: div.Section1


 369:     {page:Section1;}


 370: -->


 371: </style></p>


 372: <!--[if gte mso 10]>


 373: <style>


 374: /* Style Definitions */


 375: table.MsoNormalTable


 376: {mso-style-name:"Table Normal";


 377: mso-tstyle-rowband-size:0;


 378: mso-tstyle-colband-size:0;


 379: mso-style-noshow:yes;


 380: mso-style-priority:99;


 381: mso-style-qformat:yes;


 382: mso-style-parent:"";


 383: mso-padding-alt:0in 5.4pt 0in 5.4pt;


 384: mso-para-margin-top:0in;


 385: mso-para-margin-right:0in;


 386: mso-para-margin-bottom:10.0pt;


 387: mso-para-margin-left:0in;


 388: line-height:115%;


 389: mso-pagination:widow-orphan;


 390: font-size:11.0pt;


 391: font-family:"Calibri","sans-serif";


 392: mso-ascii-font-family:Calibri;


 393: mso-ascii-theme-font:minor-latin;


 394: mso-fareast-font-family:"Times New Roman";


 395: mso-fareast-theme-font:minor-fareast;


 396: mso-hansi-font-family:Calibri;


 397: mso-hansi-theme-font:minor-latin;}


 398: </style>


 399: <![endif]-->


 400: <p><span style="font-size: 11pt; line-height: 115%; font-family: &quot;Calibri&quot;,&quot;sans-serif&quot;;">environments</span></p>




That was for ONE WORD! You can find it by scrolling down to line 400.



Just to reiterate: 400 lines of crap for one 12 letter word.  Amazing.

 November 11, 2008

 iMakeDecisions is launched

I feel bad about not mentioning this earlier.  Some of my buddies from MobileDataForce just launched their first IPhone application: IMakeDecisions.

www.iMakeDecisions.com

Description from the site:

Let iMakeDecisions help you choose where to dine, decide when your product should launch, pick the color of your bridesmaids’ dresses, determine who should pick up the tab, select the name for your child, choose which movie to watch, pick your mood for the day, determine the value of your house, accept or reject the job offer, turn left or right, pick a new hairstyle, determine if a country has weapons of mass destruction, choose your college major, create your stock portfolio, pick your vice presidential running mate, determine guilt or innocence, select who to fire or hire, clarify your love life and/or select a candidate. iMakeDecisions can make all those decisions and more! Imagine having a decision-free life both personally and professionally.

 October 10, 2008

 INETA Community Champion

I'm not bragging (really, I'm not), I'm just posting information...about me...winning an award.  Crap, that is bragging isn't it.  Oh well, the show must go on.

I'm an INETA Community Champion for 2nd Quarter 2008.

You can read more about what it take to become a Community Champion at INETA's web site (see link above).

 On the Alt.Net Podcast

This post is a bit late, but I thought I should mention that I'm on the Alt.Net Podcast talking about JQuery in ASP.Net with Rick Strahl, Dave Ward, Bertrand Le Roy, Scott Koon, and Steven Harman.

This was a fun podcast to be on, even though we had a few hick-ups along the way (I kept disconnecting -- thank you Skype and Steve's hard drive crashed).  But having Rick Strahl and Dave Ward there was great (if you like JQuery and work on ASP.Net, you need to read their blogs). 

But having Bertrand there was absolutely wonderful.  Bertrand is a Microsoft employee that was there for the conversations that led to the JQuery announcement.

Mike Moore is doing an excellent job on these.  If you haven't seen this podcast before, I highly recommend it.

http://altnetpodcast.com/episodes/11-jquery-in-asp.net

 October 04, 2008

 LINQ in Depth: Understanding ToArray()

In my last post, I showed a bit of code that would take any list, array, diction, or IEnumerable implementer, and return a delimited string.

My solution created a StringBuilder, then looped thru the list, adding the values to the StringBuilder each time.  Then, finishing up, remove the last delimiter.

The other solution is to use the LINQ ToArray method, the pass the result to String.Join. 

You can see the code for both extension methods below.

   1: public static class Extensions


   2: {


   3:     public static string ToDelimitedString<T>(this IEnumerable<T> list, string delimiter, Func<T, string> action)


   4:     {


   5:         var sb = new StringBuilder();


   6:  


   7:         foreach (T t in list)


   8:         {


   9:             sb.Append(action.Invoke(t));


  10:             sb.Append(delimiter);


  11:         }


  12:         sb.Remove(sb.Length - delimiter.Length, 1);


  13:         return sb.ToString();


  14:     }


  15:  


  16:     public static string ToDelimitedString2<T>(this IEnumerable<T> list, string delimiter, Func<T, string> action)


  17:     {


  18:         return string.Join( delimiter, list.Select( action ).ToArray() );


  19:     }


  20:  




Next I thought it would be interesting to see what the ToArray was actually doing.  ToArray is a Linq function that converts anything that inherits from IEnumerable to an array.



An IEnumerable is a list of undetermined length, and an array has a definite length, so there has to be some sort of reallocation going on.  Enter Reflector (now a RedGate product), with Reflector you can select a method and hit Disassemble to inspect the innards.  When looking for LINQ methods, you look in the dll System.Core.  Below is what you will find.





   1: public static TSource[] ToArray<TSource>(this IEnumerable<TSource> source)


   2: {


   3:    if (source == null)


   4:    {


   5:       throw Error.ArgumentNull("source");


   6:    }


   7:    Buffer<TSource> buffer = new Buffer<TSource>(source);


   8:    return buffer.ToArray();


   9: }




The interesting part is the Buffer class -- sorry, struct -- which is an internal object.  When you start browsing the .Net Framework you will see lots of internal objects running around, some useful, some not.  You get used to it.



Anyway, you can see below that Buffer creates an array, then loops though the source object (an IEnumerable of something), adding elements to the array.  If the array runs out of space, a new array is created that is double the size of the original array (note that the initial array size is 4). This is standard collection behavior as well, you can look it up in the generic List.





   1: internal struct Buffer<TElement>


   2: {


   3:    internal TElement[] items;


   4:    internal int count;


   5:    internal Buffer(IEnumerable<TElement> source)


   6:    {


   7:       TElement[] array = null;


   8:       int length = 0;


   9:       ICollection<TElement> is2 = source as ICollection<TElement>;


  10:       if (is2 != null)


  11:       {


  12:          length = is2.Count;


  13:          if (length > 0)


  14:          {


  15:             array = new TElement[length];


  16:             is2.CopyTo(array, 0);


  17:          }


  18:       }


  19:       else


  20:       {


  21:          foreach (TElement local in source)


  22:          {


  23:             if (array == null)


  24:             {


  25:                array = new TElement[4];


  26:             }


  27:             else if (array.Length == length)


  28:             {


  29:                TElement[] destinationArray = new TElement[length * 2];


  30:                Array.Copy(array, 0, destinationArray, 0, length);


  31:                array = destinationArray;


  32:             }


  33:             array[length] = local;


  34:             length++;


  35:          }


  36:       }


  37:       this.items = array;


  38:       this.count = length;


  39:    }


  40:  


  41:    internal TElement[] ToArray()


  42:    {


  43:       if (this.count == 0)


  44:       {


  45:          return new TElement[0];


  46:       }


  47:       if (this.items.Length == this.count)


  48:       {


  49:          return this.items;


  50:       }


  51:       TElement[] destinationArray = new TElement[this.count];


  52:       Array.Copy(this.items, 0, destinationArray, 0, this.count);


  53:       return destinationArray;


  54:    }


  55: }




Now, in spite of the differences between the methods used to return the same results, my initial thought was that there would not be much of a difference, performance wise, in how the code ran.  So to test that theory I ran the following tests.



My tests class create a large string list, which is then handed to each method after it is created.  I used the same string for every item in the list, because uniqueness didn't interest me for this test.  Plus, it limited the size of the lists I could create.  If I used unique strings, the largest list I could create was 8,000,000 before I got out of memory exceptions.  Using the same string I could get 20,000,0000.





   1: [TestFixture]


   2: public class ToDelimitedString_Tests


   3: {


   4:     private List<string> _list;


   5:  


   6:     public ToDelimitedString_Tests()


   7:     {


   8:         int count = 2500000;


   9:         _list = new List<string>( count );


  10:         for (int i = 0; i < count; i++)


  11:         {


  12:             _list.Add( "Item" );


  13:         }


  14:     }


  15:  


  16:     [Test]


  17:     public void ToDelimitedString_Mine()


  18:     {


  19:         string result = _list.ToDelimitedString("----", x=>x);


  20:     }


  21:     [Test]


  22:     public void ToDelimitedString_Theirs()


  23:     {


  24:         string result = _list.ToDelimitedString2("----", x=>x);


  25:     }


  26: }




Below you can see the results (charted and in a table) in seconds.  Smaller numbers are better.



image



 












































































 



ToDelimitedString



ToDelimitedString2



10,000



0.04



0.04



100,000



0.09



0.07



1,000,000



0.28



0.35



2,500,000



0.65



0.85



5,000,000



1.26



1.81



7,500,000



1.8



2.43



10,000,000



2.52



3.38



20,000,000



5.28



6.72




 



My conclusion from the data: my hypothesis was correct. There is a performance difference between the two methods, and mine does perform better.  Also, as I suspected, there is not a true significant difference between the two methods.  At least for the size of the string lists my current application will handle.  Note that I had to get up to 1 million items before the times even got interesting, and even then everything happened pretty darn quickly. 10,000 items at 0.04 seconds is pretty darn good.  Array sizes below that barely registered.



One interesting note though, I did try to do a profile of the two methods using dotTrace.  When profiling the second method was actually faster than mine -- consistently.  At this point I don't know why that would be.  If you have any ideas please leave me a note.

 October 02, 2008

 ToDelimitedString Extension Method

This has probably been done before, but I thought I would post my implementation.

Take a given generic list (or something that implements IEnumerable, and convert it to a delimited string.

First, declare this delegate somewhere:

   1: public delegate string StringValueDelegate<T>(T obj);




 



Next, in a static class, (I have a class called GeneralExtensions for just this sort of thing), add this code.





   1: public static string ToDelimitedString<T>(this IEnumerable<T> list, string delimiter, StringValueDelegate<T> action)


   2: {


   3:     var sb = new System.Text.StringBuilder();


   4:     foreach (var t in list)


   5:     {


   6:         sb.Append(action.Invoke(t));


   7:         sb.Append( delimiter );


   8:     }


   9:     sb.Remove(sb.Length - 1, 1);


  10:  


  11:     return sb.ToString();


  12: }




Now if I have a customer class with a FirstName and LastName properties, like this:





   1: public class Customer


   2: {


   3:    public string Id { get; set; }


   4:    public string FirstName { get; set; }


   5:    public string LastName { get; set; }


   6: }




And I have a list of them, and want to convert them to a coma delimited list, I would do it like this:





   1: var list = new List<Customer>();


   2: list.Add(new Customer { FirstName="Tom", LastName="Bin" });


   3: list.Add(new Customer { FirstName="John", LastName"Doe" });


   4:  


   5: string result = list.ToDelimitedString(",", c => c.FirstName + " " + c.LastName);




The result will look like this: "Tom Bin, John Doe"

 September 29, 2008

 Generic C# WinForms

When Generics was first released in .Net 2.0, I was kind of surprised how few built in generic types there were.  A List, a dictionary, a event handler; but not much beyond that.  Nothing like what you see with C++ STL, ATL, or WTL. (turns out there are some reasons for that, C++ Templates can do things that C# Generics just can't).  But no matter, we can invent our own.

In my current desktop app, I have a reoccurring need for an OK/Cancel form.  Plus I had a number of things I wanted preset for me. 

The first problem is working with the Generic portion of the C# language.  I want to be able to create the OK/Cancel form like this:

   1: var dlg = new OkCancelForm<MyDisplayControl>();


   2: if (dlg.ShowModal()== DialogResult.OK)


   3: {


   4:   // do something here...


   5: }




Also, I need to be able to retrieve, or load the user control that is being displayed.  I created a property called DisplayControl.  So now I can load and retrieve values from the display control.  I'll expand my sample:





   1: var dlg = new OkCancelForm<MyDisplayControl>();


   2: dlg.DisplayControl.Data = MyData;  // dlg.DisplayControl will be of type MyDisplayControl


   3:                                    // data is a property of MyDisplayControl


   4: var result = dlg.ShowDialog();


   5: if (result == DialogResult.OK)


   6: {


   7:     var data dlg.DisplayControl.Data; 


   8:     // now do something with the data 


   9: }




OK, so that was how I wanted it to work, now onto some real code.



The Implementation



First thing to do is to just create a new form and call it OkCancelForm.  Put on an OK and cancel button just like you normally would.  For a bit of advice on this: I start with two panels, one on the bottom (containing the OK and Cancel buttons) docked to the bottom.  And the other docked to Fill in the middle.  This will host your custom control.



Now C# creates forms with 2 files, OkCancelForm.cs and OkCancelForm.designer.cs.  We first want to look at the OkCancelForm.cs, and change the class declaration to what you see below:





   1: public partial class OkCancelForm<T>: Form where T: ContainerControl, new()



If you compile after doing that, you will see errors (if you are using ReSharper, you wont even have to compile, you'll just see errors).  Turns out we have to change the other half of the partial file implementation that makes up a WinForms form.  So open up the file named OkCancelForm.designer.cs, and change the declaration to match this:



   1: partial class OkCancelForm<T>




Even though the class names were the same, because one class was a generic class and the other was not, they did not match.



But, diving into the syntax a bit from the first sample.  After the form declaration you see this code: "Form where T: ContainerControl, new()".  This code tells the generic (T) that T must be of type ContainerControl, and must have a default constructor that takes now parameters -- because this class is going to create a new instance of T when OkCancelForm is created.  You can't be passing in stuff through the controls constructor.  It just wont work.



Now for some more changes to OkCancelForm.cs.  Here you can see we are adding InitializeDisplayControl() to create a new copy of the display control, and we have added a property called display control of type T (which must be a ContainerControl, remember).  The other little trick we are doing there is making the control full screen. 



You will also see a reference to displayPanel on like 14.  That is one of the two panels I mentioned previously that is docked to the form in fill mode (the other is docked to the bottom of the form and holds the OK and cancel buttons).





   1: private T _displayControl;


   2: public OkCancelForm()


   3: {


   4:     InitializeComponent();


   5:     InitializeDisplayControl();


   6: }


   7:  


   8: public T DisplayControl { get { return _displayControl;  } }


   9:  


  10: private void InitializeDisplayControl()


  11: {


  12:     _displayControl = new T();


  13:     _displayControl.Dock = DockStyle.Fill;


  14:     displayPanel.Controls.Add(_displayControl);


  15: }




 



That is the basics of what you need.  Still undone in this sample is validation.  But the tricky part (knowing how to make a partial class generic) is pretty well spelled out for you here.



Enjoy.  And if you have any questions, please leave them in the comments.

 September 23, 2008

 I love FirstOrDefault

I know all of you who are using C# 3.0 (released with .Net 3.5) have found some of the goodness that is in System.Linq.  My current favorite is FirstOrDefault.  This little extension method returns the first element of a list, or the first element that meets a criteria, or returns the object's default value.   If you have done work with generics, you should be familiar with default already.  Default for nullable types is null.  Default for value types is...it depends on the type.

Example 1:

Here is my old code:

   1: List<string> list = LoadList();


   2: if (list.Count > 0)


   3:    return list[0];


   4: else


   5:    return null;




This is the new code with FirstOrDefault:





   1: List<string> list = LoadList();


   2: return list.FirstOrDefault();




 



Example 2:



Old code:





   1: List<string> list = LoadList();


   2: foreach(var s in list)


   3: {


   4:   if (s == "My special text")


   5:   {


   6:     return s;


   7:   }


   8: }


   9: return null;




New Code:





   1: List<string> list = LoadList();


   2: return list.FirstOrDefault( s => s == "My special text");