My Resume

  • My Resume (MS Word) My Resume (PDF)


Affiliations

  • Microsoft Most Valuable Professional
  • INETA Community Champion
  • Leader, NJDOTNET: Central New Jersey .NET User Group

Sunday, April 19, 2009

Of HTTP Headers and Firefox Add-Ons…

Until just last week we had hosted our main website on a single web server, however an impressive team effort of just a few days brought that situation to a screeching halt when we finally moved everything to a brand new, long-awaited web farm. The benefits of web farms are both well-known and mostly obvious, but it’s not all roses and puppy dogs - web farms certainly bring their share of headaches as well.

One of the pains I immediately felt as soon as we went live was the fact that I had no idea which server in the farm I was hitting with any given request. Yes, of course to you the site user this really shouldn’t (and doesn’t) matter, but for me and my team when something isn’t going quite right, knowing which machine this uninvited behavior is originating from is a crucial piece of information. My knee-jerk reaction was to place some kind of identifier in the page content. To this end, I opened up the master pages on each server, scrolled to the end and plopped in an HTML comment “<!-- A -->”, “<!-- B -->”, and so on. This certainly fit my immediate requirement, but had a few annoying downsides: first off, this certainly wasn’t a maintainable solution, since it would have to be re-applied (probably manually, on every server) with every release and – if that weren’t enough by itself (which it was!) – it was just plain annoying having to right-click, View Source, scroll to the bottom, and search for this identifier. My immediate need was filled, but the geek in me was raging – there had to be a better way!

Take 2: After a bit of consideration, I thought taking advantage of the Footers feature in IIS might be a good idea. I’d never used them before, and didn’t know how well it would work for our goals, but decided to try it out anyway. “Open IIS Management console, right-click on my site, Properties… wait – the HTTP Headers tab!” Most any web developer who’s done a decent bit of AJAX has probably used – or at least seen usage of – custom HTTP Headers as a way of communicating meta-data about web responses (e.g. the “X-MicrosoftAjax” header used in ASP.NET AJAX to identify an AJAX request). Frustrated with myself that I hadn’t thought about this initially, I realized this is exactly where I’d wanted to put this info all along. My initial solution of putting the HTML comment in the text left a bad taste in my mouth for so many reasons, but at this point I realized that the worst part about it was that I was putting response metadata in the content, thus committing a blatant violation of Separating Concerns. After slapping my wrist with a ruler and vowing never to do that again (yeah, right!), I set forth to correct it, quickly adding a new custom HTTP Header called “X-ResponseOrigin” on each of my servers, and each with its own unique value. After going back and removing those silly HTML comments, I sat back, made a few requests and happily viewed the responses coming back in Firebug, knowing exactly which server had produced each one.

So at this point I’m pretty pleased with the way things are going. With Firebug open, I could see everything I needed to in order to troubleshoot server-specific issues. But, after a short time I started getting annoyed again. With every new request, I’d have to scroll down to the bottom of the request history in Firebug, find my request, expand it out, and scroll down, all the while scanning for my new special header. Trying to find this new piece of metadata I added – while arguably better than the previous “View Source, Scroll ‘n Scan” method – was still pretty darn annoying… oh, and what about the guys on my team who didn’t have Firebug?? (NOTE: this is really a hypothetical situation, since it is a well-known team rule that not having Firebug on your machine - even if you’re a non-developer – is punishable by 30 push-ups and having to buy everyone donuts the following morning.) It’s at this point that I remembered what Firebug was to begin with – a Firefox Addon – and realized what I must do next…

Enter the Firefox Addon

I needed to make a custom Firefox Addon to show me what server I was on, right there in my Firefox statusbar. No, it wasn’t a requirement for this project – it was utterly imperative to fulfilling my role of “Lead Code Monkey”; it was my destiny.

A quick Googling brought me to the Mozilla Developer portal, with its wealth of knowledge of all things Mozilla. Come to find out, writing a Firefox Addon is as simple as some XHTML/XML-ish markup and accompanying JavaScript – what could be easier!? The markup was quick – I just had to declare that I wanted a custom statusbarpanel that I could put my content in. The resulting code looked like this:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="chrome://whereami/skin/overlay.css" type="text/css"?>
<!DOCTYPE overlay SYSTEM "chrome://whereami/locale/whereami.dtd">
<overlay id="whereami-overlay"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script src="overlay.js"/>
<stringbundleset id="stringbundleset">
<stringbundle id="whereami-strings" src="chrome://whereami/locale/whereami.properties"/>
</stringbundleset>
<statusbar id="status-bar">
<statusbarpanel id="whereami.location" label="" />
</statusbar>
</overlay>




As you can see, it’s pretty straightforward. We’ve got our standard XML cruft, followed by what looks like a typical JavaScript reference tag, pointing to our script file (which we’ll get to in just a minute). This is followed by our <statusbar> and <statusbarpanel> element, letting Firefox know that all we’re going to need for our UI is a little piece of the existing status bar. We also gave that statusbarpanel an ID so we can easily reference it from our scripts later on. Actually, forget “later on” – let’s go see what those scripts look like!



