SDN Article on MVC Framework

Published 3/9/2009 by Henry in ASP.NET | C#
Tags: ,

My article (in dutch) with the title: ASP.NET Webapplications finally unit-testable, or (ASP.NET webapplicaties eindelijk unit-testbaar in dutch) is been published in the 100th edition of the SDN Magazine (Software Developers Network). SDN 100th Magazine in pdf format and is available for download.

VP100100th SDN Magazine

Henry Cordes
My thoughts exactly…


I am in the middle of the analysis fase for the project I mentioned in the post about using WCSF for ASP.NET (and Sharepoint) Usercontrols.  I know how I am going to integrate the UserControls into SharePoint in such a way, that the controls can be used in SharePoint and in custom ASP.NET Web applications.
I am going to use the MVP pattern without the help of WCSF or CWAB, but with the help of Unity. I will post an article in more detail about this in the near future.
For now I want to share a simple ASP.NET composite control I need, to make it easier to have watermark functionality for every textbox on a page, without having to add a TextBoxWatermarkExtender for every TextBox.

The way I accomplish this is by creating a composite control with a TextBox and a TextboxWatermarkExtender on it.

The code:

   1:  using System;
   2:  using System.ComponentModel;
   3:  using System.Web.UI;
   4:  using System.Web.UI.WebControls;
   5:  using AjaxControlToolkit;
   6:   
   7:  namespace HC.Web.Controls
   8:  {
   9:   
  10:       [DefaultProperty("Text"),
  11:        ValidationProperty("Text"),
  12:        Description("TextBox with Watermark capabilities"),
  13:        ToolboxData("<{0}:WatermarkTextBox runat=server></{0}:WatermarkTextBox>")]
  14:      public class WatermarkTextBox: CompositeControl
  15:      {
  16:          #region Private members
  17:           private TextBox textBox;
  18:           private TextBoxWatermarkExtender watermarkExtender;
  19:   
  20:           private string _DefaultWatermarkText = "Watermark";
  21:          #endregion
  22:   
  23:          #region Properties
  24:           /// <summary>
  25:           /// Gets the ClientID of the textbox
  26:           /// </summary>
  27:          [Bindable(true),
  28:          Category("Behavior"),
  29:          Description("The TextBoxClientID of the WatermarkTextBox"),
  30:          DefaultValue("")]
  31:          public string TextBoxClientID
  32:           {
  33:               get
  34:               {
  35:                   EnsureChildControls();
  36:                   return textBox.ClientID;
  37:               }
  38:           }
  39:   
  40:           /// <summary>
  41:           /// Gets or sets the Text in the textbox
  42:           /// </summary>
  43:           [Bindable(true),
  44:          Category("Behavior"),
  45:          Description("The text of the textbox"),
  46:          DefaultValue("")]
  47:           public string Text
  48:           {
  49:               get
  50:               {
  51:                   EnsureChildControls();
  52:                   return textBox.Text;
  53:               }
  54:               set
  55:               {
  56:                   EnsureChildControls();
  57:                   textBox.Text = value;
  58:               }
  59:           }
  60:   
  61:           /// <summary>
  62:           /// Gets or sets the CssClass of the Textbox
  63:           /// </summary>
  64:           [Bindable(true),
  65:           Description("The css class that is used when the textbox is in it's normal state"),
  66:           Category("Appearance"),
  67:           DefaultValue("")]
  68:           public override string CssClass
  69:           {
  70:               get
  71:               {
  72:                   EnsureChildControls();
  73:                   return textBox.CssClass;
  74:               }
  75:               set
  76:               {
  77:                   EnsureChildControls();
  78:                   textBox.CssClass = value;
  79:               }
  80:           }
  81:   
  82:           /// <summary>
  83:           /// Gets or sets the CssClass for the watermark state of the Textbox
  84:           /// </summary>
  85:           [Bindable(true),
  86:            Description("The css class that is used when the textbox is in it's watermark state"),
  87:            Category("Appearance"),
  88:            DefaultValue("")]
  89:           public string WatermarkCssClass
  90:           {
  91:               get 
  92:               { 
  93:                   EnsureChildControls();
  94:                   return watermarkExtender.WatermarkCssClass;
  95:               }
  96:               set 
  97:               { 
  98:                   EnsureChildControls();
  99:                   watermarkExtender.WatermarkCssClass = value;
 100:               }
 101:           }
 102:   
 103:           /// <summary>
 104:           /// Gets or sets the Text for the watermark
 105:           /// </summary>
 106:          [Bindable(true),
 107:           Category("Appearance"), 
 108:           Description("The (watermark)text that is shown when the textbox is in it's watermark state"),
 109:           DefaultValue("")]
 110:          public string WatermarkText 
 111:          {
 112:               get 
 113:               { 
 114:                   EnsureChildControls();
 115:                   return watermarkExtender.WatermarkText;
 116:               }
 117:               set 
 118:               { 
 119:                   EnsureChildControls();
 120:                   watermarkExtender.WatermarkText = value;
 121:               }
 122:          }
 123:   
 124:           /// <summary>
 125:           /// Gets or sets DefaultWatermarkText, cannot be empty
 126:           /// </summary>
 127:          [Bindable(true),
 128:          Category("Appearance"),
 129:          Description("The default (watermark)text that is shown when the textbox is in it's watermark state, and the WatermarkText property is empty"),
 130:          DefaultValue("")]
 131:          public string DefaultWatermarkText
 132:          {
 133:              get { return _DefaultWatermarkText; }
 134:              set 
 135:              { 
 136:                  if (value.Length > 0)
 137:                      _DefaultWatermarkText = value; 
 138:              }
 139:          }
 140:          #endregion
 141:   
 142:          protected override void RecreateChildControls()
 143:          {
 144:              EnsureChildControls();
 145:          }
 146:   
 147:          protected override void CreateChildControls()
 148:          {
 149:              SetTextBoxIdIfEmpty();
 150:              this.Controls.Add(textBox);
 151:              watermarkExtender.ID = textBox.ID + "_waterMarkExtender";
 152:              watermarkExtender.TargetControlID = textBox.ID;
 153:   
 154:              if (WatermarkText == "")
 155:              {
 156:                  WatermarkText = DefaultWatermarkText;
 157:              }
 158:              this.Controls.Add(watermarkExtender);
 159:          }
 160:   
 161:          #region Worker Methods
 162:          /// <summary>
 163:          /// Fills textBox ID if empty.
 164:          /// Format: ID + '_textBox'
 165:          /// </summary>
 166:           private void SetTextBoxIdIfEmpty()
 167:          {
 168:              if (string.IsNullOrEmpty(textBox.ID))
 169:              {
 170:                  textBox.ID = this.ID + "_textBox";
 171:              }
 172:          }
 173:          #endregion
 174:        
 175:           #region C'tor
 176:           public WatermarkTextBox()
 177:           {
 178:               textBox = new TextBox();
 179:               watermarkExtender = new TextBoxWatermarkExtender();
 180:           }
 181:           #endregion
 182:   
 183:      }
 184:  }

