WTF Next?

Dev ramblings from a master of nothing.

  Home  |   Contact  |   Syndication    |   Login
  136 Posts | 0 Stories | 109 Comments | 0 Trackbacks


INETA Community Speakers Program WTFNext's hosting!

View Stacy Vicknair's profile on LinkedIn

Tag Cloud


Community Links

User Groups

Wednesday, May 29, 2013 #

As a follow up to the post I made in preparation of the 70-480 exam, I’d like to continue the series now with a look at the 70-486. Just like last time, we’ll look at a list of resources based on the individual exam criteria!


General Resources

Microsoft Hands On Tutorial:

Building Web Apps with ASP.NET Jump Start:

Pluralsight Training (not free, but an excellent training resource! There is a trial available.):

The Official ASP.NET MVC 4 Page:

The source code for the ASP.NET Web Stack:

Microsoft Official Training Course:


Test Breakdown

Design the Application Architecture

  • Plan the application layers.
    • This objective may include but is not limited to: plan data access; plan for separation of concerns; appropriate use of models, views, and controllers; choose between client-side and server side processing; design for scalability

  • Design a distributed application.
    • This objective may include but is not limited to: design a hybrid application (on premise vs. off premise, including Windows Azure); plan for session management in a distributed environment; plan web farms

  • Design and implement the Windows Azure role life cycle.
    • This objective may include but is not limited to: identify and implement Start, Run, and Stop events;identify startup tasks (IIS configuration [app pool], registry configuration, third-party tools)

  • Configure state management.
    • This objective may include but is not limited to: choose a state management mechanism (in-process and out of process state management, ViewState); plan for scalability; use cookies or local storage to maintain state; apply configuration settings in web.config file; implement sessionless state (for example, QueryString)

  • Design a caching strategy.
    • This objective may include but is not limited to: implement page output caching (performance oriented); implement data caching; implement HTTP caching

  • Design and implement a Web Socket strategy.
    • This objective may include but is not limited to: read and write string and binary data asynchronously (long-running data transfers); choose a connection loss strategy; decide a strategy for when to use Web Sockets

  • Design HTTP modules and handlers.
    • This objective may include but is not limited to: implement synchronous and asynchronous modules and handlers; choose between modules and handlers in IIS


Design the User Experience

  • Apply the user interface design for a web application.
    • This objective may include but is not limited to: create and apply styles by using CSS; structure and lay out the user interface by using HTML; implement dynamic page content based on a design

  • Design and implement UI behavior.
    • This objective may include but is not limited to: implement client validation; use JavaScript and the DOM to control application behavior; extend objects by using prototypal inheritance; use AJAX to make partial page updates; implement the UI by using JQuery

  • Compose the UI layout of an application.
    • This objective may include but is not limited to: implement partials for reuse in different areas of the application; design and implement pages by using Razor templates (Razor view engine); design layouts to provide visual structure; implement master/application pages

  • Enhance application behavior and style based on browser feature detection.
    • This objective may include but is not limited to: detect browser features and capabilities; create a web application that runs across multiple browsers and mobile devices; enhance application behavior and style by using vendor-specific extensions, for example, CSS

  • Plan an adaptive UI layout.
    • This objective may include but is not limited to: plan for running applications in browsers on multiple devices (screen resolution, CSS, HTML); plan for mobile web applications


Develop the User Experience

  • Plan for search engine optimization and accessibility.
    • This objective may include but is not limited to: use analytical tools to parse HTML; view and evaluate conceptual structure by using plugs-in for browsers; write semantic markup (HTML5 and ARIA) for accessibility, for example, screen readers

  • Plan and implement globalization and localization.
    • This objective may include but is not limited to: plan a localization strategy; create and apply resources to UI including JavaScript resources; set cultures; create satellite resource assemblies

  • Design and implement MVC controllers and actions.
    • This objective may include but is not limited to: apply authorization attributes and global filters; implement action behaviors; implement action results; implement model binding

  • Design and implement routes.
    • This objective may include but is not limited to: define a route to handle a URL pattern; apply route constraints; ignore URL patterns; add custom route parameters; define areas

  • Control application behavior by using MVC extensibility points.
    • This objective may include but is not limited to: implement MVC filters and controller factories; control application behavior by using action results, viewengines, model binders, and route handlers

  • Reduce network bandwidth.
    • This objective may include but is not limited to: bundle and minify scripts (CSS and JavaScript); compress and decompress data (using gzip/deflate; storage); plan a content delivery network (CDN) strategy, for example, Windows Azure CDN