Before we see the code behind all this, let’s revisit the requirements. Basically, we’re look for this add-on to do two things: get our custom HTTP header from requests that come in, and (if we find one) display it in the browser’s status bar. Initially, I had expected the latter to be the difficult part, but much to my surprise it turned out to be as simple as this one line:



document.getElementById(‘whereami.location’).label = responseOrigin;



The cool part here is the usage of the “document.getElementById()” DOM searching that you’re already used to from your normal JavaScript forays. And, there’s that element ID “whereami.location” that we set earlier in our overlay.xul file. Now that we’ve got the statusbar update figured out, let’s populate the value of responseOrigin



Quick Intro to the XPCOM API


In order to get a chance to look at what the user is browsing, you’ve got to create a class that you can register with Firefox as a listener. From that point, you’ll be notified whenever a browsing event happens – say, when a new response has been received. Before we look at the actual implementation, let’s look at a basic implementation of a Firefox listener class (as taken from the Mozilla Developer Center):



function myObserver()
{
this.register();
}
myObserver.prototype = {
observe: function(subject, topic, data) {
// Do your stuff here.
},
register: function() {
var observerService = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
observerService.addObserver(this, "myTopicID", false);
},
unregister: function() {
var observerService = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
observerService.removeObserver(this, "myTopicID");
}
}




You’ll see, all the magic happens in the observe() method, which gets fired whenever a browser event happens. For the purposes of this app, we’re looking out for any time an http-on-examine-response event is fired, indicating a new response has been received. That’s pretty easy, we’ll just check the value of eventName parameter:



if (topic == "http-on-examine-response") { /* Grab the Response Origin */ }



Now let’s take a look at my implementation:



var whereami = {
requestObserver:
{
isRegistered: false,

observe: function(subject, topic, data)
{
if (topic == "http-on-examine-response") {
var statusBar = document.getElementById('whereami.location');
statusBar.label = "";
var httpChannel = subject.QueryInterface(Components.interfaces.nsIHttpChannel);
var origin = httpChannel.getResponseHeader("X-ResponseOrigin");
if(origin && origin.length > 0)
origin = "Server: " + origin;
statusBar.label = origin;
}
},

get observerService() {
return Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
},

register: function()
{
if(this.isRegistered) return;

this.observerService.addObserver(this, "http-on-examine-response", false);
this.isRegistered = true;
},

unregister: function()
{
if(!this.isRegistered) return;

this.observerService.removeObserver(this, "http-on-examine-response");
this.isRegistered = false;
}
}
};

window.addEventListener("load", function(e) { whereami.requestObserver.register(); }, false);










You can see this is basically the same as the snippet from Mozilla, but I’ve added my logic right into the observe() method (lines 8-16).  Let’s see what we’re doing here:




  1. First, we have to get a reference to our little section of the statusbar that we reserved via the ID that I gave it earlier in the overlay.xul markup, clearing any existing (stale) data (lines 9 & 10)


  2. Then, we examine the HTTP headers that got sent back in our response, looking for the value of the “X-ResponseOrigin” that was sent from the server.  (lines 11-13)


  3. Finally, we’ll update the statusbar label with the value we got from Step 2  (line 15)

Cleaner Validation with ASP.NET MVC Model Binders & the Enterprise Library Validation Application Block

I accidentally stumbled across an awesome combination the other day:  using the Enterprise Library Validation Block with ASP.NET MVC.  Though I’ve played around with them a few times in the past, this is the first time I’ve really started to apply the Validation block in a serious application, and it just so happened to have an ASP.NET MVC website as its client.  My jaw dropped more and more as I started to realize the awesomeness that was unfolding before me…  hopefully this blog post will do the same (or as close as possible) to you!

Using the Enterprise Library Validation Block

It all started with an innocent enough Model requiring a wee bit of validation that I didn’t feel like hand-writing, so (as usual) I turned to the EntLib library to do it for me.  Applying the Enterprise Library Validation Block was surprisingly simple. 

It all started with a simple enough class (the names have been changed to protect the innocent):

public class Product
{
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public double Price { get; set; }
public int Quantity { get; set; }
}



This is basically just a DTO (data transfer object), but this ain’t the Wild West – there are rules, and they need to be followed!  After a few minutes, I’d come up with something like this:

using Microsoft.Practices.EnterpriseLibrary.Validation;
using Microsoft.Practices.EnterpriseLibrary.Validation.Validators;

