Tuesday, November 17, 2009

Book review: Professional Refactoring in C# & ASP.NET

Three months ago I was looking up to refactoring a legacy ASP.NET Webforms application. Although I was familiar with refactoring, I ordered "Professional Refactoring in C# & ASP.NET" by Daniejel Arsenovski to get deeper into refactoring.

The title

Although the title states "Professional", I think this book should find it's main audience in coding novices. Another problem with the title is the word ASP.NET in it. The book has one chapter covering ASP.NET, with only 35 poor-quality pages in it.

Now the title has some issues, but how was the content?

The content

Danijel identifies codesmells and shows refactoring techniques to solve them. Too bad some of these examples are spreaded over multiple pages, which makes them a tad sloppy and hard to read. Danijel stresses how important Object Oriented design is. He proves this by transforming procedural code into Object Oriented code, greatly improving the readability. This book should help developers who are new to or come from a non-OO background to apply the basic Object Oriented concepts. Next to refactoring techniques, he also touches refactoring tools, unit testing and design patterns.

I think the beginning .NET developer might be able to significally start improving his codebase by reading this book. For more experienced .NET developers most of the topics handled in the book should be part of their day-to-day skillset.

Conclusion

All by all I was a bit dissapointed by the book, it was an easy read, had a few interesting tricks, but I expected it would go more into depth.

Something valuable I realised though.. is that refactoring isn't something you learn by reading a book, but you learn it by obeying the constant hunger for improving your code.

If you feel confident that you dig the basic concepts of writing quality code, I would instead of buying this book, invest in a good book on Object Oriented concepts or design patterns.








Grab my feeds

Monday, November 9, 2009

My trip to Madrid in ten pictures

Last week I went to Madrid with my family-in-law to visit my girlfriend's brother and cousin.

Although our stay there was rather short (only four days), we visited some of the most impressive places in Madrid:
- Stadium Real Madrid
- The Royal Palace
- Prado Museum
- Queen Sofia Museum
- Buen Retiro Park
- Plaza Mayor
- ...


As always my girlfriend took lots of pictures, you can find my favorites below. Enjoy :)

Stadium Real Madrid



Pay attention to the stitching "Jesus in first place"


Royal Palace





Ruïnes of an Egyptian temple



Buen Retiro Park




Older lady feeding the birds. I wonder what her trick is.. Four of us tried letting them eat out of our hands, but we all failed.




Grab my feeds

Sunday, November 1, 2009

Walking through a new Web Application in Visual Studio 2010 (.NET 4.0)

Although I installed Visual Studio 2010 Beta 2 the first day it came out, today was the first day I made a new Web Application. In this post I will walk you through creating a new Web Application in Visual Studio 2010. I'll show you what's new and what's different.

Creating a new Web Application



Create new project

After clicking the New project link, you will see an improved Project Template window.

Search for the Web node in the Project Templates tree. You might notice that there are three new Project Templates: Empty ASP.NET Web Application, ASP.NET Web Application and ASP.NET MVC 2 Web Application.

In this post I'll show the ASP.NET Web Application template.



Select ASP.NET Web Application

New stuff in the this template

When you look at the Solution Explorer, you will notice that there more default folders and pages. Let me walk you through them.



Solution Explorer

New references

There are some new default references.

1: Microsoft.CSharp
The Microsoft.CSharp namespace contains classes that support compilation and code generation using the C# language.
Source: Msdn


2: System.Web.ApplicationServices
The System.Web.ApplicationServices namespace provides classes that enable you to access ASP.NET forms authentication, roles, and profiles application services as Windows Communication Foundation (WCF) services.
Source: Msdn


3: System.Web.DynamicData
The System.Web.DynamicData namespace contains classes that provide the core functionality for ASP.NET Dynamic Data. It also provides extensibility features that let you customize dynamic data behavior.
Source: Msdn


The Account folder

This folder holds a few default pages that provide default membership functionality. Yes, that's right, a membership provider is baked in this template.



The Login page



The Register page

The App_Data folder

In this folder you will find the membership database.

The scripts folder

This folder holds the jQuery(!) javascript files. Yep jQuery is now even shipping with Web Forms out of the box.

Styles

Here you will find the CSS file that's used throughout the web application.

Wonder where the Webforms team got their inspiration from ;)



The default style

The Default and About page

The Default.aspx page has been here forever, but the About.aspx page is new. And it does exactly what you think it does. You can supply some information about you or your application in this page.

Global.asax