Troubleshoot and Debug Web Applications

  • Prevent and troubleshoot runtime issues.
    • This objective may include but is not limited to: troubleshoot performance, security, and errors;implement tracing, logging (including using attributes for logging), and debugging (including IntelliTrace); enforce conditions by using code contracts; enable and configure health monitoring (including Performance Monitor)

  • Design an exception handling strategy.
    • This objective may include but is not limited to: handle exceptions across multiple layers; display custom error pages using global.asax or creating your own HTTPHandler or set web.config attributes; handle first chance exceptions

  • Test a web application.
    • This objective may include but is not limited to: create and run unit tests, for example, use the Assert class, create mocks; create and run web tests

  • Debug a Windows Azure application.
    • This objective may include but is not limited to: collect diagnostic information by using Windows Azure Diagnostics API Implement on demand vs. scheduled; choose log types, for example, event logs, performance counters, and crash dumps; debug a Windows Azure application by using IntelliTrace and Remote Desktop Protocol (RDP)


Design and Implement Security

  • Configure authentication.
    • This objective may include but is not limited to: authenticate users; enforce authentication settings; choose between Windows, Forms, and custom authentication; manage user session by using cookies; configure membership providers; create custom membership providers

  • Configure and apply authorization.
    • This objective may include but is not limited to: create roles; authorize roles by using configuration; authorize roles programmatically ; create custom role providers; implement WCF service authorization

  • Design and implement claims-based authentication across federated identity stores.
    • This objective may include but is not limited to: implement federated authentication by using Windows Azure Access Control Service; create a custom security token by using Windows Identity Foundation; handle token formats (for example, oAuth, OpenID, LiveID, and Facebook) for SAML and SWT tokens

  • Manage data integrity.
    • This objective may include but is not limited to: apply encryption to application data; apply encryption to the configuration sections of an application; sign application data to prevent tampering

  • Implement a secure site with ASP.NET.
    • This objective may include but is not limited to: secure communication by applying SSL certificates; salt and hash passwords for storage; use HTML encoding to prevent cross-site scripting attacks (ANTI-XSS Library); implement deferred validation and handle unvalidated requests, for example, form, querystring, and URL; prevent SQL injection attacks by parameterizing queries; prevent cross-site request forgeries (XSRF)

Sunday, December 30, 2012 #

If you’re familiar with NetSqlAzMan or CanCan, you know that checking permissions based on a user’s activities is easier to manage and more flexible that working with the roles a user is in. Whatever method you take to add activity based authorization, if you are working in MVC you will run into the issue that AuthorizeAttribute only cares about Users and Roles. The good news is that you can inherit from AuthorizeAttribute and easily adapt it to account for activity-based authorization.