public class Product
{
[RangeValidator(
1, RangeBoundaryType.Inclusive,             /* Lower Bound */
int.MaxValue, RangeBoundaryType.Inclusive   /* Upper Bound */
)]
public int ID { get; set; }

// Let's assume that we've got a field length limitation in
// our database of 500 characters, which we'll check for here
[StringLengthValidator(
1, RangeBoundaryType.Inclusive,             /* Lower Bound */
500, RangeBoundaryType.Inclusive            /* Upper Bound */
)]
public string Name { get; set; }

// No rules for the description - anything goes!
public string Description { get; set; }

// The Price can be whatever we want, as long as it's positive
[RangeValidator(0, RangeBoundaryType.Inclusive, double.MaxValue, RangeBoundaryType.Inclusive)]
public double Price { get; set; }

// Same deal with the Quantity - we can never have a negative quantity
[RangeValidator(0, RangeBoundaryType.Inclusive, int.MaxValue, RangeBoundaryType.Inclusive)]
public int Quantity { get; set; }


public bool IsValid()
{
return Validate().IsValid;
}

public ValidationResults Validate()
{
return Validation.Validate<Product>(this);
}
}



There are a couple of cool things I like about this setup:



  1. Declarative validation rules:  These rules are very explicit expression of business logic - there is no “if-else-then”, mumbo-jumbo.  In other words, there isn’t any code to worry about… and no code means no bugs (well, less bugs at least :).  Moreover, if any of these business rules change, it’s very easy to update these attributes without hunting around for that stray line of “if-else” code somewhere.  Lastly, I’ve heard talk of these mystical “business people” who are also able to read and understand simple code; and, if you run into one of these guys/gals they’ll easily be able to verify that you have the rules set properly as well.
  2. All of the validation logic is in one place:  all consumers of this class need to do is set its properties and ask the object whether or not it is valid.  There are no stray “if(string.IsNullOrEmpty(product.Name)” scattered through your code, just “if(product.IsValid())”.  I feel like this approach has a decent amount of cohesion.  Granted, it could be a bit more cohesive if we had, say, a separate “ProductValidator”, but this seems like overkill.  Regardless, it was bugging me enough that I actually created a super-class to encapsulate this logic further of the chain of inheritance and that made me feel a bit more comfortable:
  3. public class SelfValidatingBase
    {
    public bool IsValid()
    {
    return Validate().IsValid;
    }
    
    public ValidationResults Validate()
    {
    return ValidationFactory.CreateValidator(this.GetType())
    .Validate(this);
    }
    }
    
    public class Product : SelfValidatingBase
    {
    // ...
    }


As with pretty much anything, there is at least one glaring drawback to this approach:  there is no “real-time” checking.  That is, this approach allows consumers to set invalid values on these validated properties at any time – possibly overwriting valid values without any checks prior to the update.  I think that as long as your application (i.e. developers) know about this limitation, it’s not so much of an issue, at least not for the scenarios I’ve used it in, so this drawback doesn’t really bother me.



Now, let’s see how this applies to ASP.NET MVC…



The Awesomeness that is ASP.NET MVC’s Model Binders



When it comes to me and ASP.NET MVC’s Model Binders it was love at first site – and I haven’t stopped using them since.  In case you’re not sure what I’m talking about, here’s an example.  Instead of an Action with individual parameters and populating a new instance ourselves like this:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(string username, string message, string userUrl)
{
var comment = new Comment
{
Message = message,
Username = username,
UserUrl = userUrl,
PostedDate = DateTime.Now
};
commentsRepository.Add(comment);
return RedirectToAction("Index");
}



We let the MVC framework populate a new instance for us, like this:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Comment comment)
{
commentsRepository.Add(comment);
return RedirectToAction("Index");
}



I just think that’s beautiful, and so I’ve come to (over?)use Model Binders on my Controller Actions almost exclusively. 



ASP.NET MVC Model Binders + Enterprise Library Validation Block = BFF



The magic that I refer to at the beginning of this post first exposed itself when I inadvertently used one of my Model objects like the one I showed earlier as an Action parameter (which was really only a matter of time given the fact that I’d taken to using them so much!) using MVC’s Model Binding, and then created some validation logic for it (if you’re not sure what I’m referring to in regards to “creating validation logic”, you’ll want to check out this article on MSDN before continuing).  As I started writing my validation logic in my Action and populating the ModelState with my validation errors like so:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Product product)
{
if (!product.IsValid())
{
if(string.IsNullOrEmpty(product.Name))
this.ModelState.AddModelError("name", "Please enter a product name");
if(product.Price < 0)
this.ModelState.AddModelError("price", "Price must be greater than 0");
if(product.Quantity < 0)
this.ModelState.AddModelError("quantity", "Quantity must be greater than 0");

return View(product);
}

productRepository.Add(product);
return View("Index");
}



Now, even if I moved this code outside of my Action, I’d still be pretty embarrassed of it…  but after looking at it for a while I realized that I don’t have to do this after all – the EntLib ValidationResult (usually) maps perfectly to MVC’s Model Binding…  and ModelState errors!  Check out the same code, taking advantage of the EntLib validation results:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Product product)
{
var validationResult = product.Validate();
if (!validationResult.IsValid)
{
foreach (var result in validationResult)
this.ModelState.AddModelError(result.Key, result.Message);

return View(product);
}

productRepository.Add(product);
return View("Index");
}



