# Monday, November 07, 2011

ASP.NET MVC provides a lot of HTML Helpers that allow you to more easily with less code create your views.  Typically navigation in MVC is done using the ActionLink HTML Helper that allows you easily generate an html anchor tag that will redirect to a specified controller and action.  I found cases where I wanted my navigation to be done via a button rather than a link so I created my own HTML Helper to make this easier.


  1. using System.Web.Routing;
  3. namespace System.Web.Mvc.Html {
  5.     public static class ActionLinkButtonHelper {
  7.         public static MvcHtmlString ActionLinkButton(this HtmlHelper htmlHelper, string buttonText, string actionName, string controllerName, RouteValueDictionary routeValues) {
  8.             string href = UrlHelper.GenerateUrl("default", actionName, controllerName, routeValues, RouteTable.Routes, htmlHelper.ViewContext.RequestContext, false);
  9.             string buttonHtml = string.Format("<input type=\"button\" title=\"{0}\" value=\"{0}\" onclick=\"location.href='{1}'\" class=\"button\" />",buttonText,href);
  10.             return new MvcHtmlString(buttonHtml);
  11.         }
  12.     }
  13. }

Example Usage:

  1. @Html.ActionLinkButton("Add", "AddSiteFromDistrict", "SiteMaintenance", new RouteValueDictionary(new { districtID = @Model.DistrictID }))
posted on Monday, November 07, 2011 8:53:15 AM (Central Standard Time, UTC-06:00)  #    Comments [2]
# Monday, October 31, 2011

I recently put together an Entity Framework Code First demo that I presented to my colleagues at Skyline Technologies.

The demo includes:

  • Generating DB from POCO’s
  • Fluent and Attribute EF configuration examples
  • Creating Relationships (1 –> Many, Many –> Many)
  • Seeding Data
  • Using a separate DB instance for integration testing
  • How using Data Annotations saves you time in MVC
  • New Features Coming In EF vNext
    • Enums
    • Spatial Data Type

I put the code up on GitHub so if you are looking for an EF Code First kick starter took a look!

posted on Monday, October 31, 2011 7:35:41 AM (Central Standard Time, UTC-06:00)  #    Comments [3]
# Saturday, October 29, 2011

My latest project was being done in ASP.NET MVC3 and I needed to do some date validation that was beyond what was available out-of-the-box.  I Googled around the inter-webs for awhile and couldn’t find anything that met my needs so I decided to create my own set of extensions…and while I was at create my NuGet package and CodePlex project.

For some reason the validation attributes available for the Date data type are non-existence in MVC.  You can compare to another model field, but that only checks for equality.  You can use regular expressions, which is not fun, and you can only compare against static values, or you can create your own validation attributes…which is the route I chose.

I created custom validation attributes that I found that I needed in my projects and packed some up to make available to the masses.

