Testing Versioned API’s in ASP.Net Web API

I recently wrote about a framework for Versioning ASP.Net Web API. Continuing on the theme of versioning API’s, I researched how to test the different versions of a Web API, both for unit tests and SpecFlow acceptance tests.

Overview

As a quick review, the SDammann.WebApi.Versioning package was used for versioning the API and provides methods for selecting the controller that is active for a particular version of the API. At the code level the controller is selected by the name space of the particular version of the controller, e.g. Appname.Controllers.Version1. As mentioned in the last post, care must be taken to avoid unnecessary duplication in the controllers. Likewise the same duplication concerns apply for testing and relevant techniques will be reviewed in this post.

SpecFlow Tests

I previously covered using SpecFlow for testing the Web API.  When new versions of a Web API are introduced the following items should be considered:

  • Continue testing the previous versions that are still being supported.
  • Ensure that the features of the new version are being tested.

The challenge is to extend the test coverage across multiple versions of the Web API without duplicating features or steps. Fortunately SpecFlow provides a syntax to run the same scenario multiple times via a feature called “Scenario Outline”. This feature also allows the scenario to pass variables for each run of the scenario.

Running a Test for Multiple Versions

The ability to run a test for both versions, V1 and V2, can be set up as follows:

Scenario Outline: Create a new project saves posted values - All Versions
	Given the following project inputs and authentication
		| Field       | Value            |
		| Name        | Test Project     |
		| Description | Test Description |
		| IsUrgent    | True             |
		| UserName    | james            |
		| Password    | james2013        |
	When the client posts the inputs to the website for <Version>
	Then a Created status should be returned
	When the client gets the project by header location
	Then the saved project matches the inputs for <Version>
Scenarios: 
	| Version |
	| V1      |
	| V2      |    

The “Scenarios:” table at the bottom of the Scenario Outline provides a variable called Version that gets passed to the tests.  Since there are two instances of Version in the table it will get passed twice to run the tests for each version. The <Version> variable within the steps will get passed to the step definition.  For example the step definition for the first When statement above is written as follows:

[When(@&quot;the client posts the inputs to the website for V(.*)&quot;)]
public void WhenTheClientPostsTheInputsToTheWebsiteForV(int version)
{
  var client = StepHelpers.SetupHttpClient(_projectTestModel.UserName, _projectTestModel.Password);

  var postData = StepHelpers.SetPostData&lt;ProjectTestModel&gt;(_projectTestModel);
  HttpContent content = new FormUrlEncodedContent(postData);

  _responseContent = client.PostAsync(&quot;http://localhost:55301/api/v&quot; + version.ToString() + &quot;/projects&quot;, content).Result;
  client.Dispose();
}

The V(.*) construct within the step causes the integer part of the “Vn” to be passed to the step. Therefore for the case where “V1” is defined in the Scenario Outline then “1” will be passed via the method argument as “version”.  Then the “version” variable will be used to call the correct version of the API from within the body of the method in client.PostAsync() for each run.

Likewise for the second “Then” statement that validates the saved inputs, the “<Version>” can be passed so that any inputs that are not available in V1 are only checked for newer versions:

[Then(@&quot;the saved project matches the inputs for V(.*)&quot;)]
public void ThenTheSavedProjectMatchesTheInputs(int version)
{ 
  Assert.AreEqual(_projectTestModel.Name, _projectSaved.Name);
  Assert.AreEqual(_projectTestModel.Description, _projectSaved.Description);  
  Assert.AreEqual(_projectTestModel.UserName, _projectSaved.UserName);
  if (version &gt; 1) 
  {
    Assert.AreEqual(_projectTestModel.IsUrgent, _projectSaved.IsUrgent);
  }
}

Running a Test for a Specific Version

Some tests might be applicable for a specific version. For example to test that the lack of “IsUrgent” input should return an error only for V2.  Therefore the Scenario Outline can be set up to only run V2:

Scenario Outline: Create a new project where IsUrgent is missing returns bad request - V2
	Given the following project inputs and authentication
		| Field       | Value            |
		| Name        | Test Project     |
		| Description | Test Description |
		| UserName    | james            |
		| Password    | james2013        |
	When the client posts the inputs to the website for &lt;Version&gt;
	Then a BadRequest status should be returned
Scenarios: 
	| Version |
	| V2      |

This scenario will only run once for V2.  It is still useful to put it in the scenario outline so that when V3 is created it will be easy to extend the test to run for that version by adding a V3 row to the table at the bottom.

Running the Scenarios in Nunit

When the versions are tested in this fashion in NUnit, they will be shown as nested under each Scenario Outline:

image

The value of the variable that was passed for each run is shown and is helpful for identifying the test that was run.

Unit Tests

Unit test can be handled via a similar pattern to run the same test case multiple times by version. For example with NUnit there is an attribute called “[TestCase()]” that can be attached to a test instead of the simple “[Test]” attribute. The TestCase attribute can pass a variable to the test method, in this case it will pass “version”:

[TestCase(&quot;V1&quot;)]
[TestCase(&quot;V2&quot;)]
public void Get_Projects_Returns_Expected_Projects_For_John(string version)
{
  //Arrange
  _projectRepository = _mockRepositories.GetProjectsRepository(ReturnType.Normal);
  var projectsController = SetupController(_projectRepository.Object, &quot;john&quot;, HttpMethod.Get, version);

  //Act
  var response = projectsController.Get();
  var responseContent = JsonConvert.DeserializeObject&lt;ProjectDto&gt;(response.Content.ReadAsStringAsync().Result);

  //Assert 
  Assert.AreEqual(HttpStatusCode.OK, response.StatusCode, &quot;Expecting an OK Status Code&quot;); 
  Assert.AreEqual(1, responseContent.Projects.Count);
  Assert.AreEqual(1, responseContent.Meta.NumberProjects); 
  Assert.AreEqual(&quot;john&quot;, responseContent.Projects[0].UserName);
  Assert.AreEqual(&quot;Test Project 3&quot;, responseContent.Projects[0].Name);
}

The version variable is then used in the creation of the projects controller in the “Arrange” portion of the test. In the helper method that creates the controller the version variable is used as follows:

private dynamic SetupController(IProjectRepository mockRepository, string userName, HttpMethod method, string version)
{  
  dynamic projectsController = null;
            
  if (version == &quot;V1&quot;)  
  {
    projectsController = new ResearchLinks.Controllers.Version1.ProjectsController(mockRepository);
  }  
  else if (version == &quot;V2&quot;) 
  {
    projectsController = new ResearchLinks.Controllers.Version2.ProjectsController(mockRepository);
  }
  // other setup code ommitted...
            
  return projectsController;
}

In this case the purpose is to ensure that the correct controller is constructed according to the name space partitioning by version that is used by the SDammann.WebApi.Versioning package.

Running Unit Tests in NUnit

When the NUnit tests that are decorated with the “[TestCase()]” attribute are run in the NUnit Test Runner they appear similar to the SpecFlow tests:

image

As with the SpecFlow tests the version variable passed to the methods within each test case help identify when there are problems with an individual test case.

Summary

To fully test all versions of a Web API the “Scenario Outline” feature in SpecFlow and the “TestCase” feature in NUnit may be used to ensure that all versions are being tested without duplication of code or tests.

The full source for this project can be found at https://github.com/turnkey-commerce/ResearchLinks.  The unit tests are in the ResearchLinks.Tests folder and the Specflow tests are in the ResearchLinks.SpecTests folder.

Versioning ASP.Net Web API

One of the important things to consider when building an API is a strategy for versioning the API to manage changes.  There are several reasons this is important:

  • To support users (developers) of the API that are using an existing version so as not to force breaking changes on them.
  • To prevent breaking existing versions of the client applications that are using an existing version of the API.

Previous versions of the API will normally be maintained for either a period to allow developers and client applications to upgrade or indefinitely.

Strategies for Versioning

There are multiple ways to indicate the version of the API:

  • Specify the version as part of the URI address or URL query parameters, e.g.
    http://www.example.com/api/v1/projects
    
    http://www.example.com/api/projects?version=1
  • Specify the version as part of the Accept request header, for example:
    Accept: application/vnd.company.myapp.customer-v3+xml
  • Specify the version as a special request header, for example:
    X-API-VERSION: 3

There are pros and cons of each approach, and have been extensively discussed on the Internet with religious fervor.  I recently attended a nice talk by Michael Pratt on how to version or not version your API (be sure to use down arrows for pros and cons for each strategy). The best approach is to pick a strategy that best fits your use cases and to stick with it for consistency.

Adding Versioning to ASP.Net Web API

There are no versioning capabilities provided by the ASP.Net Web API out of the box. However there is a nice Nuget package called SDammann.WebApi.Versioning by Sebastiaan Dammann that extends the Web API with a versioning framework. The package is flexible in that it allows the API developer to choose one of the strategies mentioned above for the API versioning.  This article will show how to set up the framework on a project.

Setting Up the Project

The first step is to get the WebApi.Versioning from Nuget by bringing up the Package Manager Console and getting the Nuget package:

PM> Install-Package SDammann.WebApi.Versioning

In this example we are going to use the the URI address strategy to indicate the versioning.

The next step is to indicate in the Global.Asax.cs\Application_Start method to use the versioning package for the controller selector and to provide the strategy to use for the controller selection:

// enable API versioning
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerSelector),
              new RouteVersionedControllerSelector(GlobalConfiguration.Configuration));