I added this and awesomeness ensued.  The magic comes from the fact that the Key field of the EntLib ValidationResult is the name of the property which is causing the validation error.  This leads to what I can do in line 8 above, which is just iterate through all of the validation errors and add their message to the ModelState using their Key property, which corresponds to the form id’s that we’re using to populate the model.  Just so you don’t think I’m lying, here’s what the form would look like:

<%= Html.ValidationSummary(
"Create was unsuccessful. 
Please correct the errors and try again.") %>
<% using (Html.BeginForm()) {%>
<fieldset>
<legend>Add New Product</legend>
<p>
<label for="Name">Name:</label>
<%= Html.TextBox("Name") %>
<%= Html.ValidationMessage("Name", "*") %>
</p>
<p>
<label for="Description">Description:</label>
<%= Html.TextBox("Description") %>
<%= Html.ValidationMessage("Description", "*") %>
</p>
<p>
<label for="Price">Price:</label>
<%= Html.TextBox("Price") %>
<%= Html.ValidationMessage("Price", "*") %>
</p>
<p>
<label for="Quantity">Quantity:</label>
<%= Html.TextBox("Quantity") %>
<%= Html.ValidationMessage("Quantity", "*") %>
</p>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
<% } %>



I Think We Can Do Just a Bit Better…



So, there you have it – easy validation using ASP.NET MVC Model Binders, MVC’s Validation components, and Enterprise Library’s Validation block.  The preceeding should work like a charm, but me being the perpetual perfectionist and idealist saw one more piece of duplication that I wanted to remove.  Namely, the foreach loop used to map the ValidationResults to the ModelState.  Using an extension method to extend the ValidationResults class, this duplication can easily be removed like so:

using System.Web.Mvc;
using Microsoft.Practices.EnterpriseLibrary.Validation;

public static class EntLibValidationExtensions
{
public static void CopyToModelState(this ValidationResults results, ModelStateDictionary modelState)
{
foreach (var result in results)
modelState.AddModelError(result.Key ?? "_FORM", result.Message);
}
}



Now the previous Action looks just a bit cleaner:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Product product)
{
var validationResult = product.Validate();
if (!validationResult.IsValid)
{
validationResult.CopyToModelState(this.ModelState);
return View(product);
}

productRepository.Add(product);
return View("Index");
}



And with that, I’m happy…  What do you think??

Tuesday, March 10, 2009

Come Learn Silverlight 2 From a Master!

Hey all - if you're in the Princeton, NJ area this coming Thursday (March 12th, 2009), be sure to stop by our monthly NJDOTNET User Group meeting because this month we will be hosting Jason Beres - international conference speaker, Microsoft MVP, and an author of the two Silverlight Programmers References from WROX Press!  Jason is an incredible speaker and I strongly encourage you to do everything you can to attend this meeting!  Here are the details:

What:  NJDOTNET March Meeting – Understanding RIA’s with Silverlight 2

When: THIS Thursday, March 10, 2009  6:15 PM – 8:30 PM

Where:  Infragistics Corporate HQ  (Click here for directions)

Who:
Jason Beres is the Director of Product Management for Infragistics, the world’s leading publisher of presentation layer tools.  Jason is one of the founders of Florida .NET User Groups, he is the founder of the Central New Jersey .NET User Group, he is a Visual Basic .NET MVP, and he is on the INETA Speakers Bureau.  Jason is the author of several books on .NET development, including the recently published Silverlight 2 Programmers Reference from Wrox Press.  Jason is a national and international conference speaker; he is a frequent columnist for several .NET publications, and keeps very active in the .NET community.

Abstract:
Understanding RIA’s with Silverlight 2
In this code-focused talk, we’ll look at the features in Silverlight 2 and how they can help you build better RIA (Rich Internet Application) experiences.  We’ll look at the Silverlight development experience, how to build a Silverlight application with the new Silverlight 3 features, and how this will help you build rich line-of-business experiences using data binding, animations and media.

Tuesday, February 17, 2009

Tag Mappings to the Rescue!

Our recent project at work lately (and the main reason for my previous two months of blog silence) has been upgrading and re-theming our installation of Community Server.  I’ve written a few posts in the past on the couple of modules and customizations I’ve done for our current site, and this upgrade is no different.  In fact, I’ve had to do more!  The most recent one I did just a few minutes ago just happens to be not Community Server-specific at all, but a regular ol’ ASP.NET trick, so I wanted to write about it first.  You’ll see more about the Community Server-specific customizations I’ve had to do following this post.