Listing: 1

As you can see in the code in listing 1,in the override of the CreateChildControls the actual adding of the controls to the control collection of the composite container is done.
It is important to make sure the textbox has a valid ID. Than you need to set the TargetControlID of the TextboxWatermarkExtender equal to the ID of the TextBox and the WatermarkText needs to be filled.

EnsureChildControls()
When you built a composite control make sure to call EnsureChildControls, so you can be sure the controls are accesible and no object reference not set exception is thrown.
A simple but quite useful example.

Henry Cordes
My thoughts exactly…


At the moment I am in the middle of the analysis phase for a project where the product will be constructed of several (User)Controls that contain certain blocks of functionality, these controls together will create the product.
Our first client needs this product to integrate with SharePoint 2007 (MOSS 2007), but my product manager makes it real clear that at least some of the ‘blocks of functionality’ or ‘components’ need to have the possibility be integrated in existing ASP.NET web applications.

So the challenge I face is creating controls that can be integrated inside SharePoint and custom ASP.NET web apps. Another challenge is that we really want to use the MVP, or MVC pattern, to increase the level of (unit)testability and maintainability. 
Also with testability in mind I want to use some kind of IoC container (Inversion of Control), to make it easier to swap out certain functionalities for others (also a Need To Have requirement), be it for unit testing, or swapping out data store's .