If you didn’t know already, you can browse the code for ASP.NET on CodePlex. Here’s the code for AuthorizeAttribute:

   1: // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
   3: using System.Diagnostics.CodeAnalysis;
   4: using System.Linq;
   5: using System.Security.Principal;
   6: using System.Web.Mvc.Properties;
   8: namespace System.Web.Mvc
   9: {
  10:     [SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes", Justification = "Unsealed so that subclassed types can set properties in the default constructor or override our behavior.")]
  11:     [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
  12:     public class AuthorizeAttribute : FilterAttribute, IAuthorizationFilter
  13:     {
  14:         private readonly object _typeId = new object();
  16:         private string _roles;
  17:         private string[] _rolesSplit = new string[0];
  18:         private string _users;
  19:         private string[] _usersSplit = new string[0];
  21:         public string Roles
  22:         {
  23:             get { return _roles ?? String.Empty; }
  24:             set
  25:             {
  26:                 _roles = value;
  27:                 _rolesSplit = SplitString(value);
  28:             }
  29:         }
  31:         public override object TypeId
  32:         {
  33:             get { return _typeId; }
  34:         }
  36:         public string Users
  37:         {
  38:             get { return _users ?? String.Empty; }
  39:             set
  40:             {
  41:                 _users = value;
  42:                 _usersSplit = SplitString(value);
  43:             }
  44:         }
  46:         // This method must be thread-safe since it is called by the thread-safe OnCacheAuthorization() method.
  47:         protected virtual bool AuthorizeCore(HttpContextBase httpContext)
  48:         {
  49:             if (httpContext == null)
  50:             {
  51:                 throw new ArgumentNullException("httpContext");
  52:             }
  54:             IPrincipal user = httpContext.User;
  55:             if (!user.Identity.IsAuthenticated)
  56:             {
  57:                 return false;
  58:             }
  60:             if (_usersSplit.Length > 0 && !_usersSplit.Contains(user.Identity.Name, StringComparer.OrdinalIgnoreCase))
  61:             {
  62:                 return false;
  63:             }
  65:             if (_rolesSplit.Length > 0 && !_rolesSplit.Any(user.IsInRole))
  66:             {
  67:                 return false;
  68:             }
  70:             return true;
  71:         }
  73:         private void CacheValidateHandler(HttpContext context, object data, ref HttpValidationStatus validationStatus)
  74:         {
  75:             validationStatus = OnCacheAuthorization(new HttpContextWrapper(context));
  76:         }
  78:         public virtual void OnAuthorization(AuthorizationContext filterContext)
  79:         {
  80:             if (filterContext == null)
  81:             {
  82:                 throw new ArgumentNullException("filterContext");
  83:             }
  85:             if (OutputCacheAttribute.IsChildActionCacheActive(filterContext))
  86:             {
  87:                 // If a child action cache block is active, we need to fail immediately, even if authorization
  88:                 // would have succeeded. The reason is that there's no way to hook a callback to rerun
  89:                 // authorization before the fragment is served from the cache, so we can't guarantee that this
  90:                 // filter will be re-run on subsequent requests.
  91:                 throw new InvalidOperationException(MvcResources.AuthorizeAttribute_CannotUseWithinChildActionCache);
  92:             }
  94:             bool skipAuthorization = filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true)
  95:                                      || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true);
  97:             if (skipAuthorization)
  98:             {
  99:                 return;
 100:             }
 102:             if (AuthorizeCore(filterContext.HttpContext))
 103:             {
 104:                 // ** IMPORTANT **
 105:                 // Since we're performing authorization at the action level, the authorization code runs
 106:                 // after the output caching module. In the worst case this could allow an authorized user
 107:                 // to cause the page to be cached, then an unauthorized user would later be served the
 108:                 // cached page. We work around this by telling proxies not to cache the sensitive page,
 109:                 // then we hook our custom authorization code into the caching mechanism so that we have
 110:                 // the final say on whether a page should be served from the cache.
 112:                 HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache;
 113:                 cachePolicy.SetProxyMaxAge(new TimeSpan(0));
 114:                 cachePolicy.AddValidationCallback(CacheValidateHandler, null /* data */);
 115:             }
 116:             else
 117:             {
 118:                 HandleUnauthorizedRequest(filterContext);
 119:             }
 120:         }
 122:         protected virtual void HandleUnauthorizedRequest(AuthorizationContext filterContext)
 123:         {
 124:             // Returns HTTP 401 - see comment in HttpUnauthorizedResult.cs.
 125:             filterContext.Result = new HttpUnauthorizedResult();
 126:         }
 128:         // This method must be thread-safe since it is called by the caching module.
 129:         protected virtual HttpValidationStatus OnCacheAuthorization(HttpContextBase httpContext)
 130:         {
 131:             if (httpContext == null)
 132:             {
 133:                 throw new ArgumentNullException("httpContext");
 134:             }
 136:             bool isAuthorized = AuthorizeCore(httpContext);
 137:             return (isAuthorized) ? HttpValidationStatus.Valid : HttpValidationStatus.IgnoreThisRequest;
 138:         }
 140:         internal static string[] SplitString(string original)
 141:         {
 142:             if (String.IsNullOrEmpty(original))
 143:             {
 144:                 return new string[0];
 145:             }
 147:             var split = from piece in original.Split(',')
 148:                         let trimmed = piece.Trim()
 149:                         where !String.IsNullOrEmpty(trimmed)
 150:                         select trimmed;
 151:             return split.ToArray();
 152:         }
 153:     }
 154: }


The method that manages whether or not a user is authorized is the AuthorizeCore method:

   1: protected virtual bool AuthorizeCore(HttpContextBase httpContext)
   2: {
   3:     if (httpContext == null)
   4:     {
   5:         throw new ArgumentNullException("httpContext");
   6:     }
   8:     IPrincipal user = httpContext.User;
   9:     if (!user.Identity.IsAuthenticated)
  10:     {
  11:         return false;
  12:     }
  14:     if (_usersSplit.Length > 0 && !_usersSplit.Contains(user.Identity.Name, StringComparer.OrdinalIgnoreCase))
  15:     {
  16:         return false;
  17:     }
  19:     if (_rolesSplit.Length > 0 && !_rolesSplit.Any(user.IsInRole))
  20:     {
  21:         return false;
  22:     }
  24:     return true;
  25: }


Going through the code:

  1. If the httpContext is null, error out.
  2. If the user isn’t authenticated, return false.
  3. If the required users list isn’t empty and the user isn’t in that list, return false.
  4. If the required roles list isn’t empty and the user isn’t in a role in that list, return false.
  5. If we made it this far, the user is good to go.

To add activities, we simply need an additional step:

  • If the activity list isn’t empty and the user doesn’t have permission for that activity, return false.

To do this, we can simply subclass AuthorizeAttribute and override the AuthorizeCore method:

In VB:

   1: Protected Overrides Function AuthorizeCore(httpContext As HttpContextBase) As Boolean
   2:     If httpContext Is Nothing Then
   3:         Throw New ArgumentNullException("httpContext")
   4:     End If
   6:     Dim user As IPrincipal = httpContext.User
   7:     If Not user.Identity.IsAuthenticated Then
   8:         Return False
   9:     End If
  11:     If Actions.Length > 0 Then
  12:         Dim component = New SiteActionsComponent()
  13:         Dim roles = component.GetRolesForSiteActions(Actions)
  14:         If Not roles.Any(user.IsInRole) Then
  15:             Return False
  16:         End If
  17:     End If
  19:     Return MyBase.AuthorizeCore(httpContext)
  20: End Function

In C#:

   1: protected override bool AuthorizeCore(HttpContextBase httpContext)
   2: {
   3:     if (httpContext == null)
   4:     {
   5:         throw new ArgumentNullException("httpContext");
   6:     }
   8:     IPrincipal user = httpContext.User;
   9:     if (!user.Identity.IsAuthenticated)
  10:     {
  11:         return false;
  12:     }
  14:     if (Actions.Length > 0)
  15:     {
  16:         var component = new SiteActionsComponent();
  17:         var roles = component.GetRolesForSiteActions(Actions);
  18:         if(!roles.Any(user.IsInRole))
  19:         {
  20:             return false;
  21:         }
  22:     }
  24:     return base.AuthorizeCore(httpContext);
  25: }


This overridden method gives us the following:

  1. if the httpContext is null, error out.
  2. If the activity list isn’t empty and the user doesn’t have permission for that activity, return false.
  3. If we made it this far, check the base method (the steps above).

In the example above the SiteActionsComponent is a business component that provides the lists of roles that the user could be in to satisfy the need for the listed actions. The example comes from a project that uses activities in combination with WebSecurity, and I wanted to avoid additional complication such as custom security providers / principals. You will need a similar provider in order to use this method.


Thursday, November 8, 2012 #

If you have an MSDN account and, like me, systematically claim keys just as well as you systematically forget which keys you’ve used in which test environments! Well, in a meager attempt to help myself track my keys I created an importer for KeePass 2 that takes in the XML document that you can export from MSDN and TechNet. The source is available at

GitHub has chosen to deprecate the downloads section for files. Right now, to download the dll you can go to but I will look into options for hosting these files somewhere else in the future.

How do I get my KeysExport.xml from MSDN or TechNet?

Easy! First, in MSDN, go to your product keys.


From there, at the top right select Export to XML.


This will let you download an XML file full of your Microsoft Keys.


How do I import it into KeePass 2?

The instructions are simple and available in the GitHub, so I won’t repeat them. Here is a screenshot of what the imported result looks like:



As you can see, the import process creates a group called Microsoft Product Keys and creates a subgroup for each product. The individual entries each represent an individual key, stored in the password field. The importer decides if a key is new based on the key stored in the password, so you can edit the notes or title for the individual entries however you please without worrying about them being overwritten or duplicated if you re-import an updated KeysExport.xml from MSDN! This lets you keep track of where those pesky keys are in use and have the keys available anywhere you can access your KeePass database!


Technorati Tags: ,,,

Monday, October 8, 2012 #

Here’s a list of sources of information for the different elements that comprise the 70-480 exam:

General Resources

EDIT: This is the end all source for video coverage of the exam, including information on the followup exam for building Windows Store apps with HTML5, CSS and Javascript. Go to the site to get a free voucher code to take the exam while supplies last! (As pointed out in David Pallmann’s blog some of this content is unverified, but it is a decent source of information. For more about when it isn’t decent, see ) (A guy who did a lot of what I did already, sadly I found this halfway through finishing my resources list. This list is expertly put together so I would recommend checking it out.) (Yes, this isn’t free, but if you look at the course listing there is an entire section on HTML5, CSS3 and Javascript. You can always try the trial!)

(update): (This sample set includes a lot of information about both the 70-480 as well as 70-481)

Some of the links I put below will overlap with the other resources above, but I tried to find explanations that looked beneficial to me on links outside those already mentioned.


Test Breakdown

Implement and Manipulate Document Structures and Objects (24%)

Create the document structure.

o This objective may include but is not limited to: structure the UI by using semantic markup, including for search engines and screen readers (Section, Article, Nav, Header, Footer, and Aside); create a layout container in HTML


Write code that interacts with UI controls.

o This objective may include but is not limited to: programmatically add and modify HTML elements; implement media controls; implement HTML5 canvas and SVG graphics


Apply styling to HTML elements programmatically.

o This objective may include but is not limited to: change the location of an element; apply a transform; show and hide elements


Implement HTML5 APIs.

o This objective may include but is not limited to: implement storage APIs, AppCache API, and Geolocation API


Establish the scope of objects and variables.

o This objective may include but is not limited to: define the lifetime of variables; keep objects out of the global namespace; use the “this” keyword to reference an object that fired an event; scope variables locally and globally


Create and implement objects and methods.