Community Server sites are really just the “Community Server Platform” (which encompasses a whole lotta stuff!), and a customizable theme on top of that platform.  Like any well-made site, CS themes are plain ol’ ASPX pages with a mixture of user and server controls.  This leaves us with themes that have got somewhere between a dozen and a million pages with the following mark-up:

<CSForum:BreadCrumb runat="server" Tag="Div" />

… but I don’t like what it’s outputting and I want to override some of its behavior.  Overriding the control’s behavior is easy enough, of course – you just extend the class and throw in an override here and there and you’re all good.  Now we’ve got our new control – Infragistics.CommunityServer.Controls.ForumsBreadCrumb – and the trick is getting this nice shiny control in place.  Your first thought might be that we’re up for a massive global search n’ replace, right?  Wrong!


I know I kinda ruined the surprise in the title of this post, but for those of you who skipped over that part, forget the global replace – it’s tag mappings to the rescue!  Tag mappings allow you to substitute (or map if you want to get technical) one control for another using a simple web.config change!  In our case, we’ll do this:


<pages>
<tagMapping>
<add
tagType="CommunityServer.Discussions.Controls.BreadCrumb"
mappedTagType="Infragistics.CommunityServer.Controls.ForumsBreadCrumb"/>
</tagMapping>
</pages>

It’s pretty straight-forward – you’re telling ASP.NET that everywhere you’ve used a tag in your markup (tagType) you want to use another type instead (mappedTagType).  This makes it really easy to override and/or extend the functionality of a control and use your custom version instead of the original, without changing any of your code


This tactic can really help you reduce the risk of such a major change, since - I don’t know about you - but my history with global replacements in markup pages have more often than not cost me more problems (and time spent fixing those problems) than if I had just manually made all the replacements to begin with.  Next time you’re tempted to do a global replace on a control, take a couple of seconds to think about whether or not this tactic will work for you.  It might end up saving you quite a bit of time!


And, as always, happy coding!

Friday, December 19, 2008

ASP.NET MVC Release: So close you can FEEL it!

I had a great time reading ScottGu's blog post today discussing all of the cool new features coming in the RC. Some of them (like the View page template not including a code-behind file) really got me excited, but I nearly freaked out when I got to the end and read this:

We'll be releasing the ASP.NET MVC Release Candidate in January. Our plan is to have that build be ASP.NET MVC V1 API and feature-complete and have zero known bugs. We'll give people a short period to upgrade to it, give it a good tire-kicking, and report any last minute issues they find. We'll then ship the official V1 release shortly after that (so not far off now).

ASP.NET MVC v1 is SOOO close! I really feel like this framework has come a long way in its relatively short development lifetime and with all of the recent candy that's been added in the past few releases, I can just tell that it will be a wonderful platform to develop on for years to come.

Microsoft... ScottGu (and the rest of the MVC team)... You ROCK. I can not wait to be working in this framework on a daily basis.

Tuesday, December 9, 2008

Princeton, NJ -- Community Events This Week

If you're in the Princeton, NJ area - or can somehow manage to get here - this week, boy do we have some events for you!  Infragistics has teamed up with our local .NET User Group (NJDOTNET) and our local Microsoft Developer Evangelists out of New York City to bring you the following awesome events:

  1. Thursday, December 11th, 1PM - 5PM:  MSDN Roadshow
    Presenters:  Peter Laudati and Bill Zack
    Session 1: Cloud Computing

    Hear about key problems that cloud computing is solving and how these services fit into the Microsoft cloud computing initiatives. Learn about the pillars of the platform, its service lifecycle, and see how they fit with both Microsoft and non-Microsoft technologies.

    Session 2: Silverlight 2 Application Development

    Now it’s time for you to get ready to build next generation rich Internet applications with Silverlight!  In this session, we’ll quickly review what the Silverlight 2 platform is, and then move into the bits and bytes.

    If you're interested, register using this link:

    http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032395688&culture=en-US

     

  2. Thursday, December 11th, 6:15-8:30 PM:  NJDOTNET User Group monthly meeting
    Topic:  The ASP.NET MVC Framework
    Presenter:  Jess Chadwick

    The Model-View-Controller (MVC) architectural pattern is one that many developers are familiar with which separates an application into three main components: the model, the view, and the controller. The ASP.NET MVC framework provides an alternative to the ASP.NET Web Forms pattern for creating MVC-based Web applications. It is a lightweight, highly testable framework that allows you to easily incorporate this pattern into your applications, helping to separate the different aspects  (input logic, business logic, and UI logic) into loosely-coupled and pluggable elements.

  3. Saturday, December 13th,  9:30 AM - 5:00 PM:  NJDOTNET ASP.NET MVC Firestarter
    Join us at the Infragistics HQ to participate in an all-day, deep-dive into one of Microsoft's latest (and greatest!) technologies: ASP.NET MVC.

    At the ASP.NET MVC Firestarter, we’ll give you a quick tour of the framework, then peel back the layers and dive deeper into how it works.   As part of that, we’ll spend time discussing the design and development practices that lead to the creation of the MVC framework.  By the time you leave, you’ll have enough knowledge to get fired up and start building web applications with it.

    Detailed Agenda:

    • ASP.NET MVC Introduction
      • The MVC Design Pattern
      • Hello World Demo – Walking through routing, controllers, and views
    • Framework Fundamentals & Practices
      • C# 3.0 Primer
      • Anonymous Classes
      • Lambda Expressions
      • Extention Methods
      • LINQ
      • Dependency Injection
    • Routing & Controllers
      • Routing 101
      • Controllers – Actions & ActionResults
      • Controllers & TDD
    • Rendering Markup
      • Views (using WebForm tools)
      • Extensibility with View Engines
    • Working with Data
      • Creating & Submitting Forms
      • UI Helpers
    • Building Rich Web Interfaces
      • Applying AJAX Helper extensions
      • Walkthrough of ASP.NET AJAX + MVC Extensions
      • Enhancing MVC with jQuery
      • Action Filters & applying to AJAX

    If you are interested in attending this session, please register using the following link:
    http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032397108&culture=en-US

 