In this case the new RouteVersionControllerSelector(…) indicates to the package which strategy to use (in this case selecting by routes in the URI). For that to work the default route (and likewise any custom routes) must be modified to include the version in App_Start\WebApiConfig.cs:

config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/v{version}/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

The {version} integer variable after the “v” will be utilized by the package to determine which controller to use based on the value. For example “v1” will indicate to use the controllers that are in the namespace Appname.Controllers.Version1.

Managing Controllers to Avoid Duplication

One of the downsides of this approach is that it could cause a lot of code duplication if the entire controllers are copied to a new namespace each time a version is added. One approach to reduce besides keeping the controllers “skinny” is to add a base class for each controller and implement overrides for the version where needed.  For example the Controllers folder would look something like this:

image

The base controllers would contain the initial implementation for version 1 with virtual methods:

namespace ResearchLinks.Controllers
{
    [Authorize]
    public class ProjectResearchItemsControllerBase : ApiController
    {
        protected IResearchItemRepository _researchItemRepository;
        protected IProjectRepository _projectRepository;

        // GET /api/projects/4/researchItems
        public virtual HttpResponseMessage Get(int projectId)
        {
            var researchItems = new List<ResearchItem>();
            var project = new Project();
            // Rest of implementation ommitted...
        }
...

Then for the Version1 implementation it would not need to override any methods but only provide services such as dependency injection and to expose the methods to the Version1 class:

namespace ResearchLinks.Controllers.Version1
{
    [Authorize]
    public class ProjectsController : ProjectsControllerBase
    {
        // Constructor here to inject dependencies in concrete class.
        public ProjectsController(IProjectRepository projectRepository)
        {
            _projectRepository = projectRepository;
        }

        // Nothing to override in Version1
    }
}

Then for Version2 we can override the methods that will be affected by a change and ignore the other methods that will be inherited from the base class. For example say we need to add a new Boolean property to the Project model called “IsUrgent”. We don’t want it to affect Version1 users but we do want it to be mandatory for Version2.  We can add this property to the model as a nullable Boolean property and not add any Required attributes so as not to disturb Version1 usage:

    public class Project
    {
        [Key]
        public int ProjectId { get; set; }

        [Required, MaxLength(50)]
        public string Name { get; set; }

        // Added for version 2 and higher
        public bool? IsUrgent { get; set; }

        // Other properties omitted...

    }

This change will affect the “Post” and “Put” verbs for the Projects controller and we will need to override those methods.  For example to override the “Post” method and to ensure the required flag is present we can do the following:

namespace ResearchLinks.Controllers.Version2
{
    [Authorize]
    public class ProjectsController : ProjectsControllerBase
    {
    
        //VERSION 2!

        // In version 2 we need to add an additional bool property IsUrgent on the post and put.
        // We will catch it in the controller since it is not required in the data model for backward compatibility in V1.

        // Constructor here to inject dependencies in concrete class.
        public ProjectsController(IProjectRepository projectRepository)
        {
            _projectRepository = projectRepository;
        }