Web Client Software Factory
With all these requirements the Web Client Software Factory came to mind, it leverages the Composite Web Application Block and can use Unity (ObjectBuilder) as Dependency Injection or Inversion of Control Container. When I follow the Quick start however it is quite easy to create a webpage that acts as the View and uses a Presenter and a Controller (all interface based!).
The problem I get is when I want to create a UserControl  as a View that acts indepentently with it’s own Presenter and  Controller, as i am seeing it, the WCSF uses the containing page of a UserControl as the part that maps everything together.

I want to make a really independent control, that can exist all by itself. The learning curve was quite steep, because of my lack of knowledge of the WCSF and CWAB.

Approaches
I am not sure which route I will take in the end, but I am trying different approaches:

  1. Using Return of SmartPart to host a UserControl that consists of Usercontrols built using the Web Client Software Factory;
  2. Create a WebPart (derived from CompositeWeb.SharePoint.Web.UI.WebPart) that hosts UserControls (that are derived from CompositeWeb.SharePoint.Web.UI.UserControl), using the CompositeWeb.Sharepoint.dll and guidance published on the WCSF CodePlex site

SmartPart
For now I created both in a really simple form and find that the SmartPart has a real nice deployment model, you install the SmartPart using a installer and you only have to activate the Smartpart in the SiteCollection to make it available in the available Webpart’s list in SharePoint. You than make a folder with the name ‘usercontrols’ in the root of the sharePoint site, where  you put the .ascx files you want to be hosted. The dll belonging to the UserControl and it’s dependencies are to be placed into the bin directory of the same SharePoint site. I read somewhere that the installer sets the site´s security to full trust, but I can not verify that.

WebPart derived from CompositeWeb.SharePoint.Web.UI.WebPart
The Webpart solution gives a real nice compatibility model. You derive from these types and your webpart and UserControls work in SharePoint and in am ASP.NET webapp. This is achieved through the BuildItemWithCurrentContext method in the SPWebClientApplication class (CompositeWeb.SharePoint.dll). This method runs different code depending on the running HttpApplication implementation. You have to manually edit the global.asax file in the root of the SharePoint site. You have to edit the web.config manually to make several changes, one of them is to set the security to full trust! Part of the web.config changes is to add the PublicKeytoken for the webpart in an attribute of the Safecontrol element for the webpart. Furtermore you have to place the assemblies and their dependencies into the bin directory of the Sharepoint site. Of course you could automate these task by creating an installer, but I think it makes clear that there are lots of manual tasks to be done.

At this point in time I have not decided either way, but I will post when I have.

My thoughts exactly…
Henry Cordes


Version Tracker.NET v 1.0 released

Published 1/26/2009 by Henry in C#
Tags:

Today I released Version Tracker.NET v 1.0. It's a tool that simplifies version management in large solutions. This release only supports C#, but who knows, if someone asks for VB.NET (or another language) to be supported by Version tracker, maybe I will do it.
It is a WPF application, I had not worked with WPF, only Silverlight. I had a lot of fun experimenting and discovering the parts of WPF I needed for this app.

Version Tracker.NET
Version Tracker.NET

I learnt about Templates, Styles, Model-View-ViewModel and on the other side: Solution files, Project files and AssemblyInfo.cs files.
It was so much fun, I am going to try to put more features in Version Tracker.NET and maybe create another tool that's useful.

Quick download links

You can install it through ClickOnce installment or simply download the install.

Click to install Version Tracker.NET v 1.0 through ClickOnce deployment                           Click to download  Version Tracker.NET v 1.0 setup

Pick the ClickOnce deployment version if you always want the latest version, ClickOnce will tell you when a new version is available, pick the setup download if you do not need the latest version as soon as it is available and these features are all you need.

This version (v 1.0) is free for download, if you want the sourcecode drop me a line, you are free to use it, but you must mention me as the original author.

My thoughts exactly...
Henry Cordes


NDepend analyses staticly

Published 1/20/2009 by Henry in C#
Tags:

A few months ago Patrick Smacchia a C# MVP and the author of NDepend approached me to take a look at his product: NDepend

I must admit until than I never done anything with it.

Nevertheless, after I checked the request was really from Patrick, I started to think about it and decided to do it, because:
A.) I felt honoured to be asked;
B.) I was curious if this product could be of value to me

FEATURES
A short overview of the area's NDepend focuses on, I took the area's from NDepend's site:

Conventions, Rules, Constraints Design, analyse and enforce your code conventions, naming guidelines and coding standards
Code Structure, Design, Dependencies     Know and control the design and structure of your code base
Build comparison Design rules to avoid breaking changes, only review changed and newly added code
Metrics Report over number of lines of code, increase testability and readability, coupling, dead code, design flaws
Code Coverage In general, but more important of newly added and refactored code, also it integrates with MS Visual Studio and NCover
Build Process / CI integration NDepend is designed to integrate with: CruiseControl.NET, VSTS Build Server, Nant and many other CI or Build tools

This list already shows that NDepend is more than just a dependency tool. Sure it can help you get an insight into the dependencies of your app or code base, but it is much more than just that.
It can help you get a deep understanding of the design and structure of any code base real fast, so if you are in the consulting business like me, this tool can really help you to get up to speed fast.
Also it can help you enforce design and coding standards, not only in the case of problems, reviews or in consulting gigs, but you can integrate it into your CI an/or build process, to get your code base to live up not only to your (quality) standards, but report about them to your clients and/or users also!
Now we know how valuable this tool is in theory, let's find out how it perform's in the real world.

INSTALLATION
So I installed NDepend, installing in the case of NDepend is nothing more than copying the files onto your harddrive and you are good to go!
I really like this approach, no registry hacks, no dependencies on stuff you do not want on your system, just the 16,6 MB of files and the .NET Framework 2.0 or higher (pic. 1).

 

Picture 1: NDepend Files
Picture 1: NDepend Files

When we start it up it looks quite familiair to the Visual studio user (pic. 2):

Picture 2: Ndepend start pagePicture 2: Ndepend start page