I look forward to seeing you at these great events!

Sunday, November 16, 2008

Easier Automated Database Testing with SQL Express

Scenario

I've got a project in which I actually have full create scripts for my database such that I can build a whole new instance from the bottom up.  I've also got some automated unit/integration tests that I want to run against this database, complete with a bunch of scripts that can build some test data for me (unrealistic, I know...  but bear with me :).  Also, I really don't want to have to worry about configuring connection strings just for my tests - I just want some database available to me when I need it that I can wail on with requests and gets cleaned up for me when I'm done.  Finally, I want to keep my tests as isolated as possible, which to me means a file-based SQL Express database; that way, I can attach, detach, and delete as much as I want with as little exposure and impact to the rest of my build system as possible.

Solution

My solution to the above scenario I found myself in was to create a helper class called TestDatabase whose job is to give me a database when I need one, provide me with a clean version of my test data before each test I run, and clean up after me when I'm done.  To this end, I started searching for how to create a file-based SQL Express database using code, and came up with Louis DeJardin's great blog post that walked me right though it.  After I had that, it was a simple matter of whipping up the class, shown below (Note: this is only a partial listing.  You can get the full listing from my code repository):

TestDatabase.cs (partial listing)
public class TestDatabase : IDisposable
{
private readonly string connectionString;
private readonly string databaseFilename;

public string ConnectionString { get { return connectionString; } }
public string Schema { get; set; }
public string TestDataScript { get; set; }

public TestDatabase(string databaseFilename, string schema, string testData)
{
this.databaseFilename = databaseFilename;
connectionString = string.Format(
@"Server=.\SQLEXPRESS; Integrated Security=true;AttachDbFileName={0};",
Path.GetFullPath(databaseFilename));
Schema = schema;
TestDataScript = testData;
}

public void Dispose()
{
DeleteDatabaseFiles();
}

public void RecreateTestData()
{
EnsureDatabaseCreated();

if (!string.IsNullOrEmpty(TestDataScript))
ExecuteQuery(TestDataScript);
}

// Create a new file-based SQLEXPRESS database
// (Credit to Louis DeJardin - thanks! http://snurl.com/5nbrc)
protected void CreateDatabase()
{
var databaseName = Path.GetFileNameWithoutExtension(databaseFilename);

using (var connection = new SqlConnection(
"Data Source=.\\sqlexpress;Initial Catalog=tempdb;" +
"Integrated Security=true;User Instance=True;"))
{
connection.Open();
using (var command = connection.CreateCommand())
{
command.CommandText =
"CREATE DATABASE " + databaseName +
" ON PRIMARY (NAME=" + databaseName +
", FILENAME='" + databaseFilename + "')";
command.ExecuteNonQuery();

command.CommandText =
"EXEC sp_detach_db '" + databaseName + "', 'true'";
command.ExecuteNonQuery();
}
}

// After we've created the database, initialize it with any
// schema we've been given
if (!string.IsNullOrEmpty(Schema))
ExecuteQuery(Schema);
}
}


Let's analyze the things we've got going on here:


  1. First, we've got the CreateDatabase() method (lines 34-61) - basically ripped right from Louis's blog post linked above - which does the magic of creating a file-based SQL Express database.  It all boils down to a "CREATE DATABASE" and "EXEC sp_detach_db" call on the local SQL Express instance's tempdb database, which everyone has access to.  Then when that's all done, I execute the schema script that the tester passed in to build the database schema and finish the initial setup.
  2. Now that the database has been created and initialized with its schema, we can run some tests against it!  Problem is, at this point it's just an empty database...  Fortunately for us, we've got the RecreateTestData() method, which just executes the TestDataScript against the current database, allowing us to easily populate whatever test data we want!  This script should include everything it needs to clean out the database and rebuild it from scratch with a new set of clean data.
  3. Built-in connection string management.  As you can see, our constructor takes in a database filename, builds a connection string out of it, and then exposes that connection string to our testers via a read-only property.  That is one less connection string that our test project has to worry about managing in its app.config (or whatever), which is pretty nice and clean, IMHO!
  4. Finally, our big finale:  cleaning up after ourselves!  You can see that TestDatabase implements IDisposable, allowing us to create a Dispose() method which cleans up after everything we've done - namely, deleting the database files we've created along the way.  This means that after everything is said and done, we've left not one footprint of our presence on the build system.