The Global.asax is there by default. A nice feature that has been added are inline comments that help you understand the most common application events.



   1:  namespace MyFirstWebApplication
   2:  {
   3:      public class Global : System.Web.HttpApplication
   4:      {
   5:   
   6:          void Application_Start(object sender, EventArgs e)
   7:          {
   8:              // Code that runs on application startup
   9:   
  10:          }

  11:   
  12:          void Application_End(object sender, EventArgs e)
  13:          {
  14:              //  Code that runs on application shutdown
  15:   

  16:          }
  17:   
  18:          void Application_Error(object sender, EventArgs e)
  19:          {
  20:              // Code that runs when an unhandled error occurs
  21:   
  22:          }
  23:   
  24:          void Session_Start(object sender, EventArgs e)
  25:          {
  26:              // Code that runs when a new session is started

  27:   
  28:          }
  29:   
  30:          void Session_End(object sender, EventArgs e)
  31:          {
  32:              // Code that runs when a session ends. 
  33:              // Note: The Session_End event is raised only when the sessionstate mode
  34:              // is set to InProc in the Web.config file. If session mode is set to StateServer 
  35:              // or SQLServer, the event is not raised.

  36:   
  37:          }
  38:   
  39:      }

  40:  }


Site.Master

A default master page comes with the template as well.

Conclusion

Although I rather will use the Empty ASP.NET Web Application, I think this template is a great effort to push best practices to the novice Web Forms developer. This template helps you getting started with the most powerful features of Webforms.

What are your thoughts on this new template? Will you use it?

Grab my feeds

Saturday, October 24, 2009

Linqify your legacy webapplications: five real-world refactor examples

Edit notes:
- Edited examples based on Bart's feedback (see comments).

This post is meant for developers who are upgrading legacy webapplications to .NET 3.5 and for developers who know Linq, but have a hard time finding scenarios to apply Linq.

I got my inspiration for this post by reading Professional Refactoring in C# & ASP.NET (Wrox Programmer to Programmer).

I downloaded the My Web Pages Starter Kit to find some examples, which is written for .NET 2.0. I upgraded it to .NET 3.5 to use Linq.

Below you can find some real-world examples of refactoring to use Linq.

Querying collections never has been this clean!


Example one

Before

   1:  bool blnTravelDiary = false;
   2:  foreach (string theme in themes) {
   3:      if (Path.GetFileName(theme) == "TravelDiary")
   4:              blnTravelDiary = true;
   5:  }


After

   1:  bool blnTravelDiary = themes.Any(theme => Path.GetFileName(theme) == "TravelDiary"); 



Example two

Before

   1:  foreach (RoleData data in _roles) {
   2:      if (data.RoleName.Equals(roleName, StringComparison.CurrentCulture))
   3:              return true;
   4:  }
   5:  return false;


After

   1:  bool exists = _roles.Any(roleData => roleData.RoleName.Equals(roleName, StringComparison.CurrentCulture));



Example three

Before

   1:  foreach (RoleData data in _roles) {
   2:      if (data.RoleName == rolename) {
   3:              found = data;
   4:                      break;
   5:           }
   6:  }

   7:  return found;


After

   1:  var found = from RoleData data in _roles
   2:              where data.RoleName == rolename
   3:              select data;
   4:  return found.FirstOrDefault();



Example four

Before

   1:  List<string> foundRoles = new List<string>();
   2:  foreach (RoleData data in _roles){
   3:      if (data.Users.Contains(username))
   4:              foundRoles.Add(data.RoleName);
   5:  }
   6:  return foundRoles.ToArray();


After

   1:  var data = from RoleData roleData in _roles
   2:             where roleData.Users.Contains(username)
   3:             select roleData.RoleName;
   4:  return data.ToArray();



Example five

Before

   1:  foreach (MembershipUser user in Membership.GetAllUsers())
   2:  {
   3:      if (string.Compare(user.UserName, txtUserName.Text, true) == 0)
   4:          {
   5:              Login1.UserName = user.UserName;
   6:                     return;
   7:          }
   8:  }



After

   1:  var matchingUsers = from MembershipUser user in Membership.GetAllUsers()
   2:                      where string.Compare(user.UserName, txtUserName.Text, true) == 0
   3:                     select user.UserName;
   4:   
   5:  var firstMatch = matchingUsers.FirstOrDefault();
   6:   
   7:  if (firstMatch != null) {
   8:      Login1.UserName = firstMatch;
   9:  }



Grab my feeds

Friday, October 23, 2009

The evolution of the Windows desktop in images, from Windows 3.1 To Windows 7.