I think the UI is made with the help of DevExpress controls (http://www.devexpress.com/Products/NET/Controls/WinForms/Bars/), so the app has dockable windows like we know and love from Visual Studio and MS Office. NDepend is skinable. In this post I started out using the default skin, but from picture 9 (Dependency Graph) on I use another skin. When I load the first assembly I must admit that I experienced exactly what Scott Hanselman describes in his post about NDepend.

<QUOTE>
The first 10 minutes of NDepend is the hardest. It has to click first. There's the whole "what the hell am I looking at" process, often followed by the "screw this" declaration, followed by a quick uninstallation and a sense of "what happened."
</QUOTE>

For this post I use the Enterprise Library 4.1 and I am going to analyze the DataAccess Application Block by selecting all dll's and .pdb files in the bin directory of the application block's source folder and dragging and dropping them onto the NDepend assembly grid (pic. 3).

Picture 3: Ndepend drag and drop assemblies

After we dropped the grid (pic. 4) shows the assemblies that we dropped onto the grid.

Ndepend drag and drop assembliesPicture 4: Ndepend drag and drop assemblies

When I click on OK, NDepend starts it's magic, after a minute Internet Explorer is loaded with a report that contains all information on the project and the NDepend start page (pic. 2) is replaced with multiple dockable windows, containing multiple windows that present information about the codebase in their own way (pic. 5).

Picture 5: Ndepend First analysisPicture 5: Ndepend First analysis

While the analyzing takes place NDepend shows what it is doing in a for Visual Studio users very familiair way.
The Visual Studio Output Window and the error list rolled into one. It looks the same and it behaves the same. The window in picture 6 shows what NDepend is doing and what the results of it's actions are.

Ndepend Error listPicture 6: Ndepend Error list

NDepend calls this the Error List (familiair?). Because of the complexity that NDepend is dealing with, I think that the familairity with Visual Studio is a good thing. If you are like me, deep inside you know that static code analysis is necessary, but it can get really overwhelming. Making NDepend familair helps getting over the initial "why do I need all this?" feeling, it does not completely remove it, but it helps. In other words: IMO this approach is good .

CLASS BROWSER
As shown in picture 5 left the 'Class Browser' window is shown, again exactly like we are used to in Visual Studio, the NDepend 'Class Browser' shows a treeview with all classes and their methods, properties, interfaces and fields (pic. 7). Not exactly the same, but close enough.

Ndepend class BrowserPicture 7: Ndepend class Browser

CONTEXT (sensitive)
Everything in the NDepend UI is context sensitive, by that I mean wherever you select an item in a list or in a picture the other windows of NDepend show data that is relevant to the selected item.

METRICS
This window (pic. 8) puzzled me a lot at first. what am I looking at?
It is a visual way of showing the codebase, all elements are shown as grey rectangles. which are grouped into a rectangle which is the assembly or class. all methods and members are grey rectangles inside the class rectangle. The rectangles are bigger if they contain more lines of code. You can hover over them with your mouse and information (names etc.) is shown in a context sensitive way. Again, the other windows react to these changes and show data accordingly.

Ndepend MetricsPicture 8: Ndepend Metrics

DEPENDENCY GRAPH
The Dependency Graph (pic. 9) window shows an image that is a visual represantation of the code base (or selected part of the code base!).


Picture 9: Ndepend Dependency Graph

Again it is context sensitive, if you select some class or member in another window, the content of the Dependency Graph changes accordingly and when you hover over a class in the Dependency Graph, the other windows react to this change.

Picture 10: Ndepend Dependency Graph contextPicture 10: Ndepend Dependency Graph context

DEPENDENCY MATRIX
The Dependency Matrix shows the coupling of the classes in  the code base. It shows exactly how many methods and fields are used between all classes.

Ndepend Dependency MatrixPicture 11: Ndepend Dependency Matrix

Picture 11 shows that 74 methods of Microsoft.Practices.EnterpriseLibrary.Data are using 71 members of Microsoft.Practices.EnterpriseLibrary.Common, so green are methods and blue are members.
By right clicking on an item in the matrix a contect menu is opened where several actions can be chosen.

Picture 12: Ndepend Dependency Matrix contect menuPicture 12: Ndepend Dependency Matrix contect menu

CQL QUERIES WINDOW
In this window (pic. 13) the CQL Queries can be selected. When selected the query is done during the analysis. The queries are grouped. NDepend comes with a lot of pre-defined queries. They are called queries for a reason, Patrick Smacchia created his own query language called CQL (Code Query Language). With this language it is possible to query code. CQL is the heart and soul of NDepend, it makes NDepend flexible and extensible. It is possible to create your own groups and CQL queries.
It goes too far for this article to go into detail, but I think it is brilliant to use a query language to analyse code.

Picture 13: Ndepend CQL Queries window

You might think: "real nice that I can write my own queries, but such a query language must be time consuming to learn", and discard this option right away, DON'T! Patrick did not only created his own query language, he also made an editor with intellisense! And it really works, it is really easy to write your own CQL query. Give it a try and you know what I am talking about.

Picture 14: Ndepend Roll your own CQL Queries

While I was working on this article, I came to appreciate NDepend more and more. I think it is a mature and well structured tool.
The integration with NCover, Reflector, Visual Studio 2005 and 2008, CruiseControl.NET, VSTS Build Server and Nant are impressive.
It also provides the possibility to choose another code editor over Visual Studio, all these integration possibilities make it very strong, because no matter what your preference is, NDepend will work with the tools you work with. 

The UI provides all functionality needed, but I hope that in the future we get a WPF based version of NDepend. The Windows forms UI and the DevExpress dockable windows provide all functionality, but in this day and age I just expect that slick look and feel.

Because NDepend focusses on static analysis only and does this very well. The use of CQL, the query language created to query code is brilliant. Every weird aspect that you need to report over in your codebase is possible through this language and it's editor with intellisense.

The way all windows show information about the code base in their own unique but comprehensive way is exactly what you would expect from a tool like this. The way all windows react in a context sensitive way to selections or changes made in other windows, gives me the feeling that this tool is created with a professional in mind and makes it a pleasure to work with NDepend.

My thoughts exactly...
Henry Cordes