o This objective may include but is not limited to: implement native objects; create custom objects and custom properties for native objects using prototypes and functions; inherit from an object; implement native methods and create custom methods



Implement Program Flow (25%)

Implement program flow.

o This objective may include but is not limited to: iterate across collections and array items; manage program decisions by using switch statements, if/then, and operators; evaluate expressions


Raise and handle an event.

o This objective may include but is not limited to: handle common events exposed by DOM (OnBlur, OnFocus, OnClick); declare and handle bubbled events; handle an event by using an anonymous function


Implement exception handling.

o This objective may include but is not limited to: set and respond to error codes; throw an exception; request for null checks; implement try-catch-finally blocks


Implement a callback.

o This objective may include but is not limited to: receive messages from the HTML5 WebSocket API; use jQuery to make an AJAX call; wire up an event; implement a callback by using anonymous functions; handle the “this” pointer


Create a web worker process.

o This objective may include but is not limited to: start and stop a web worker; pass data to a web worker; configure timeouts and intervals on the web worker; register an event listener for the web worker; limitations of a web worker


Access and Secure Data (26%)

Validate user input by using HTML5 elements.

o This objective may include but is not limited to: choose the appropriate controls based on requirements; implement HTML input types and content attributes (for example, required) to collect user input


Validate user input by using JavaScript.

o This objective may include but is not limited to: evaluate a regular expression to validate the input format; validate that you are getting the right kind of data type by using built-in functions; prevent code injection


Consume data.

o This objective may include but is not limited to: consume JSON and XML data; retrieve data by using web services; load data or get data from other sources by using XMLHTTPRequest


Serialize, deserialize, and transmit data.

o This objective may include but is not limited to: binary data; text data (JSON, XML); implement the jQuery serialize method; Form.Submit; parse data; send data by using XMLHTTPRequest; sanitize input by using URI/form encoding



Use CSS3 in Applications (25%)

Style HTML text properties.

o This objective may include but is not limited to: apply styles to text appearance (color, bold, italics); apply styles to text font (WOFF and @font-face, size); apply styles to text alignment, spacing, and indentation; apply styles to text hyphenation; apply styles for a text drop shadow


Style HTML box properties.

o This objective may include but is not limited to: apply styles to alter appearance attributes (size, border and rounding border corners, outline, padding, margin); apply styles to alter graphic effects (transparency, opacity, background image, gradients, shadow, clipping); apply styles to establish and change an element’s position (static, relative, absolute, fixed)


Create a flexible content layout.

o This objective may include but is not limited to: implement a layout using a flexible box model; implement a layout using multi-column; implement a layout using position floating and exclusions; implement a layout using grid alignment; implement a layout using regions, grouping, and nesting


Create an animated and adaptive UI.

o This objective may include but is not limited to: animate objects by applying CSS transitions; apply 3-D and 2-D transformations; adjust UI based on media queries (device adaptations for output formats, displays, and representations); hide or disable controls


Find elements by using CSS selectors and jQuery.

o This objective may include but is not limited to: choose the correct selector to reference an element; define element, style, and attribute selectors; find elements by using pseudo-elements and pseudo-classes (for example, :before, :first-line, :first-letter, :target, :lang, :checked, :first-child)


Structure a CSS file by using CSS selectors.

o This objective may include but is not limited to: reference elements correctly; implement inheritance; override inheritance by using !important; style an element based on pseudo-elements and pseudo-classes (for example, :before, :first-line, :first-letter, :target, :lang, :checked, :first-child)


Wednesday, June 27, 2012 #

Liskov Substitution Principle (LSP) is a principle of object oriented programming that many might be familiar with from the SOLID principles mnemonic from Uncle Bob Martin. The principle highlights the relationship between a type and its subtypes, and, according to Wikipedia, is defined by Barbara Liskov and Jeanette Wing as the following principle:


Let q(x) be a property provable about objects x of type T. Then q(y) should be provable for objects y of type S where S is a subtype of T.


Rectangles gonna rectangulate

The iconic example of this principle is illustrated with the relationship between a rectangle and a square. Let’s say we have a class named Rectangle that had a property to set width and a property to set its height.

   1: Public Class Rectangle
   2:     Overridable Property Width As Integer
   3:     Overridable Property Height As Integer
   4: End Class


We all at some point here that inheritance mocks an “IS A” relationship, and by gosh we all know square IS A rectangle. So let’s make a square class that inherits from rectangle. However, squares do maintain the same length on every side, so let’s override and add that behavior.

   1: Public Class Square
   2:     Inherits Rectangle
   4:     Private _sideLength As Integer
   6:     Public Overrides Property Width As Integer
   7:         Get
   8:             Return _sideLength
   9:         End Get
  10:         Set(value As Integer)
  11:             _sideLength = value
  12:         End Set
  13:     End Property
  15:     Public Overrides Property Height As Integer
  16:         Get
  17:             Return _sideLength
  18:         End Get
  19:         Set(value As Integer)
  20:             _sideLength = value
  21:         End Set
  22:     End Property
  23: End Class