Now, after we've got our TestDatabase class available, our unit tests become as easy as this:


public void SomeCoolDatabaseDrivenServiceTest()
{
var mySchema = System.IO.File.ReadAllText("mySchema.sql");
var testData = System.IO.File.ReadAllText("testData.sql");
using (var db = new TestDatabase("TestDatabase.mdf", mySchema, testData))
{
db.Initialize();
var service = new MyService(db.ConnectionString);
service.DoSomething();
}
}

Of course, individual tests can have even less code if you manage the test database outside of the test by using your test framework's setup and teardown methods.  For example, if I had a whole slew of tests against the same database (which is usually always the case), the test class would start out like this:


TestDatabase database;

public void ClassInitialize()
{
var mySchema = System.IO.File.ReadAllText("mySchema.sql");
var testData = System.IO.File.ReadAllText("testData.sql");
database = new TestDatabase("TestDatabase.mdf", mySchema, testData);
database.Initialize(true);
}

public void TestInitialize()
{
// Rebuild the test data from scratch before EVERY test
database.RecreateTestData();
}

public void ClassCleanup()
{
database.Dispose();
}

Now that we have all of that setup and teardown logic out of the way, we can focus on what we're actually testing, so then that test I showed you before becomes a simple one-liner (as it would have been if we were just passing in a connection string from a configuration file):


public void SomeCoolDatabaseDrivenServiceTest()
{
// No TestDatabase setup - just use its connection string!
var service = new MyService(database.ConnectionString);
service.DoSomething();
}

What's cool about this is that not only do we not have to worry about where to get our connection string from, our entire suite of test data is also being rebuilt for us before every test is run!

Try It Out For Yourself!


If you like what you've seen in this post and want to try it out for yourself, you can grab the full source file (complete with in-line comments and unit tests) from my repository: TestDatabase.cs.  Just drop it in your project and start using it!
Note: The full source file has unit tests included. If you don't want them, you can simply delete them without affecting the main class.


As always, I'd love to hear your comments and feedback on all this.  If you've found this useful or - better yet - if you have a better way of doing it, please let me know!

Monday, October 27, 2008

Live from PDC: Getting settled in and thoughts on the Keynote

Greetings from PDC!