@CodingHorror: I can't deal with Chrome themes or Windows 7 themes... at all. Give me plain, simple, clean, and uncluttered. kthxbye

Jeff Atwood tweeted this a few days ago. This triggered me to assemble a list of Windows desktops, from Windows 3.1 to Windows 7.

I also don't think the extra UI stuff in Windows Vista and Windows 7 add extra value. I'm still a big fan of the simple Windows XP UI.

Which one do you like best? Is there to much clutter in the new interfaces?

Check out the list of images below to see the evolution of the Windows desktop.

Windows 3.1


Windows 3.5


Windows 3.51


Windows 4


Windows 95


Windows 98


Windows 2000


Windows XP


Windows Vista


Windows 7





Grab my feeds

Sunday, October 18, 2009

Building a simple Twitter widget using TweetSharp and ASP.NET

Widgets are a great way to spread your content. Users can just copy and paste some simple HTML or JavaScript, and off they are. By embedding this HTML or JavaScript, content is loaded from another server. Perfect examples are Google ads and Amazon ads.

I wondered how hard it could be. That's why I wrote a small Twitter widget using ASP.NET and TweetSharp. This widget simply shows your Tweets. To keep things simple it's HTML hosted in an iFrame. This solution might be a scalability nightmare tho, because it's executing the code every time the page loads.

When finished the widget looked something like this.



Let's take a look how you can build your own.

Get tweets by username

I used the very Elegant TweetSharp API for this.



   1:  private IEnumerable<TwitterSearchStatus> GetStatuses(string screenName) {
   2:       var twitter = FluentTwitter.CreateRequest().
   3:                                  Search().Query().FromUser(screenName);

   4:       return twitter.Request().AsSearchResult().Statuses;
   5:  }      



Build the widget

This method builds the HTML. I used the HtmlTextWriter class for this. A safe way to build HTML.


   1:   private String BuildWidget(string username, IEnumerable<TwitterSearchStatus> statuses) {
   2:              StringWriter stringWriter = new StringWriter();
   3:              
   4:              using (HtmlTextWriter htmlWriter = new HtmlTextWriter(stringWriter)) {
   5:                  htmlWriter.RenderBeginTag(HtmlTextWriterTag.B);
   6:                  htmlWriter.Write("My tweets");

   7:                  htmlWriter.RenderEndTag();
   8:   

   9:                  htmlWriter.RenderBeginTag(HtmlTextWriterTag.Div);
  10:                  htmlWriter.RenderBeginTag(HtmlTextWriterTag.Ul);
  11:   
  12:                  foreach (var status in statuses) {
  13:                      htmlWriter.RenderBeginTag(HtmlTextWriterTag.Li);
  14:   
  15:                      htmlWriter.Write(String.Format("({0})", status.CreatedDate.ToString("hh:mm")));
  16:                      htmlWriter.Write(" ");
  17:                      htmlWriter.Write(status.Text);
  18:                      
  19:                      htmlWriter.RenderEndTag();
  20:                  }           
  21:   
  22:                  htmlWriter.RenderEndTag();
  23:   
  24:                  htmlWriter.AddAttribute(HtmlTextWriterAttribute.Href, "http://twitter.com/" + username);                
  25:                  htmlWriter.RenderBeginTag(HtmlTextWriterTag.A);
  26:                  htmlWriter.Write("Follow me");
  27:                  htmlWriter.RenderEndTag();
  28:   
  29:                  htmlWriter.RenderEndTag();
  30:              }
  31:   
  32:              return stringWriter.ToString();             
  33:          }



Writing the widget to the page

On the Page_Load event of the Page I get the username from the QueryString, get the statuses for this username, pass them to the BuildWidget method and write that result to the Reponse Stream.


   1:  protected void Page_Load(object sender, EventArgs e) {
   2:              string username = Request.QueryString["username"];;
   3:              if (!String.IsNullOrEmpty(username)) {
   4:                  Response.Write(BuildWidget(username, GetStatuses(username)));
   5:              }
   6:          }



Embedding the widget in a page

I hosted the widget in an iFrame. Set the src attribute of the iFrame to the url of your widget.


   1:  <div style="width:30%;height:100%;float:right"> 
   2:              <iframe scrolling="yes" 
   3:                  style="" 
   4:                  frameborder="1" 
   5:                  src="http://localhost:1524/TwitterWidget.aspx?username=JefClaes" 
   6:                  marginheight="0" 
   7:                  marginwidth="0">
   8:              </iframe> 
   9:          </div> 



That was pretty easy right?

Get the source.