Now, say we had the following test:

   1: Public Sub SetHeight_DoesNotAffectWidth(rectangle As Rectangle)
   2:     'arrange
   3:     Dim expectedWidth = 4
   4:     rectangle.Width = 4
   6:     'act
   7:     rectangle.Height = 7
   9:     'assert
  10:     Assert.AreEqual(expectedWidth, rectangle.Width)
  11: End Sub


If we pass in a rectangle, this test passes just fine. What if we pass in a square?



This is where we see the violation of Liskov’s Principle! A square might "IS A” to a rectangle, but we have differing expectations on how a rectangle should function than how a square should!

Great expectations

Here’s where we pat ourselves on the back and take a victory lap around the office and tell everyone about how we understand LSP like a boss. And all is good… until we start trying to apply it to our work. If I can’t even change functionality on a simple setter without breaking the expectations on a parent class, what can I do with subtyping? Did Liskov just tell me to never touch subtyping again?

The short answer: NO, SHE DIDN’T. When I first learned LSP, and from those I’ve talked with as well, I overlooked a very important but not appropriately stressed quality of the principle: our expectations. Our inclination is to want a logical catch-all, where we can easily apply this principle and wipe our hands, drop the mic and exit stage left. That’s not the case because in every different programming scenario, our expectations of the parent class or type will be different. We have to set reasonable expectations on the behaviors that we expect out of the parent, then make sure that those expectations are met by the child. Any expectations not explicitly expected of the parent aren’t expected of the child either, and don’t register as a violation of LSP that prevents implementation.

You can see the flexibility mentioned in the Wikipedia article itself:

A typical example that violates LSP is a Square class that derives from a Rectangle class, assuming getter and setter methods exist for both width and height. The Square class always assumes that the width is equal with the height. If a Square object is used in a context where a Rectangle is expected, unexpected behavior may occur because the dimensions of a Square cannot (or rather should not) be modified independently. This problem cannot be easily fixed: if we can modify the setter methods in the Square class so that they preserve the Square invariant (i.e., keep the dimensions equal), then these methods will weaken (violate) the postconditions for the Rectangle setters, which state that dimensions can be modified independently. Violations of LSP, like this one, may or may not be a problem in practice, depending on the postconditions or invariants that are actually expected by the code that uses classes violating LSP. Mutability is a key issue here. If Square and Rectangle had only getter methods (i.e., they were immutable objects), then no violation of LSP could occur.

What this means is that the above situation with a rectangle and a square can be acceptable if we do not have the expectation for width to leave height unaffected, or vice-versa, in our application.

Conclusion – the oft forgot third wheel

Liskov Substitution Principle is meant to act as a guidance and warn us against unexpected behaviors. Objects can be stateful and as a result we can end up with unexpected situations if we don’t code carefully. Specifically when subclassing, make sure that the subclass meets the expectations held to its parent. Don’t let LSP think you cannot deviate from the behaviors of the parent, but understand that LSP is meant to highlight the importance of not only the parent and the child class, but also of the expectations WE set for the parent class and the necessity of meeting those expectations in order to help prevent sticky situations.


Code examples, in both VB and C#

Thursday, May 31, 2012 #

Applications these days have more options than ever for a user interface, and it’s only going to grow. A successful product might require native applications for mobile devices, a regular web implementation, or even a gaming console. These systems often will be centralized and data driven.

The solution is one that’s fairly solitary, a service layer! Simply put, take what’s shared and put it behind a physical or abstract layer that defines the boundary between the specific user interface and the shared content.



I know, I know, none of this is complicated. But some times it can be difficult to discern what belongs on which side of the line. For instance, say we’re creating a service that will provide content for both an ASP.NET MVC application and a WP7 application. Although the content served to each application is the same, there are different paradigms and patterns for displaying that data in the different environments. In ASP.NET MVC, you may create a model specific to a page that combines necessary information. In the WP7 application you might require different sets of data that you will connect via MVVM with the view.

The general rule of thumb is that any shared content, business rules, or data should exist separately. Any element that is specific to the current UI implementation should be included in a separate library or with the UI implementation itself. The WP7 application doesn’t need my MVC specific model classes. My MVC application doesn’t require those INotifyPropertyChanged viewmodels that the WP7 application depends on. In both cases, there should be additional processing done above the service layer to massage the data to the application’s specific needs.


Service-ocalypse: the text based adventure

What helps me the most about deciding whether or not something belongs coupled to the UI implementation or in the shared implementation is thinking of the simplest implementation you could have: a console application. You might have played a game like Peasant’s Quest:


The console app is the text based adventure game version of your application. If you’re service was consumed in its simplest form, you would simply have a console based API for it that issues requests. Maybe those requests aren’t SWIM TO BOAT, but they might be CREATE USER JOHN. If I issue a request, I expect that request to be issued to the service. If the service has any exceptions or issues with my input, that business logic should be encapsulated in that service, not implemented in the UI. The service layer should be your functional application in its entirety, and anything above that layer should only assist with the display of that information.

Monday, April 30, 2012 #

Since I recently went through this I figured it would be worthwhile to compile the downloads, regedits and other steps into one location.


Downloads for Visual Studio 2008

You’ll need to download and install the following for Visual Studio 2008 in this order. You may need to reinstall SP1 if you already have it installed to ensure TFS 2008 behaves properly:


Adding the TFS repository

If Visual Studio 2008 will let you, you can now add the server with the following format:


If you get TF30335: The server name cannot contain characters ‘/’ or ‘:’ …:

  1. Open Regedit and browse to HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\TeamFoundation\Servers
  2. Add a new string value:
    1. Name – Friendly name that VS2008 will display.
    2. Value - https://tfsserver:port/vdir/projectCollection

Important Note: In VS2010 you don’t have to specify the project collection to connect. Please be mindful that this is necessary for 2008!



Monday, April 16, 2012 #

For the past two years SQL Saturday and Tech Day in Baton Rouge has offered tracks across the Microsoft stack to its attendees. This event is one of the largest SQL Saturdays and attracted 400 registrants last year. We are looking for speakers experienced in SQL Server, .NET development, Sharepoint, Windows IT Professionals and other professional skills that apply to the technology field. If you are interested in speaking please visit and submit your sessions. Submissions close June 5th.

Saturday, March 31, 2012 #

If you’re familiar with SSRS and development you are probably aware of the SSRS web services. The RS utility is a tool that comes with SSRS that allows for scripts to be executed against against the SSRS web service without needing to create an application to consume the service. One of the better benefits of using this format rather than writing an application is that the script can be modified by others who might be involved in the creation and addition of scripts or management of the SSRS environment.


Reporting Services Scripter

Jasper Smith from created Reporting Services Scripter to assist with the created of a batch process to deploy an entire SSRS environment. The helper scripts below were created through the modification of his generated scripts.

Why not just use this tool? You certainly can. For me, the volume of scripts generated seems less maintainable than just using some common methods extracted from these scripts and creating a deployment in a single script file. I would, however, recommend this as a product if you do not think that your environment will change drastically or if you do not need to deploy with a higher level of control over the deployment. If you just need to replicate, this tool works great.

Executing with RS.exe

Executing a script against rs.exe is fairly simple.


The Script

Half the battle is having a starting point. For the scripting I needed to do the below is the starter script. A few notes:

  • This script assumes integrated security.
  • This script assumes your reports have one data source each.

Both of the above are just what made sense for my scenario and are definitely modifiable to accommodate your needs. If you are unsure how to change the scripts to your needs, I recommend Reporting Services Scripter to help you understand how the differences.

The script has three main methods: CreateFolder, CreateDataSource and CreateReport. Scripting the server deployment is just a process of recreating all of the elements that you need through calls to these methods. If there are additional elements that you need to deploy that aren’t covered by these methods, again I suggest using Reporting Services Scripter to get the code you would need, convert it to a repeatable method and add it to this script!