        // POST api/v2/projects (Insert)
        public override HttpResponseMessage Post(Project project)
        {
            // Check for presence of V2 "IsUrgent" flag.
            if (project.IsUrgent == null)
            {
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "The IsUrgent indicator is required.");
            }
           // Rest of implementation ommitted...
        }
...

Conclusion

The SDammann.WebApi.Versioning package provides an easy and flexible framework for versioning ASP.Net Web API. It covers the most common strategies to version a web API and could be extended to support less common methods as it is open source.

In the next blog post I will discuss strategies for testing the versioning of the Web API.

The full source for this project can be found at https://github.com/turnkey-commerce/ResearchLinks.

Using SpecFlow to Test the ASP.Net Web API

I previously wrote about the use of SpecFlow in an ASP.Net MVC application with the SimpleBrowser library. I’ve recently been building a project to utilize the ASP.Net Web API to study the best practices of building a “RESTful” API for an application to save research notes and links about multiple projects.

Approach

Since the Web API is intended to be utilized by a number of types of client applications that support the HTTP protocol (smart phones, tablets, desktop applications, as well as browsers), it is convenient to use a library that is well-suited to use the HTTP verbs used by the Web API. In this case I used the HTTPClient class for interacting with the Web API.

For example in the case of posting a new project, and the client has been setup with the proper post parameters, then the client can post to the Web API as follows:

_responseContent = client.PostAsync("http://localhost:55301/api/projects", content).Result;

The “.Result” property causes the results to be returned to the _responseContent synchronously, which is desired for the tests.

Similarly to test an update (“put” verb) then the client can post to the Web API as follows:

_responseContent = client.PutAsync("http://localhost:55301/api/projects/" + _projectSaved.ProjectId, content).Result;

Defining SpecFlow Feature Files

The feature files are defined to exercise the various features of the API, for example the post verb to create a new project:

  Feature: Projects API
      In order to perform CRUD operations on the projects
      As a client of the Web Api
      I want to be able to Create, Update, Delete, and List projects