EzValidation contains validation for:

  • Equal, NotEqual, Greater, Less, GreaterOrEqual, LessOrEqual
    • Available for all Primitive Data Types (including nullable)
    • Compare to another field in the Model
        1. [Equal("Email")]
        2. public string ConfirmEmail { get; set; }
    • Compare to a specific value
        1. [NotEqual("|28|")]
        2. public int Age {get; set;}
    • Compare to Current Date (Dates and Strings only)
        1. [Greater("CompareToCurrentDate")]
        2. public DateTime ADateInTheFuture { get; set; }
    • Compare to Yesterday's Date (Dates and Strings only)
        1. [Less("CompareToYesterday")]
        2. public DateTime DateBeforeYesterday { get; set; }
    • Compare to Tomorrow's Date (Dates and Strings only)
        1. [GreaterOrEqual("CompareToTomorrow")]
        2. public DateTime DateAfterTomorrow { get; set; }


    The source Code is available on CodePlex.

    The package can be installed via NuGet.  “package-install EzValidation"

    posted on Saturday, October 29, 2011 7:09:00 PM (Central Daylight Time, UTC-05:00)  #    Comments [1]
    # Sunday, July 03, 2011

    Earlier this year during Chicago Code Camp 3, I had the privilege of sitting down with Clark Sell and Marc Nichols and recording my first podcast.  Clark and Mark are the duo behind Developer Smackdown.  If you are not familiar with Developer Smackdown I suggest you take a listen.  In my musing, as Clark and Marc refer to the episodes, we discuss a topic very near and dear to my hear, Test-driven Development.  Take a listen and let me know what you think.

     TDD With Keith Burnell

    posted on Sunday, July 03, 2011 8:30:00 PM (Central Daylight Time, UTC-05:00)  #    Comments [2]
    # Sunday, May 22, 2011

    Last weekend I presented a session at the third annual Chicago Code Camp entitled: Test-driven Development in .NET – Tips, Tools, and Techniques.  The session was standing room only and carried into the commons area afterwards with some excellent questions from attendees.  What is greater than that is that the questions didn’t stop there, they kept coming via email.  One question in particular has stuck with me because it was a hurdle I myself had to overcome early on in my TDD adventures.

    The question boiled down to how do you test code the depends on ASP.NET, specifically Web Configuration and Application Settings?  So I thought I would put together a blog post how this can be done, and how it should be done.

    To set the stage…I have a simple ASP.NET web application with one page and one class.  The page load method calls the one method in the class that returns an app setting stored in the web config file.

    1. namespace WebApp
    2. {
    3.     public partial class Index : System.Web.UI.Page
    4.     {
    5.         protected void Page_Load(object sender, EventArgs e) {
    6.             lblValue.Text = SomeClassThatNeedsTesting.GetSomeStringValue();
    7.         }
    8.     }
    9. }

    1. namespace WebApp
    2. {
    3.     public static class SomeClassThatNeedsTesting
    4.     {
    5.         public static string GetSomeStringValue() {
    6.             return System.Web.Configuration.WebConfigurationManager.AppSettings["MyAppSettingValue"];
    7.         }
    8.     }
    9. }

    Your first option to getting your tests to run and return the configuration and/or app settings is to tell your tests to run under the ASP.NET host process and not the VSTest host process and also tell what url to run the test under.

    1. [TestMethod]
    2. [HostType("ASP.NET")]
    3. [UrlToTest("http://localhost:2356/Index.aspx")]
    4. [AspNetDevelopmentServerHost("$(SolutionDir)\\WebApp")]
    5. public void GetSomeStringValue_ShouldReturn_NonNull_NonEmpty_String() {
    6.     var val = WebApp.SomeClassThatNeedsTesting.GetSomeStringValue();
    7.     Console.WriteLine(val.ToString());
    8.     Assert.IsFalse(string.IsNullOrEmpty(val));
    9. }

    If you run this you will see that the test passes…eventually…after Casini is started and the test runner twiddles its thumbs for a bit.  Speed is my first issue with setting up your test to run in this fashion.  My second issue is that you aren’t testing the ASP.NET configuration framework so why would you need to add all this extra plumbing to make your code take that route?  There is a better option!

    Since we really don’t care how or where are value comes from we just need some sort of value returned so we can test our method, we can easily add a thin layer of abstraction and mock the pieces of code that depend on ASP.NET.

    Lets start by creating an interface for a simple class that reads application settings.

    2. namespace WebApp {
    4.     public interface IAppSettingsReader {
    6.         string GetAppSettingValue(string settingKey);
    7.     }
    8. }

    Now we can implement the interface and add the actual code to read the app settings from the web config file.

    1. namespace WebApp {
    3.     public class AppSettingsReader : IAppSettingsReader {
    5.         public string GetAppSettingValue(string settingKey) {
    6.             if (string.IsNullOrEmpty(settingKey)) throw new NullReferenceException("settingKey is required");
    7.             return (WebConfigurationManager.AppSettings[settingKey]);
    8.         }
    10.     }
    11. }

    Next we will modify our class that needs testing to use the new AppSettingsReader.  Because our goal is to eventually be able to mock the settings reader we need to invert the control of the dependency and provide a mechanism for injecting the dependency.  The change is fairly straightforward.

    1. namespace WebApp {
    3.     public class SomeClassThatNeedsTesting {
    5.         private readonly IAppSettingsReader _settingsReader;
    7.         public SomeClassThatNeedsTesting(IAppSettingsReader settingsReader) {
    8.             _settingsReader = settingsReader;
    9.         }
    11.         public string GetSomeStringValue() {
    12.             return _settingsReader.GetAppSettingValue("MyAppSettingValue");
    13.         }
    14.     }
    15. }

    Now we have introduced a breaking change and need to modify our page and our test to accommodate the change to SomeClassThatNeedsTesting.

    1. namespace WebApp {
    3.     public partial class Index : Page {
    5.         protected void Page_Load(object sender, EventArgs e) {
    6.             var someClass = new SomeClassThatNeedsTesting(new AppSettingsReader());
    7.             lblValue.Text = someClass.GetSomeStringValue();
    8.         }
    9.     }
    10. }

    1. namespace TestProject {
    3.     [TestClass]
    4.     public class SomeClassThatNeedsTesting_Tests {
    6.         [TestMethod]
    7.         [HostType("ASP.NET")]
    8.         [UrlToTest("http://localhost:2356/Index.aspx")]
    9.         [AspNetDevelopmentServerHost("$(SolutionDir)\\WebApp")]
    10.         public void GetSomeStringValue_ShouldReturn_NonNull_NonEmpty_String_ASP() {
    11.             SomeClassThatNeedsTesting someClass = new SomeClassThatNeedsTesting(new AppSettingsReader());
    12.             string val = someClass.GetSomeStringValue();
    13.             Console.WriteLine(val);
    14.             Assert.IsFalse(string.IsNullOrEmpty(val));
    15.         }
    16.     }
    17. }

    At this point we can run our test from above and, after we have taken a bathroom break, checked Twitter, and made a sandwich, we will notice that the test still passes.  This is true because all we have done is add a layer of abstraction.  We have not changed the core functionality of the process.  Now that the layer of abstraction is in place we can write another test and this time instead of writing more code to please ASP.NET lets drop that dependency completely by mocking it.

    To implement our mock I am going to use my mocking tool of choice, RhinoMocks.  (I am purposefully not supplying a URL here because you should be using NuGet to get your packages!)

    Here is our new and improved test.

    New And Improved Test
    1. [TestMethod]
    2. public void GetSomeSringValue_ShouldReturn_NonNull_NonEmpty_String_Mocked() {
    3.     //Arrange
    4.     string myAppSettingValue = "This is my expected mocked setting value";
    5.     MockRepository _repository = new MockRepository();
    6.     IAppSettingsReader mockSettingsReader = MockRepository.GenerateStrictMock<IAppSettingsReader>();
    7.     mockSettingsReader.Expect(msr => msr.GetAppSettingValue("MyAppSettingValue")).Return(myAppSettingValue).Repeat.Once();
    8.     _repository.ReplayAll();
    9.     //Act
    10.     SomeClassThatNeedsTesting someClass = new SomeClassThatNeedsTesting(mockSettingsReader);
    11.     string val = someClass.GetSomeStringValue();
    12.     //Assert
    13.     Assert.AreEqual(myAppSettingValue, val, "Wrong value returned from GetSomeSringValue");
    14. }

    If you take a look at the test you can see that the first thing that I did was create my mock AppSettingReader and set my expectations.  After that I instantiated my class under test and passed in the settings reader mock.

    Hope you found this useful!  Complete code is available here!

    posted on Sunday, May 22, 2011 7:17:23 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]