Public Sub Main()
    CreateFolder("/", "Data Sources")
    CreateFolder("/", "My Reports")
    CreateDataSource("/Data Sources", "myDataSource", _
        "Data Source=server\instance;Initial Catalog=myDatabase")
    CreateReport("/My Reports", _
        "MyReport", _
        "C:\myreport.rdl", _
        True, _
        "/Data Sources", _
End Sub
Public Sub CreateFolder(parent As String, name As String)
    Dim fullpath As String = GetFullPath(parent, name)
        RS.CreateFolder(name, parent, GetCommonProperties())
        Console.WriteLine("Folder created: {0}", name)
    Catch e As SoapException
        If e.Detail.Item("ErrorCode").InnerText = "rsItemAlreadyExists" Then
            Console.WriteLine("Folder {0} already exists and cannot be overwritten", fullpath)
            Console.WriteLine("Error : " + e.Detail.Item("ErrorCode").InnerText + " (" + e.Detail.Item("Message").InnerText + ")")
        End If
    End Try
End Sub
Public Sub CreateDataSource(parent As String, name As String, connectionString As String)
        RS.CreateDataSource(name, parent,False, GetDataSourceDefinition(connectionString), GetCommonProperties())
        Console.WriteLine("DataSource {0} created successfully", name)
    Catch e As SoapException
        Console.WriteLine("Error : " + e.Detail.Item("ErrorCode").InnerText + " (" + e.Detail.Item("Message").InnerText + ")")
    End Try
End Sub
Public Sub CreateReport(parent As String, name As String, location As String, overwrite As Boolean, dataSourcePath As String, dataSourceName As String)
    Dim reportContents As Byte() = Nothing
    Dim warnings As Warning() = Nothing
    Dim fullpath As String = GetFullPath(parent, name)
    'Read RDL definition from disk
        Dim stream As FileStream = File.OpenRead(location)
        reportContents = New [Byte](stream.Length-1) {}
        stream.Read(reportContents, 0, CInt(stream.Length))
        warnings = RS.CreateReport(name, parent, overwrite, reportContents, GetCommonProperties())
        If Not (warnings Is Nothing) Then
            Dim warning As Warning
            For Each warning In warnings
            Next warning
            Console.WriteLine("Report: {0} published successfully with no warnings", name)
        End If
        'Set report DataSource references
        Dim dataSources(0) As DataSource
        Dim dsr0 As New DataSourceReference
        dsr0.Reference = dataSourcePath
        Dim ds0 As New DataSource
        ds0.Item = CType(dsr0, DataSourceDefinitionOrReference)
        dataSources(0) = ds0
        RS.SetItemDataSources(fullpath, dataSources)
        Console.Writeline("Report DataSources set successfully")
    Catch e As IOException
    Catch e As SoapException
        Console.WriteLine("Error : " + e.Detail.Item("ErrorCode").InnerText + " (" + e.Detail.Item("Message").InnerText + ")")
    End Try
End Sub
Public Function GetCommonProperties() As [Property]()
    'Common CatalogItem properties
    Dim descprop As New [Property]
    descprop.Name = "Description"
    descprop.Value = ""
    Dim hiddenprop As New [Property]
    hiddenprop.Name = "Hidden"
    hiddenprop.Value = "False"
    Dim props(1) As [Property]
    props(0) = descprop
    props(1) = hiddenprop
    Return props
End Function
Public Function GetDataSourceDefinition(connectionString as String)
    Dim definition As New DataSourceDefinition
    definition.CredentialRetrieval = CredentialRetrievalEnum.Integrated
    definition.ConnectString = connectionString
    definition.Enabled = True
    definition.EnabledSpecified = True
    definition.Extension = "SQL"
    definition.ImpersonateUser = False
    definition.ImpersonateUserSpecified = True
    definition.Prompt = "Enter a user name and password to access the data source:"
    definition.WindowsCredentials = False
    definition.OriginalConnectStringExpressionBased = False
    definition.UseOriginalConnectString = False
    Return definition
End Function
Private Function GetFullPath(parent As String, name As String) As String
    If parent = "/" Then
        Return parent + name
        Return parent + "/" + name
    End If
End Function

Monday, February 27, 2012 #

Last year I had the pleasure of attending one of Markus Egger’s sessions at Houston Techfest. Markus is the President and CSA of EPS Software, creators of CODE magazine and a company that I have a great amount of respect for. The people I’ve met from EPS have consistently been great programmers and speakers who have a commitment to creating great software.

The reason I bring up Markus Egger and EPS Software is because of a particular aspect of their business that challenges me as an individual and as a developer. On Markus’s personal website as well as published in CODE Magazine are several public facing postmortems. That’s right. Public postmortems.

These postmortems outline the successes and failures, the right decisions and the wrong decisions, that were made on real life projects performed by EPS software. This isn’t just a case study that glosses over details and highlights just the positives. I personally am in awe of this. Maybe admitting this says something negative about me, but I think it’s worth saying: I admire the courage and confidence that this concept portrays.

The concept of a public postmortem makes me ask myself the following questions: If I knew my successes and failures would be made public, would I code any differently? Would I have made the same decisions? Am I truly looking to learn from my mistakes? What if my company made public facing postmortems? What would my personal postmortem say on Project XYZ? Can I code without regret?

Software development is a continuous learning process, one that I am confident that the day I believe I have mastered it is the day I should be forcefully retired or committed. Our profession is one of continuous growth and learning, only bested by a continual desire to better oneself. We all have our moments of reflection where we see something we’ve written before and cringe. We’ve all written code that we adamantly hope is never traced back to us. That there’s no developer lurking in the dark alleyways of the internet waiting for the right time to surface and single us out.

The admiration I have is for the pure embrace of the fact that we are imperfect. We will make mistakes and hedge bets that might not turn out as well. There are lessons we can learn if we are willing to hold ourselves accountable for those missed decisions. If we cannot do that, then we will never become the greatest we can be and we will never have the confidence necessary to make the best decisions we can make.

So here’s the call to action. For myself, for anyone who might be listening. Let’s code with the confidence that our decisions were the best we could have made. Let’s reflect afterwards and confirm or adjust our opinions to align with the results we’ve achieved. Let’s learn to code without regret.