  Scenario: Create a new project saves posted values.
      Given the following project inputs and authentication
          | Field       | Value            |
          | Name        | Test Project     |
          | Description | Test Description |
          | UserName    | james            |
          | Password    | james2013        |
      When the client posts the inputs to the website
      Then a Created status should be returned
      When the client gets the project by header location
      Then the saved project matches the inputs

This scenario gathers the inputs, then posts the inputs to the Web API. It then checks that a “Created” status is returned. Then from the “location” header returned, the client will use that information to get the project that was saved and than verify that it matches the inputs.

Similar tests are setup for the other verbs for the Project API.

Defining Step Details

For each of the steps in the scenario a corresponding C# step file will be defined. The details for each step will be discussed below.

Given the following project inputs and authentication

This step takes the Fields and Values defined in the scenario and uses a SpecFlow helper “FillInsance” to load the values into a “ProjectTestModel” DTO class that was defined for holding values associated with the tests:

[Given(@"the following project inputs and authentication")]
public void GivenTheFollowingProjectInputsAndAuthentication(Table table)
{
     table.FillInstance<ProjectTestModel>(_projectTestModel);
}

This properties of the _projectTestModel member variables will be used downstream in the other steps.

When the client posts the inputs to the website

This step takes the inputs loaded in the previous step and uses them to post to the Web API to create a new project:

[When(@"the client posts the inputs to the website")]
public void WhenTheClientPostsTheInputsToTheWebsite()
{

     var client = StepHelpers.SetupHttpClient(_projectTestModel.UserName, _projectTestModel.Password);

     var postData = StepHelpers.SetPostData<ProjectTestModel>(_projectTestModel);
            HttpContent content = new FormUrlEncodedContent(postData);

     _responseContent = client.PostAsync("http://localhost:55301/api/projects", content).Result;
            client.Dispose();
}

This step uses two custom helpers to set up the HttpClient with the authentication header and to set up the post data from the ProjectTestModel DTO. These helpers reduce the amount of repetitive code in the steps. Finally the client posts the data to the Web API and captures the response.

Then a Created status should be returned

This step does an assert to check that the expected Status code is returned in the response:

[Then(@"a (.*) status should be returned")]
public void ThenAStatusShouldBeReturned(string statusCode)
{
     Assert.AreEqual(statusCode, _responseContent.StatusCode.ToString());
}

This step is coded in a way that the status code that is expected is passed in the step definition with the (.*) wildcard and passed to the code as “statusCode”. Then it compares the expected statusCode to the one that is returned in the _responseContent returned from the previous step.

When the client gets the project by header location

This step gets the URL path for the new project by examining the “Location” header parameter that was returned by the response.  This will give the path and project ID needed to get the created project:

[When(@"the client gets the project by header location")]
public void WhenTheClientGetsTheProjectByHeaderLocation()
{
      var client = StepHelpers.SetupHttpClient(_projectTestModel.UserName, _projectTestModel.Password);
      _responseContent = client.GetAsync(_responseContent.Headers.Location).Result;
      _projectSaved = JsonConvert.DeserializeObject<Project>(_responseContent.Content.ReadAsStringAsync().Result);
            client.Dispose();
}

This step does a setup of a new HttpClient similar to the post. However, in this case it does a “get” verb using the URL that was returned in the “Location” header. The JSON.Net library is then used to deserialize the response into the “_projectSaved” Project object so that it can be used to compare to the expected values.

Then the saved project matches the inputs

This step will then do asserts to compare the properties of the inputs in the “_projectTestModel” DTO to the “_projectSaved” obtained from the previous step:

[Then(@"the saved project matches the inputs")]
public void ThenTheSavedProjectMatchesTheInputs()
{
     Assert.AreEqual(_projectTestModel.Name, _projectSaved.Name);
     Assert.AreEqual(_projectTestModel.Description, _projectSaved.Description);
     Assert.AreEqual(_projectTestModel.UserName, _projectSaved.UserName);
}

Other Scenarios

Other scenarios were set up to complete the testing of the Project API to test for all of the verbs (“get”, “put”, “post”, and “delete”) as well as testing for aspects such as invalid authorization or testing that users may not access or modify other user’s projects. These scenarios are defined in the following file: ProjectsApi.feature.

Other Testing Considerations

It’s important that the tests are run with a clean environment so that they don’t depend on other tests.  Therefore a “[BeforeScenario]” method is used to ensure that the projects are removed prior to each test, in the following file: DatabaseHelpers.cs.

Also to ensure that the web server is available for the test run, the IISExpress module is started when the tests are run via the “[SetUp]” and “[TearDown]” attributes on methods that start and shutdown IISExpress. This setup and teardown is found in the following file: Startup.cs.

The SpecFlow code should be set up in a separate project within the solution, also separate from unit tests.  This allows it to be omitted from some deployments. For example this is useful for AppHarbor deployments where these type of tests won’t run within the production environment.

Full Source code

The full source code for this project can be found at the ResearchLinks solution on GitHub and the code related to SpecFlow is contained in the ResearchLinks.SpecTests sub-project.

 

Hanselminutes Podcast: On Empathy with Leon Gersing the Ruby Buddha

Scott Hanselman recently published a really great podcast on his always-good Hanselminutes show, “On Empathy with Leon Gersing the Ruby Buddha”.  They discuss how important it is to maintain empathy when dealing with others on the Internet as well as in real life, and the importance of keeping a direct connection to your end customers and colleagues in your community. It should be required listening for those in the software industry.

Using SimpleBrowser with SpecFlow for BDD with ASP.NET MVC

The SpecFlow project provides a useful way to integrate BDD (Behavior Driven Development) testing into .NET projects using the Gherkin language. The main idea is that the project specs or user stories are written in user language and then are linked to actual tests that are automatically executed as the project is developed. There are several possible ways to implement this with ASP.NET MVC to automate the testing with the browser.

WatiN

Steve Sanderson wrote a nice article about applying SpecFlow with ASP.Net MVC.  In this case he used the WatiN tool to drive the tests through a browser. I implemented a similar testing setup on a project using SpecFlow and WatiN but found that driving an actual browser made the tests too slow.

HtmlUnit

A later article from Sanderson describes a way to use HtmlUnit for a “headless browser automation” approach to testing.  This approach is faster but requires using the IKVM method of linking Java within .NET. To ease this aspect of it there is a Nuget package called NHtmlUnit.  I did a small spike with NHtmlUnit but found it slower than I expected but faster than the WatiN approach.

SimpleBrowser

I found a project on GitHub called SimpleBrowser by Nathan Ridley which offers a headless browser testing approach written in directly in .NET. I found the interface to be easy to use and best of all the tests written with SimpleBrowser are very fast.

For example a typical SpecFlow scenario for user login:

    Feature: Log On
       In order to access the features of the website
       As a user
       I want to be able to log On.