After a long and uncomfortable (for those who don't know me - 6'3", 220lbs...) flight, I'm finally here in beautiful and smoggy Los Angeles, ready for some PDC action!  First up - this morning's keynote in which Ray Ozzie announced Windows Azure, their new offering.  Sounds much like Amazon's service offerings (EC2, S3, etc)... only .NET and a whole slew of other MS offerings.  Sounds pretty darn cool, if you ask me.  So far, I haven't really been interested in utilizing Amazon's services, mostly due to cost, and I wonder how Azure will compare.  Ozzie says their CTP will be free due to changes that may possibly break anything and everything that you make with it at this point (my words, not his), and says that the final pricing will be "competitive with the market" (dunno if that's an exact quote or not, but it's about right).  One has to ask - what's "the market"?  As far as I can tell, that means Amazon's services and - as I just got done saying - their pricing was a deal-breaker for me.  Along these same lines, I noticed that one of the bullet points said "hobbyist-friendly" - with any luck that is referring to their pricing structure.

I also found it interesting that they referred to "new patterns and best practices such as loosely-coupled services and applications" numerous times...  It really is news to me that loosely-coupled designs are "new patterns and best practices"!   But, I'm not complaining - if developers are now more or less forced to use loosely coupled architectures to take the most advantage of cloud services, that's a good thing, right?

My next session (A Lap Around Windows Azure) is starting, so I should wrap this one up...  but, more to come for sure.

Wednesday, October 8, 2008

Wow - Thanks, Microsoft!

It's taken me quite a few days to get around to writing this post (been busy preparing and delivering a new ASP.NET MVC presentation at the Richmond Code Camp last Saturday), but I received a great email last Wednesday welcoming me to a great community of Microsoft professionals, and beginning with this header:

I'm now a Microsoft MVP in ASP.NET!  Needless to say, as soon as I found out, I got crazy excited and began thinking of everyone who was so helpful in achieving this great award. 

The first two guys I needed to thank were Aaron Marisi and Todd Snyder.   These two have been - and continue to be - crucial in helping me run the NJDOTNET User Group.  With their help (and it was only possible with their help!) we have been able to expand this monthly meeting to a meeting every week, providing exponentially more value to the members of the group.  I am going to make it my mission from here on out to make sure these two guys get all the credit they deserve!

In a separate class altogether are Ambrose Little and Jason Beres.  It is these two guys that had the greatest impact on my professional and community life because it was the leadership, knowledge, and obvious passion that these two MVPs (and I mean that in every sense of the acronym) exhibit on a daily basis that inspired me to become so involved with the development community in the first place.  Were it not for them, I probably would still be sitting in the back of the monthly user group meetings, barely saying a word.  But, after working with them for only a short time, their selfless guidance and inspirational example were too much to ignore and I just had to join in and attempt to contribute even half as much as they do.  In fact, I attribute so much of my recent success to them that if I could (and if they didn't already have one!) I would give my award directly to them.

I can't even imagine how much more vibrant and exciting our community would be if there were more Aarons, Ambroses, Jasons, and Todds out there pushing things along.  I eternally grateful to be able to work with all of them and even call them my friends.

So, thank you everyone for all of your support and I am really looking forward to all of the great community participation in the coming year!

Wednesday, September 10, 2008

S-E-Ooooh, That's How You Do It!

My boss, Kevin, and I headed out to Seattle last month (coincidentally during the time that some of our Infragistics buddies were heading up the speaker list at DevScovery) to attend an expert-level SEO seminar given by the bright folks over at SEOmoz.  And, boy was it enlightening!

Now, before I go any further, I'm going to have to state right up front that (until late last month) I have been wandering through my professional web career knowing only a bare minimum about SEO.  I thought I understood basic concepts like linking and keyword placement - the more times you link to a page and repeat a word, the higher your search rank, right?  Unsurprisingly, it turns out to be a bit more involved that that. :)

There's no way I'm going to duplicate in a blog post or even a series of blog posts what I learned at that awesome seminar - if you're truly that interested, I would suggest signing up for the training or at the very least checking out the articles on SEOmoz.  However, I wanted to 'jot down' a few of my largest takeaways, because they really made me reevaluate my view on the way SEO works.  Since I have a knack for oversimplifying things (verging on naivety), I figured a bulleted list would do just the trick.  So, below you'll find my ridiculously simplified...

List of Things You Probably Already Knew About SEO But Didn't Realize How Important They Were (or at least I didn't...):

  1. Backlinks.  I'm sure it comes as no surprise that having other sites (especially the big/important ones) link to yours is beneficial, but I'd have to say the most unexpected thing I took away from this seminar was just how important they are!  From what I understand, these account for the vast majority of your PageRank-ings - I'm talking well over half.  That means you need to beg, borrow, cheat, and steal (wait, no... not those last two) to get everyone and their dog to link back to you (assuming their dog's site has a lot of traffic, of course!).  As always, the better their PageRank, the better your Link Juice.

  2. Oh, yeah - Link Juice and nofollow!   To be honest, I'd never heard the term 'link juice' before.  But after hearing it explained, it was just so incredibly appropriate I really became endeared with it.  Put simply, think of the traffic to any one of your pages as water flowing into a pipe.  You start out with 10 gallons of water coming into one pipe (this landing page) from which it is split up and diverted to various other pipes (pages you're linking to from the landing page).  Each of these splits divides and cuts down the volume of the initial 10 gal., such that if you have, say, 10 links on your page each of them gets 1 gal. of that initial 10.  Now, if you play that concept all the way through each page, constantly splitting up the water on every page, you can imagine how quickly that 10 gallon deluge can become just a trickle...  Obviously, we'd like to see some pages on our site get more traffic than others, so how do we  keep our existing links so people can still navigate our site, yet "divert the water" to the pages that we think are the most important?  Fortunately, the answer is pretty simple - the "rel='nofollow'" tag!  Placing this tag on any of your links basically tells search engines "this page really isn't important to me and I really don't want to waste my influence on it."  It's kind of like disavowing all knowledge of your pages... even if it quite obvious that they're worth something to you (since they still exist, after all).

  3. Then there's plain ol' good, properly-formatted, and relevant content...  Really, from what I could tell, those first two bullets are the major players in terms of tips & tricks.  The search engines are getting better at filtering out spammers every day through various techniques, so your ultimate defense is to create interesting content, and make use of standard best practices like putting your important keywords in your <title> and <hx> tags, concentrating on creating relevant content, and trying to keep your markup light and semantically correct.  Simple... right?  "Easier said than done" is more like it!

I had intended from the start for this to be a quick overview of what I took away from my recent training and nowhere near a "deep dive" into SEO.  But, to help you on your way, I've collected a few resources that might help you learn some more if I've happened to pique your interest... which I certainly hope I have!

Additional Resources:

Hope this all helps!  Oh, and please leave me a comment and let me know if it does - I'd love to hear about it!