Grab my feeds

Saturday, October 17, 2009

Scripting together a Twitter Client, using ASP.NET and Tweetsharp. Doing the Top-To-Bottom.

This week Joe Stagner blogged on Write ASP.NET without Web Forms or MVC !.

This post made me think of my years in school when I was hacking together webapplications in old ASP. It inspired me to try the Top-To-Bottom once again.

I scripted a Twitter client Top-Top-Bottom in ASP.NET using the fluent TweetSharp API. Do you find this API as sexy as I do?

I used TableCloth to decorate the tweets table.

Here is a screenshot of the result.



The code can be found below.



   1:  <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="ScriptedTwitterClient._Default" EnableViewState="false"%>
   2:   
   3:  <%@ Import Namespace="Dimebrain.TweetSharp" %>
   4:  <%@ Import Namespace="Dimebrain.TweetSharp.Fluent" %>
   5:  <%@ Import Namespace="Dimebrain.TweetSharp.Model" %>
   6:  <%@ Import Namespace="Dimebrain.TweetSharp.Extensions" %>
   7:   
   8:  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   9:   
  10:  <script runat="server">
  11:      private const string TWITTER_LOGIN_USERNAME = "YOUR_USERNAME_GOES_HERE";
  12:      private const string TWITTER_LOGIN_PASSWORD = "YOUR_PASSWORD_GOES_HERE";   
  13:         
  14:      private string ShowUrlsAsHtml(string text){
  15:          Regex regx = new Regex("http://([\\w+?\\.\\w+])+([a-zA-Z0-9\\~\\!\\@\\#\\$\\%\\^\\&amp;\\*\\(\\)_\\-\\=\\+\\\\\\/\\?\\.\\:\\;\\'\\,]*)?", RegexOptions.IgnoreCase);
  16:   
  17:          //A shameless copy from http://weblogs.asp.net/farazshahkhan/archive/2008/08/09/regex-to-find-url-within-text-and-make-them-as-link.aspx
  18:          foreach (Match match in regx.Matches(text)) {
  19:              text = text.Replace(match.Value, "<a href='" + match.Value + "'>" + match.Value + "</a>");
  20:          }
  21:   
  22:          return text;      
  23:      }
  24:  </script>
  25:   
  26:  <html xmlns="http://www.w3.org/1999/xhtml" >
  27:  <head runat="server">
  28:      <title>
  29:          Scripting together a Twitter Client, using ASP.NET and Tweetsharp.
  30:          Doing the Top-To-Bottom.
  31:      </title>   
  32:      <link href="Style/tablecloth/tablecloth.css" rel="stylesheet" type="text/css" media="screen" />
  33:      <script type="text/javascript" src="Style/tablecloth/tablecloth.js"></script>
  34:  </head>
  35:  <body>
  36:      <form id="form1" runat="server">   
  37:      <div align="center">
  38:          <img src="Style/images/twitterlogo.jpg" alt="TwitterLogo" />
  39:      </div>
  40:      <div>    
  41:          <% TwitterClientInfo clientInfo = new TwitterClientInfo();
  42:             clientInfo.ClientName = "TwitterClient";
  43:            var twitter = FluentTwitter.CreateRequest()
  44:                 .AuthenticateAs(TWITTER_LOGIN_USERNAME, TWITTER_LOGIN_PASSWORD)
  45:                 .Statuses().OnFriendsTimeline().AsXml();
  46:            var response = twitter.Request();
  47:            var statuses = response.AsStatuses(); %>
  48:          <table cellspacing="0" cellpadding="0">                
  49:              <% if (statuses == null) {
  50:                     Response.Write("Something is wrong. No statuses are found.");
  51:                     Response.Write(response.AsError().ErrorMessage);
  52:                 }else{                                            
  53:                     foreach (TwitterStatus status in statuses) {
  54:                         Response.Write("<tr>");
  55:                         Response.Write(String.Format("<td><b><a href='{0}'>{1}</a></b></td>", 
  56:                                                              status.User.Url, status.User.ScreenName));
  57:                         Response.Write(String.Format("<td>{0}</td>", ShowUrlsAsHtml(status.Text)));
  58:                         Response.Write(String.Format("<td>{0}</td>", status.CreatedDate.ToString("hh:mm")));
  59:                         Response.Write("</tr>");
  60:                     }
  61:                 }
  62:              %>  
  63:          </table>      
  64:      </div>
  65:      </form>
  66:  </body>
  67:  </html>


This is something you should try at home, and not at the office ;)

Download the source.

Grab my feeds