    Scenario: Log On User
       Given I am on the Login Page
       When I enter my username and password
       And I click the Log On button
       Then I am on the Home Page Logged In

The tooling that SpecFlow provides for Visual Studio creates a method stub for the tests steps, which can then be filled in to use the SimpleBrowser methods. For example for the first step of being on the Registration page, after filling in the test method with the SimpleBrowser calls:

[Given(@"I am on the Login Page")]
public void GivenIAmOnTheLoginPage() {
     WebBrowser.Current.Navigate("http://localhost:51044/Account/LogOn");
     Assert.IsTrue(WebBrowser.Current.Find("h2", FindBy.Text, "Log On").Exists);
}

The method is linked to the scenario step via the attribute [Given(…)] and the body of the method uses the SimpleBrowser “Navigate” method to load the page.  Then the “Assert” tests that the SimpleBrowser has indeed loaded the log on page by finding an “h2” tag where its inner text is “Log On”.

The “WebBrowser.Current” is a static class that holds the SimpleClass browser instance within the SpecFlow ScenarioContext so that it can maintain state between steps, especially after a login:

[Binding]
public static class WebBrowser {
   public static Browser Current {
       get {
          if (!ScenarioContext.Current.ContainsKey("browser"))
             ScenarioContext.Current["browser"] = new Browser();
          return (Browser)ScenarioContext.Current["browser"];
       }
   }
}

The “new Browser();” is where the SimpleBrowser Browser class is created.

Steps such as clicking on the Log On button are easy to accomplish with the Click() method:

[When(@"I click the Log On button")]
public void WhenIClickTheLogOnButton() {
    WebBrowser.Current.Find("input", FindBy.Value, "Log On").Click();
}

There is also an overload for the Find() method that allows a shortcut if there is an “id” attribute within the html element. For example if there is are “id” elements with UserName and Password for those input elements, then the step for filling in the form fields is simple:

[When(@"I enter my username and password")]
public void WhenIEnterMyUsernameAndPassword() {
    WebBrowser.Current.Find("UserName").Value = "user";
    WebBrowser.Current.Find("Password").Value = "password";
}

Conclusion

I found using the SimpleBrowser easy to use and capable for most testing required for BDD testing with a “headless” browser. The resulting tests run very fast and aren’t fragile to minor changes in the HTML. The only limitation is that it doesn’t support Javascript but test that require Javascript can be done using WatiN or Selenium as part of automated integration tests rather than BDD.

JQuery UI Autocomplete and MVC3 Remote Validation Conflict–Update

I previously posted about a fix to a problem when the JQuery UI Autocomplete doesn’t play well with the ASP.Net MVC3 Remote validation. Part of the solution included a way to ensure that the remote validation isn’t fired for each key click or change of focus in the text box.

The method for doing this is to change the settings of the validation to not fire onkeyup or onfocusout, but to get there the validator settings must be obtained from the form in question.  The following snippet was given to grab the settings (do not use this method):

var validatorSettings = $.data($('form')[0], 'validator')

The problem is that this method of getting the settings will not work correctly if a new form is inserted before the form in question, because that will case the original form to have a counter of [1] and the code will no longer work. Better to use the following method to get the form by named id:

var validatorSettings = $('#searchForm').validate().settings;

Here’s how it looks in the whole snippet of Javascript:

<script type="text/javascript">
    window.onload = function () {
        var validatorSettings = $('#searchForm').validate().settings;
        validatorSettings.onkeyup = false;
        validatorSettings.onfocusout = false;
    }
</script>

Then the form can be given an id so that JQuery will select the correct form:

@using (Html.BeginForm("Index", "Services", FormMethod.Get, new { id = "searchForm" })) {

For the full code refer to the previous article (where this issue has been corrected).

Remembering Steve Jobs

jobs_billboard_different

Steve brought a lot of greatness to the world. I remember buying my first Apple computer back in early ‘82.  It was an Apple II-Plus and I remember how cool it was that it did color graphics with a TV output. My brother and I were playing the Swashbuckler game right after we got it out of the box. It was also fun and easy to program in Applesoft Basic. Then along came the Apple IIc which was small and easy to haul around, although it wasn’t a true laptop. I then got distracted by the “Amiga” computer and didn’t buy another Apple product for a while but we bought an iPad last year and have really enjoyed it.

He was great in that he stuck to his principles went against the conventional wisdom again and again (Apple Store, iTunes, iPad, etc).  He listened to his own inner voice and vision, and turned a company that was on the ropes into the leading technology company.

He was great in his emphasis on design and taste. His lessons on minimalism in design and functionality should be an inspiration to us all. The modern Apple machines are well designed, well built, and more like easy-t0-use, instant-on appliances rather than complicated computers that take forever to start. The whole concept of knowing what to leave out and keeping it simple are great design principles that Steve used to create products that are easy to use and understand.

Thanks Steve, you were insanely great.

JQuery UI Autocomplete and MVC3 Remote Validation Conflict

On a recent project I had a great deal of trouble to get JQuery UI Autocomplete and ASP.Net MVC3 Remote Validation to play nicely with each other. The goal was to have a type-in for selecting a city for a search in which the pull-down would auto-complete based on the available cities in the database:

Autocomplete in action.

Once a city is selected from the autocomplete it should do a validation as to whether the city is populated with actual data in the database (in case the user types in an invalid city:

Validation for missing city.

This is accomplished using the MVC 3 remote validation which makes it easy to do by adding an annotation to the ViewModel to indicate that the attribute will be remotely validated:

    public class SearchFormViewModel {
        ...
        [Remote("IsCityAvailable","Listings",ErrorMessage="Selected city has no listings, please reselect.")]
        public string City { get; set; }
    }

This of course requires an “IsCityAvailable” action on the “Listings” controller that will return false if there are no database entries for the given city:

     //Check that a city exists on the search selector.
     public JsonResult IsCityAvailable(string city) {
            City findCity = cityRepository.FindByCityName(city);
            if (findCity == null) {
                return Json(false, JsonRequestBehavior.AllowGet);
            } else {
                return Json(true, JsonRequestBehavior.AllowGet);
            }
     }

Conflict with Autocomplete

The problem comes in when the user types in a part of the city name and then selects from the drop-down autocomplete, it causes the remote validation to fire but it only includes the text that was typed, e.g. “A” rather than the selected drop-down text.  This causes the validation to fail when it should indicate success.

This has to do with the way the JQuery validation fires based on key-up and blur events. Researching the web shows that there are ways to turn this part off, but it is complicated by the layer that MVC3 puts on top of the JQuery validation.

Solution

The solution was to add some Javascript to the partial view that defined the search inputs so that the “onkeyup” and “onfocusout” settings are set to false. This is done in the “window.onload” so that it they are turned off early enough in the process:

<script type="text/javascript">
    window.onload = function () {
        var validatorSettings = $('#searchForm').validate().settings;
        validatorSettings.onkeyup = false;
        validatorSettings.onfocusout = false;
    }
</script>

Then a JQuery handler is added to the Search button click event so that the validate is forced when the search button is pressed (also works when the form is submitted via a return):

    $("#searchSubmit").click(function (event) {
        $("#searchForm").validate().element("input#City");
    });

Clipboard Printer App

Sometimes you might want to print a small section from an email that has 30-embedded replies or just a snippet of code from that big class file. The Clipboard Printer Windows app makes it easy to do by copying what you want to print into the clipboard (CTL-C or right-mouse “Copy”) and then print it to your printer.

I built this small app for this purpose a couple of years ago and thought I’d share it here in case someone else needed to use it. It’s simple to use:

  • Copy the text you want to print to the clipboard by highlighting it and using CTL-C or right-mouse “Copy”. clipboard_printer_icon
  • Start the Clipboard Printer app by clicking on the icon:
  • Then optionally verify what’s in the clipboard by clicking “Preview” and then click “Print” to send it to the printer:

clipboard_printer

To install the app download the installer MSI file:

ClipboardPrinterSetup.msi

The source code is also available here:

Clipboard Printer Source at Github

User Initialization in Code First/Altairis

In a previous post I showed how Entity Framework Code First ORM could be integrated with the Altairis Web Security simple membership provider to create a simple way to add a membership provider with an application using the EF 4.1 framework. One of the issues is that when the database is regenerated during development the users would have to be manually re-registered.  This is a hassle if you want to create an initial admin account or user account for testing.

RWBrad asked in the comments if there was a way to seed an initial user in the DBInitializer routine. I did some experimenting with the Seed method and found that it can be done by calling the membership provider directly to create a new user and then adding the appropriate roles via the EF context as shown below:

// Create a user.
MembershipCreateStatus status = new MembershipCreateStatus();
Membership.CreateUser("admin", "password", "admin@user.com");
if (status == MembershipCreateStatus.Success) {
    // Add the role.
    User admin = context.Users.Find("admin");
    Role adminRole = context.Roles.Find("Administrator");
    admin.Roles = new List<Role>();
    admin.Roles.Add(adminRole);
}

Then Adam Nagle then showed that the user can also be created more directly by the context when it’s preferred to keep the data access independent of the provider assembly.

These ideas make this concept more useful by allowing the seeding of initial users without having to go to SQL to add the admin role.

The example ASP.Net MVC3 application has been updated with these changes and is available for download at Github: Download Code