Steve Michelotti

A .NET Developer's Toolbox

  Home  |   Contact  |   Syndication    |   Login
  175 Posts | 0 Stories | 935 Comments | 51 Trackbacks

News

View Steve Michelotti's profile on LinkedIn

profile for Steve Michelotti at Stack Overflow, Q&A for professional and enthusiast programmers




Google My Blog

What I'm Reading:

Shelfari: Book reviews on your book blog

Tag Cloud


Archives

Post Categories

Code

Publications

Friday, December 02, 2011 #

My newest course was published yesterday on Pluralsight on KnockoutJS. The course can be viewed here. It is divided up into 4 modules. The first module gives an introduction to Knockout and shows a “Beyond Hello World” demo. The second module discusses the different types of observables you have in Knockout and demos of each. The third module focus on bindings including templating and custom bindings. The fourth module brings everything together with data features while shows a few more advanced techniques. The following is the description of the course:

As web applications become richer and more interactive, a better client-side experience is essential and expected by the user. KnockoutJS is a JavaScript MVVM framework that provides developers with a robust toolset including declarative bindings, dependency tracking, and advanced templating. In addition to all the powerful tools that are built-in, the extensibility of KnockoutJS is what allows you to take your applications to the next level. Whether you’re building a desktop browser application or a mobile application, KnockoutJS enables you to take full advantage of HTML5 and JavaScript while working in any mainstream browser.

Go check it out!

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Monday, November 14, 2011 #

Thanks to everyone who attending my session on MVC Scaffolding at the CMAP Code Camp this past weekend. PowerPoint and all code samples can be downloaded here.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Tuesday, October 11, 2011 #

KnockoutJS is an awesome MVVM JavaScript data binding framework for building rich user experiences. As sites get more interactive and more presentation logic gets pushed to the client-side, it’s important to have rich frameworks which enable these scenarios. The next version of MVC is going to include the Knockout NuGet package in the box. Now is a perfect time to start learning Knockout.

As I’ve been learning Knockout, I’ve been pleased to discover that, although it comes with a rich set of features built-in, one of the best aspects of Knockout is the extensibility. When there is a behavior you need that doesn’t match the out of the box capabilities of Knockout it’s easy to customize. Typically this takes the form of building your own custom binding. Let’s take an example.

A typical Knockout scenario is when you have a text box which is used to add an item to a list. From the jsFiddle below you the see the JavaScript and HTML for this are very straight-forward. If you click the “Result” tab, you will see that any item you type in the text box will be added to the list when you click the “Add” button:

 

Direct link to the jsFiddle.

 

This is all well and good but it would be more convenient for the user if they did not have to pick up their mouse to click the Add button for each item – but instead were able to just hit the Enter key to add the item. This can be done with relative ease by using the event binding (in conjunction with the keypress event) that comes with Knockout as shown in the next jsFiddle:

 

Direct link to the jsFiddle.

 

As you can see in the JavaScript above, the addOnEnter function checks the charCode of 13 (i.e., the Enter key) and invokes the addItem() function for this scenario.

We now have the behavior we want. However, the problem here is that my addOnEnter function() is not a re-usable solution at all because the call to the specific addItem function is directly embedded inside. If we have another text box that should add to another collection, we can’t use the above solution without some copy/paste ugliness replacing the 1-line of code to call the appropriate “add” function. Fortunately, the re-usability problem can be solved easily be created your own custom binding. Basically what we’re after is the ability to have our own binding called “executeOnEnter” which automatically checks the Enter key press and provides the ability to specify the function that should be called. In other words, we’d like to declaratively be able to specify this:

   1:  <input type="text" data-bind="value: itemToAdd, valueUpdate: 'afterkeydown', executeOnEnter: addItem" />

In order to do this, we have to write our own custom binding for executeOnEnter which is shown in the following jsFiddle:

 

Direct link to the jsFiddle.

 

The key thing to notice is that we are passing in the reference to the function that we want to be executed. This happens automatically via the “allBindingsAccessor” variable that is available for all custom bindings. However, instead of invoking the function directly, I use the JavaScript call() function and pass in the viewModel (conveniently, the viewModel is another parameter that is automatically available for all custom bindings). In JavaScript, the call() method assigns the this pointer for the specific method invocation. If we didn’t do this, this addItem() method wouldn’t work properly because the this pointer would be in the context of the custom binding rather than the context of the view model. It would force us to have to write our addItem() method like this:

   1:  addItem: function() {
   2:      viewModel.items.push({ name: viewModel.itemToAdd() });
   3:      viewModel.itemToAdd("");
   4:  } 

rather than like this (much preferred):

   1:  addItem: function() {
   2:      this.items.push({ name: this.itemToAdd() });
   3:      this.itemToAdd("");
   4:  } 

 

This is just the tip of the iceberg for the types of things you can do with custom bindings with Knockout!

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Monday, August 22, 2011 #

I recently had the pleasure of creating a course for Pluralsight on MVC Scaffolding. For the next 24-hours the course will be completely free! Click here to view the course now.

I’ve divided the course up into three modules. In the first module, I cover everything you need to know to be quickly productive with MVC Scaffolding. This includes mastering the command line, understanding one-to-many relationships, and scaffolding Actions and Unit Tests.

In the second module, I do a deep dive on customizing MVC Scaffolding. In my opinion, this is really the sweet spot for MVC Scaffolding. I always say, if you don’t like the output Scaffolding produces in some area, change it! The beauty of MVC Scaffolding is that it was built on top of T4Scaffolding with true extensibility in mind. In this module, I show how to customize view and controller templates as well as taking a deeper dive on understanding Scaffolders, how they function, and what they do.

In the third module, I deep dive on building your own custom scaffolders. In fact, to emphasize the extensibility, I build a custom scaffolder *outside* the context of MVC. Instead, I build a custom scaffolder for the WCF Web API where I essentially show how I built Web API Scaffolding on CodePlex. In this module, I show not only the basics of creating your own custom scaffolder, but also how to leverage the built-in T4 Scaffolders and built-in T4 Commandlets to build a multi-file scaffolder. I also show how you package your custom scaffolder into a NuGet package for easy distribution.

Enjoy!

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Sunday, August 21, 2011 #

I was recently asked to review Studio for Wijmo MVC by Component One and, overall, I am impressed. There are 2 major components of this. The first is Wijmo Complete which is a collection of over 30 UI widgets (very similar to jQuery UI). The second is Wijmo Scaffolding for MVC which builds upon the scaffolding that was released as part of the MVC 3 Tools Update (note: is does *not* build on top of powershell-based MVC Scaffolding which Microsoft released earlier this year).

Some of the Wijmo widgets have corresponding widgets in jQuery UI – the idea is for them to *extend* jQuery UI. For example:

In addition to these widgets, Wijmo contains several pretty cool widgets that have some functionality that you don’t get out of the box with jQuery UI. For example, the Wijmo Charts are stunning and really enable a rich experience with minimal implementation required.

wijmochart

 

Also, the Menu widget is very rich and highly customizable.

wijmomenu

 

The Wijmo Grid is another widget that is extremely impressive and is on par with jqGrid. These rich widgets like the Chart, Menu, Grid, etc. are where Wijmo really shines. Although Wijmo does offer some widgets that are similar to what you can find in other libraries like jQuery UI, the fact that they bundle all of them together and add several widgets that you cannot find in jQuery UI make it quite compelling. Additionally, the Wijmo Documentation is comprehensive as well.

When MVC first came out, many Microsoft control vendors went down the path of trying to create MVC Helpers for complex controls that were for C# centric. This often led to an awkward API that didn’t feel right in web development. Fortunately, Component One did not take this path with Wijmo MVC – instead the widgets follow the typical jQuery API so could be used outside the context of MVC. However, they do add some niceties that integrate nicely with some MVC concepts (e.g., Data Annotation metadata on view models) so that if you *are* using MVC, you get some nice value adds.

Wijmo Scaffolding for MVC

The Wijmo Scaffolding is a nice feature for quickly getting up and running with Wijmo controls but there were a couple of aspects that fell a little short of my expectations overall. When I first heard about Wijmo Scaffolding I was initially very excited because I thought it was integrated with PowelShell-based MVC Scaffolding. However, that is not the case. Specifically, Wijmo Scaffolding comes with some replacement T4 templates for the templates that work with the MVC 3 Tools Update scaffolding dialog (i.e., the new “Add Controller” dialog). The differences between the Wijmo templates and the default templates are not earth shattering. The primary differences are:

  • Wijmo adds additional CSS styles to support the Wijmo styles
  • Wijmo templates work with the 3 Editor Templates that ship with Wijmo Scaffolding
  • Wijmo templates do *not* take into account one-to-many relationships

Let’s take an example walkthrough for building something with Wijmo Scaffolding. Consider view models that look like this:

   1:  public class Task
   2:  {
   3:      public int Id { get; set; }
   4:   
   5:      [Required]
   6:      public string Name { get; set; }
   7:   
   8:      [DisplayName("Due Date")]
   9:      [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:d}")]
  10:      public DateTime? DueDate { get; set; }
  11:   
  12:      public int StatusId { get; set; }
  13:      public virtual Status Status { get; set; }
  14:   
  15:      [StringLength(100)]
  16:      public string Notes { get; set; }
  17:  }
  18:   
  19:  public class Status
  20:  {
  21:      public int Id { get; set; }
  22:      public string Name { get; set; }
  23:  }

 

Notice there is a typical one-to-many relationship between Status and Task. After going through the standard “Add Controller” dialog box with Wijmo scaffolding, the resulting “Create” screen looks like this:

wijmoCreate

I’ve got nice looking styles and the date field conveniently gets the Wijmo Input Date widget. However, the foreign key to StatusId is not taken into account automatically as it would be with traditional MVC Scaffolding. This would be a great enhancement for Component One to make.

After adding a few items, the List view, which gets scaffolded using the Wijmo grid widget, looks like this:

wijmoGrid

 

There’s automatic sorting/paging and the styles look nice as well (though we have the same pesky problem with the foreign key on StatusId). However, when I sorted by the “Name” column, although the alphabetical sort worked great, the visual styles were lost:

wijmoGrid

 

This may be just a minor bug but I did not dig into trying to debug it.

Wijmo MVC comes with 3 Editor templates:

  • DateTime – which uses the Wijmo Input Date widget
  • Decimal – which uses the Wijmo Input Number widget based on Data Annotations [Range] attribute
  • IntSlider – which uses the Wijmo Int Slider widget also taking into account the Data Annotations [Range] attributes. Note: since this editor is not named for the Integer data type, it is meant to be used by invoking a [UIHint].

These editor templates all do the intended job nicely. However, as a small nitpick, I’d probably choose to change the implementation slightly. The DateTime editor looks like this:

   1:  @inherits System.Web.Mvc.WebViewPage<System.DateTime?>
   2:  @if (Model.HasValue)
   3:  { 
   4:      @Html.TextBox("", (Model.Value), new { @class = "datePicker" })
   5:  }
   6:  else {
   7:      @Html.TextBox("", "", new { @class = "datePicker" })
   8:      
   9:  }
  10:  <script type='text/javascript'>
  11:      $(document).ready(function () {
  12:          $("#@ViewData.TemplateInfo.GetFullHtmlFieldId("")").wijinputdate({ showTrigger: true});
  13:      });
  14:  </script>

 

Since the wijinputdate() widget is applied directly the the element itself (as seen on line #12), it means that you’ll have a snippet of jQuery like this interspersed throughout your markup for *every* DateTime on your page:

   1:  <script type='text/javascript'>
   2:      $(document).ready(function () {
   3:          $("#DueDate").wijinputdate({ showTrigger: true});
   4:      });
   5:  </script>

 

My preference is that they take a more “unobtrusive” approach. For example, since they are already adding a class=”datePicker” to the text box, all we’d need to do is to add 1 line of jQuery to the page that would take care of *all* of these like this:

   1:  <script type="text/javascript">
   2:      $(function () {
   3:          $(".datePicker").wijinputdate({ showTrigger: true });
   4:      });
   5:  </script>

So rather than having multiple jQuery calls through the page for this – it’s just one (i.e., any element with a class of “datePicker”). This would also make the payload sent to the browser smaller as well. But again, this is a small nitpick.

 

Conclusion

Overall, I was very impressed with Wijmo MVC and I think it is a compelling option for any developer building rich MVC applications. Although the widgets can be used for any jQuery solution, the integration with MVC is a nicety that makes things more seamless. In my opinion, the sweet spot for Wijmo are the incredibly rich widgets such as the charts, graphs, menus, and grids. My constructive suggestions are that I’d like to see Component One extend the scaffolding support by supporting the integration with the Powershell-based MVC Scaffolding. At the same time, it would not be difficult to add support for foreign keys of one-to-many relationships – this would also enable Repository support that MVC Scaffolding provides as well. Overall, if you’re looking for a cohesive suite of UI widgets for your MVC application, I’d definitely recommend checking out Studio for Wijmo MVC.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Thursday, July 14, 2011 #

MvcScaffolding is a tremendous productivity improvement for MVC developers. Earlier this year, Steve Sanderson posted the definitive 7-part series on MvcScaffolding which is a must-read for anyone serious about doing scaffolding. The best part about the scaffolding infrastructure is that MvcScaffolding is actually built on top of another package called T4Scaffolding. T4Scaffolding can be used as the basis for *any* scaffolding – not just MVC projects. To that end, we can enjoy the same power of MvcScaffolding in non-MVC projects like the WCF Web API.

Recently I did a post that showed how easy it was to get up and running with Web API by leveraging NuGet. This consisted of a NuGet package which added the appropriate references and provided starter code for a basic HTTP CRUD service (I included a 6-minute screencast showing it in action). However, there are several aspects of the NuGet-only approach that are not ideal:

  • State was held by a static in-memory dictionary which, while good for a demo, you have to replace.
  • It created a dummy “MyModelType” class where you had to then rely on Visual Studio refactoring tools to perform a “rename” operation everywhere.
  • You have to manually move the model type to its own code file.
  • You have to manually rename the Service class.
  • You have to manually specify the route you want.
  • It only created a single service – so if you want to create a second service, it was a copy/paste exercise.

By leveraging T4Scaffolding, we can address all of these issues. I’ll start with the end result and then discuss the implementation.

Web API Scaffolding

I have created a NuGet package called WebApi.Scaffolding. You can start with the “Empty ASP.NET Web Application” project if you want to follow this step by step. The first step is to execute the install for this package:

PM> Install-Package WebApi.Scaffolding

This installs the package along with a few dependent NuGet packages (which I’ll discuss more later). Like MvcScaffolding, this doesn’t add any binary references to your project – instead it adds PowerShell commands to the Package Manager console. We can immediately scaffold our first Web API HTTP service:

PM> Scaffold WebApiService -ResourceName ContactResource -ServiceName ContactService -DbContextType ContactsDbContext

This results in 5 files being created at once:

webapi-solexpl

 

And just like that, all 6 of our “less than ideal” aspects from before are addressed. Let’s take a closer look at what was generated.

To get up and running quickly, I also highly recommend you install SQL Server Compact Edition:

PM> Install-Package EntityFramework.SqlServerCompact

MvcScaffolding revolves around the Model. The controller, data access, and views are generated from it. Web API Scaffolding works in a similar way. That is, we start with a resource (“ContactResource” in this example) and the service and data access is generated from it. The generated resource is very simple:

   1:  public class ContactResource
   2:  {
   3:      public int Id { get; set; }
   4:   
   5:      //TODO: Add other properties below
   6:  }

By convention it just has an Id and we can add in any other properties we want without affecting the service or data access. More importantly if you already have a type that you want to expose, you can just specify the existing type for the ModelResource and it will use that and will not overwrite the class.

The next thing is the service class:

   1:  [ServiceContract]
   2:  public class ContactService
   3:  {
   4:      private readonly IContactResourceRepository contactresourceRepository;
   5:   
   6:      // If you are using Dependency Injection, you can delete the following constructor
   7:      public ContactService () : this(new ContactResourceRepository()) 
   8:      {
   9:      }
  10:   
  11:      public ContactService (IContactResourceRepository contactresourceRepository) 
  12:      {
  13:          this.contactresourceRepository = contactresourceRepository;
  14:      }
  15:   
  16:      [WebGet(UriTemplate = "{id}")]
  17:      public HttpResponseMessage<ContactResource> Get(int id)
  18:      {
  19:          var item = this.contactresourceRepository.Find(id);
  20:          if (item == null)
  21:          {
  22:              var notFoundResponse = new HttpResponseMessage();
  23:              notFoundResponse.StatusCode = HttpStatusCode.NotFound;
  24:              notFoundResponse.Content = new StringContent("Item not found");
  25:              throw new HttpResponseException(notFoundResponse);
  26:          }
  27:          var response = new HttpResponseMessage<ContactResource>(item);
  28:   
  29:          // set it to expire in 5 minutes
  30:          response.Content.Headers.Expires = new DateTimeOffset(DateTime.Now.AddSeconds(30));
  31:          return response;
  32:      }
  33:   
  34:      [WebInvoke(UriTemplate = "", Method = "POST")]
  35:      public HttpResponseMessage<ContactResource> Post(ContactResource item)
  36:      {
  37:          this.contactresourceRepository.InsertOrUpdate(item);
  38:          this.contactresourceRepository.Save();
  39:   
  40:          var response = new HttpResponseMessage<ContactResource>(item);
  41:          response.StatusCode = HttpStatusCode.Created;
  42:          response.Headers.Location = new Uri("Contacts/" + item.Id, UriKind.Relative);
  43:          return response;
  44:      }
  45:   
  46:      [WebInvoke(UriTemplate = "{id}", Method = "PUT")]
  47:      public ContactResource Put(int id, ContactResource item)
  48:      {
  49:          this.contactresourceRepository.InsertOrUpdate(item);
  50:          this.contactresourceRepository.Save();
  51:          return item;
  52:      }
  53:   
  54:      [WebInvoke(UriTemplate = "{id}", Method = "DELETE")]
  55:      public HttpResponseMessage Delete(int id)
  56:      {
  57:          this.contactresourceRepository.Delete(id);
  58:          this.contactresourceRepository.Save();
  59:          return new HttpResponseMessage(HttpStatusCode.NoContent, "No Content");
  60:      }
  61:   
  62:  }

Notice how it’s using a repository for data access rather than an in-memory static dictionary. This repository encapsulates an Entity Framework 4.1 (Code First) data context. All this is made possible because T4Scaffolding makes this available out of the box.  Finally, we have the ContactServiceStart.cs file:

   1:  using System;
   2:  using System.Web.Routing;
   3:  using Microsoft.ApplicationServer.Http.Activation;
   4:  using Microsoft.ApplicationServer.Http.Description;
   5:   
   6:  [assembly: WebActivator.PreApplicationStartMethod(typeof(WebApiScaffoldingDemo.App_Start.ContactServiceStart), "Start")]
   7:   
   8:  namespace WebApiScaffoldingDemo.App_Start {
   9:      public static class ContactServiceStart {
  10:          public static void Start() {
  11:              RouteTable.Routes.MapServiceRoute<ContactService>("contacts");
  12:          }
  13:      }
  14:  }

Notice that we are using the WebActivator library which automatically invokes our initialization code during application start up for an ASP.NET application. Also notice that the route of “contacts” was created automatically by pluralizing the model type (and removing the word “Resource” from the end). All of this was generated automatically with no need to customize. Additionally, if we want to create another service, we just scaffold again – no copy/paste required.

One thing you might have noticed in the service code above, is that there are 2 constructors and line #6 has the comment stating that you can remove the one with the default constructor if you’re using Dependency Injection with an IoC container. Fortunately, this is now easily supported in the WCF Web API. But if I know that I use IoC for my entire application, I don’t want to have to delete the default constructor every single time. Wouldn’t it be nice if I could tell the Scaffolder that I’m using IoC? The good news is that you can:

PM> Scaffold WebApiService -ResourceName ContactResource -ServiceName ContactService -DbContextType ContactsDbContext -UseIoC -Force

There are two things to notice here. First, I’ve added a –Force switch here because by default it will not overwrite the files that Scaffolding has already created unless you explicitly indicate that it should. Second, I’ve added a –UseIoC switch on the end. This tells the code to generate the service without a default constructor and well as change the initialization code in the ContactServiceStart class. Now the initialization code looks like this:

   1:  [assembly: WebActivator.PreApplicationStartMethod(typeof(WebApiScaffoldingDemo.App_Start.ContactServiceStart), "Start")]
   2:   
   3:  namespace WebApiScaffoldingDemo.App_Start {
   4:      public static class ContactServiceStart {
   5:          public static void Start() {
   6:              var iocContainer = IoC.Initialize();
   7:              var config = HttpHostConfiguration.Create()
   8:                  .SetResourceFactory(new IoCResourceFactory(iocContainer));
   9:              RouteTable.Routes.MapServiceRoute<ContactService>("contacts", config);
  10:          }
  11:      }
  12:  }

The Web API Scaffolder has generated the code necessary to use IoC. It has also included two more files in a new folder called DependencyResolution:

WebApiScaffold-solexpl-depres

 

These files include the initialization of the IoC container as well as a Web API Resource Factory that uses it. The Web API Scaffolder has a dependency on StructureMap so the StructureMap NuGet package is a dependency that is automatically added when you add the WebApi.Scaffolding NuGet package. Of course, you can always replace this with your IoC of choice.

 

Building Web API Scaffolding

Now that we’ve seen what WebApi.Scaffolding does, let’s look closer into how it does it. The structure of the solution for WebApi.Scaffolding looks like this:

WebApiScaffold-nuget-solexpl

The heart of the scaffolding solution is the WebApiService.ps1 file. This is the PowerShell commandlet that is invoked by the scaffolding commands that are executed from the console. The first part of this commandlet is the declaration:

   1:  [T4Scaffolding.Scaffolder(Description = "This Scaffolder create a WCF Web API service")][CmdletBinding()]
   2:  param(        
   3:      [parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)][string]$ServiceName,
   4:      [parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)][string]$ResourceName,
   5:      [string]$DbContextType,
   6:      [string]$Project,
   7:      [string]$CodeLanguage,
   8:      [string[]]$TemplateFolders,
   9:      [switch]$Force = $false,
  10:      [switch]$UseIoC = $false
  11:  )

 

You can see the parameters I used earlier (i.e., ResourceName and ServiceName) as well as the switches (i.e., Force and UseIoC). The next thing do is to utilize the Add-ProjectItemViaTemplate commandlet that comes with T4Scaffolding:

   1:  Add-ProjectItemViaTemplate "Resources\$ResourceName" -Template WebApiResourceTemplate `
   2:      -Model @{ Namespace = $namespace; ResourceName = $ResourceName } `
   3:      -SuccessMessage "Added WebApiService output at {0}" `
   4:      -TemplateFolders $TemplateFolders -Project $Project -CodeLanguage $CodeLanguage -Force:$false

 

This commandlet really does some heavy lifting for us by invoking the T4 template specified (WebApiResourceTemplate) and adding the result to our Visual Studio solution at the location specified. The other thing to notice is the –Model parameter that I am passing which consists of 2 properties (Namespace and ResourceName) that I am dynamically specifying. This allows me to use these properties in my T4 template as shown on line #8 and #10:

   1:  <#@ Template Language="C#" HostSpecific="True" Inherits="DynamicTransform" #>
   2:  <#@ Output Extension="cs" #>
   3:  using System;
   4:  using System.Collections.Generic;
   5:  using System.Linq;
   6:  using System.Web;
   7:   
   8:  namespace <#= Model.Namespace #>.Resources
   9:  { 
  10:      public class <#= Model.ResourceName #>
  11:      {
  12:          public int Id { get; set; }
  13:   
  14:          //TODO: Add other properties below
  15:      }
  16:  }

 

I can add my template for the Service class in a similar way. Next, I create the repository by leveraging the repository scaffolder that comes with T4Scaffolding:

   1:  Scaffold Repository -ModelType $ResourceName -DbContextType $DbContextType -Project $Project -CodeLanguage $CodeLanguage -Force:$Force -BlockUi

This command not only creates the repository for me but also the Entity Framework DbContext – this all comes built-in with T4Scaffolding!

The next thing I want to do is to create my initialization code. You’ll recall it created a route for me like this:

   1:  RouteTable.Routes.MapServiceRoute<ContactService>("contacts");

 

We specified “ContactResource” for the –ResourceType but I don’t want the word “Resource” in my route and I also want the pluralized word for the URI. Once again, T4Scaffolding comes in handy because it comes with a commandlet called Get-PluralizedWord which we can use like this:

   1:  $route = Get-PluralizedWord $ResourceName.Replace("Resource", "").ToLower()
   2:  $appStartName = "App_Start\$ServiceName" + "Start"
   3:  Add-ProjectItemViaTemplate $appStartName -Template WebApiAppStartTemplate `
   4:      -Model @{ 
   5:          Namespace = $namespace; 
   6:          ServiceName = $ServiceName; 
   7:          ServiceRoute = $route;
   8:          UseIoC = [Boolean]$UseIoC;
   9:      } -SuccessMessage "Added WebApiService output at {0}" `
  10:      -TemplateFolders $TemplateFolders -Project $Project -CodeLanguage $CodeLanguage -Force:$Force

 

The $route variable on line #1 now is “contacts” which gets passed into the T4 template for the ServiceRoute on line #7.

Finally, I have the conditional IF statement that determines whether or not to add the DependencyResolution infrastructure depending on if the –UseIoC switch was specified:

   1:  if ($UseIoC) {
   2:      Add-ProjectItemViaTemplate "DependencyResolution\IoCResourceFactory" -Template WebApiIoCResourceFactoryTemplate `
   3:          -Model @{ 
   4:              Namespace = $namespace; 
   5:          } -SuccessMessage "Added WebApiService output at {0}" `
   6:          -TemplateFolders $TemplateFolders -Project $Project -CodeLanguage $CodeLanguage -Force:$Force
   7:   
   8:      Add-ProjectItemViaTemplate "DependencyResolution\IoC" -Template WebApiIoCTemplate `
   9:          -Model @{ 
  10:              Namespace = $namespace; 
  11:          } -SuccessMessage "Added WebApiService output at {0}" `
  12:          -TemplateFolders $TemplateFolders -Project $Project -CodeLanguage $CodeLanguage -Force:$Force
  13:  }

 

Customizing Web API Scaffolding

Up to this point we’ve seen what Web API Scaffolding does and how it gets built. But what if you want to customize it in your own project? For example, let’s say you know that you always use a certain Media Type Formatter and you want the initialization code to always be generated to specify your media type formatter. For example, let’s say I want to use HAL for my media type and I have a HalMediaTypeFormatter (described here in a previous post). All you have to do is to run this command in your project:

PM> Scaffold CustomTemplate WebApiService WebApiAppStartTemplate

This will create a “CodeTemplates” folder in your solution for the WebApiService Scaffolder with the WebApiAppStartTemplate:

webapi-custempl

 

You can then modify the T4 template for WebApiAppStartTemplate to add the formatter as you see on line #8 below:

   1:  namespace <#= Model.Namespace #>.App_Start {
   2:      public static class <#= Model.ServiceName #>Start {
   3:          public static void Start() {
   4:  <# if (Model.UseIoC) { #>
   5:              var iocContainer = IoC.Initialize();
   6:              var config = HttpHostConfiguration.Create()
   7:                  .SetResourceFactory(new IoCResourceFactory(iocContainer))
   8:                  .AddFormatters(new HalMediaTypeFormatter());
   9:              RouteTable.Routes.MapServiceRoute<<#= Model.ServiceName #>>("<#= Model.ServiceRoute #>", config);
  10:  <# } else { #>
  11:              RouteTable.Routes.MapServiceRoute<<#= Model.ServiceName #>>("<#= Model.ServiceRoute #>");
  12:  <# } #>
  13:          }
  14:      }
  15:  }

 

Next time you run the Scaffold WebApiService… command, it will automatically pick up the changes in your locally customized T4 template.

T4Scaffolding gives you a HUGE amount of power and control when building your own solutions. It is well worth your time to familiarize yourself with the tools available to you and you will be amazed to find new ways to increase your productivity that you hadn’t before thought of. The sky is the limit for the different types of “recipes” you can create for yourself.

The WebApi.Scaffolding package is available on NuGet. The complete source code can be found on CodePlex.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Thanks to everyone who attended my presentation last night at TriNUG. The code samples as PowerPoint can be downloaded here.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Monday, June 06, 2011 #

In a previous post, I talked about how to build your own custom Media Type Formatter with the WCF Web API. In this post, I used HAL as the media type to expose an API for Nerd Dinner. There are a core set of guiding principles to building RESTful services and one of those principles is that documentation efforts for a service should be focused on defining the media type(s) and link relations that the service uses. While it’s important to have a consistent pattern for URI design, it’s really not that important in comparison to defining the link relations because clients should just “follow the links” and not have tight coupling to URI’s (i.e., clients shouldn’t have knowledge of what the URI’s look like).

Let’s take the example HAL response that returned a dinner resource in my last post:

   1:  <resource rel="self" href="http://localhost:1700/dinners/1">
   2:    <link rel="http://localhost:1700/rels/rsvps" href="http://localhost:1700/dinners/1/rsvps" />
   3:    <link rel="http://localhost:1700/rels/update-dinner" href="http://localhost:1700/dinners/1" />
   4:    <link rel="http://localhost:1700/rels/delete-dinner" href="http://localhost:1700/dinners/1" />
   5:    <DinnerId>1</DinnerId>
   6:    <Title>MVC Dinner</Title>
   7:    <Description>This dinner will be for MVC developers.</Description>
   8:    <Address>123 Main Street</Address>
   9:    <Country>USA</Country>
  10:    <EventDate>7/1/2011 12:00:00 AM</EventDate>
  11:  </resource>

The hypermedia shown on lines 2-4 have link relations in URI format (ignore the ugly “localhost:1700” and imagine this was something like “http://nerddinner.com/rels/rsvps”). Since the rel attributes are already in URI format, a common convention is to actually provide the documentation for that link relation at that URI if someone hits that in a browser. This documentation page can contain information such as a human readable description of the purpose of the link relation, what media type should be used in the Accept header, which HTTP verb to use, the format of the resource messages, etc.

How can we produce this documentation when using the WCF Web API? The /help page that comes out of the box in WCF 4 won’t help us much here because that is much more in an RPC style with application/xml and application/json formats that are too generic to match our application’s media type. By leveraging the HAL media type formatter that I’ve previously built, I can use this to help document my link relations to produce a help page that looks like this (this page looks like the WCF /help page simply because I copied their CSS):

linkRelDocPage

 

There were several steps that went in to producing this page. First I defined a metadata object that I used for documentation purposes.

   1:  using System;
   2:  using System.Collections.Generic;
   3:   
   4:  namespace NerdDinnerWebApi.ResourceModel
   5:  {
   6:      public class LinkRelationMetadata
   7:      {
   8:          public LinkRelationMetadata()
   9:          {
  10:              this.HypermediaItems = new List<HypermediaMetadata>();
  11:          }
  12:   
  13:          public string Rel { get; set; }
  14:   
  15:          public string Description { get; set; }
  16:   
  17:          public string HttpMethod { get; set; }
  18:   
  19:          public string Schema { get; set; }
  20:   
  21:          public string Example { get; set; }
  22:   
  23:          public string MediaType { get; set; }
  24:   
  25:          public List<HypermediaMetadata> HypermediaItems { get; set; }
  26:      }
  27:  }

This will allow me to “write my documentation” like this:

   1:  linkRelations.AddItem(LinkRelationNames.Dinner, HttpMethod.Get, "Get a dinner resource for Nerd Dinner.", typeof(Dinner),
   2:      new HypermediaMetadata { Rel = LinkRelationNames.UpdateDinner, ConditionsDescription = "Always present as a resource." },
   3:      new HypermediaMetadata { Rel = LinkRelationNames.DeleteDinner, ConditionsDescription = "Always present as a resource." },
   4:      new HypermediaMetadata { Rel = LinkRelationNames.Rsvps, ConditionsDescription = "Always present as a resource." });

 

The AddItem() method above is the key. Specifically, its job is the instantiate an instance of the type and populate it with dummy values (e.g., “abc” for strings, 123 for integers, etc. This implementation is fairly rudimentary right now) – it does this on line #3 below. Then on line #4 it calls the ToHalRepresentation() method which internally leverages the HalMediaTypeFormatter (line #42) to create the example XML representation that will be shown on the screen.

 

   1:  private static void AddItem(this Dictionary<string, LinkRelationMetadata> dict, string rel, HttpMethod httpMethod, string description, Type responseMessageType, params HypermediaMetadata[] hypermedia)
   2:  {
   3:      var instance = PopulateInstance(responseMessageType);
   4:      var xml = ToHalRepresentation(instance);
   5:           
   6:      dict.Add(rel.Replace("http://localhost:1700/rels/", string.Empty), new LinkRelationMetadata { Rel = rel, HttpMethod = httpMethod.ToString(), MediaType = "application/vnd.nerddinner.hal+xml", Description = description, Example = xml, HypermediaItems = hypermedia.ToList() });
   7:  }
   8:   
   9:  private static object PopulateInstance(Type type)
  10:  {
  11:      var instance = Activator.CreateInstance(type) as HalResource;
  12:      if (instance == null)
  13:      {
  14:          return null;
  15:      }
  16:   
  17:      // First populate HAL-specific properties
  18:      instance.Rel = "self";
  19:      instance.HRef = "http://example.com/foo";
  20:   
  21:      instance.Links = new List<Link>
  22:      {
  23:          new Link { Rel = "abc", HRef = "http://example.com/abc" },
  24:          new Link { Rel = "xyz", HRef = "http://example.com/xyz" }
  25:      };
  26:   
  27:      foreach (var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty))
  28:      {
  29:          if (property.IsValueTypeOrString())
  30:          {
  31:              SetDummyValue(instance, property);
  32:          }
  33:      }
  34:   
  35:      return instance;
  36:  }
  37:   
  38:  private static string ToHalRepresentation(object instance)
  39:  {
  40:      var formatter = new HalMediaTypeFormatter();
  41:      var stream = new MemoryStream();
  42:      formatter.WriteToStream(instance.GetType(), instance, stream, null, null);
  43:      stream.Position = 0;
  44:      var xml = new StreamReader(stream).ReadToEnd();
  45:      return xml;
  46:  }
  47:   
  48:  private static void SetDummyValue(object instance, PropertyInfo property)
  49:  {
  50:      if (property.PropertyType == typeof(int))
  51:      {
  52:          instance.SetValue(property, 123);
  53:      }
  54:      else if (property.PropertyType == typeof(string))
  55:      {
  56:          instance.SetValue(property, "abc");
  57:      }
  58:      else if (property.PropertyType == typeof(DateTime))
  59:      {
  60:          instance.SetValue(property, DateTime.Now);
  61:      }
  62:      else
  63:      {
  64:          throw new InvalidOperationException("Unsupported type for setting a dummy value.");
  65:      }
  66:  }

 

At this point I’m just populating the dictionary that will be used for the service call which looks like this:

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Net;
   4:  using System.Net.Http;
   5:  using System.ServiceModel;
   6:  using System.ServiceModel.Web;
   7:  using Microsoft.ApplicationServer.Http;
   8:  using Microsoft.ApplicationServer.Http.Dispatcher;
   9:  using NerdDinnerWebApi.ResourceModel;
  10:   
  11:  namespace NerdDinnerWebApi.Services.Services
  12:  {
  13:      [ServiceContract]
  14:      public class LinkRelationService
  15:      {
  16:          static readonly Dictionary<string, LinkRelationMetadata> linkRelations = LinkRelationInitializer.Create();
  17:   
  18:          [WebGet(UriTemplate = "{rel}")]
  19:          public HttpResponseMessage<LinkRelationMetadata> Get(string rel)
  20:          {
  21:              LinkRelationMetadata linkRelation = null;
  22:              if (!linkRelations.TryGetValue(rel, out linkRelation))
  23:              {
  24:                  var notFoundResponse = new HttpResponseMessage();
  25:                  notFoundResponse.StatusCode = HttpStatusCode.NotFound;
  26:                  notFoundResponse.Content = new StringContent("Link Relation '" + rel + "' not found");
  27:                  throw new HttpResponseException(notFoundResponse);
  28:              }
  29:              return new HttpResponseMessage<LinkRelationMetadata>(linkRelation);
  30:          }
  31:      }
  32:  }

 

I would like to provide this data in an HTML format when a user agent such as a browser is requesting with an Accept header of “text/html”. To accomplish this, I’ll use my RazorHtmlMediaTypeFormatter which I blogged about here which utilizes Razor *outside* of MVC and *within* the WCF Web API to render this HTML resource:

   1:  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   2:  <html xmlns="http://www.w3.org/1999/xhtml">
   3:    <head>
   4:      <title>Link relation - @Model.Rel</title>
   5:      <style>{copied from WCF help page but omitted here for brevity}</style>
   6:    </head>
   7:    <body>
   8:      <div id="content">
   9:        <p class="heading1">Link relation - @Model.Rel</p> 
  10:        <p><b>Description: @Model.Description</b></p>
  11:        <table>
  12:          <tr>
  13:            <th>Item</th>
  14:            <th>Description</th>
  15:          </tr>
  16:          <tr>
  17:              <td>HTTP Method</td>
  18:              <td>@Model.HttpMethod</td>
  19:          </tr>
  20:          <tr>
  21:              <td>Media Type</td>
  22:              <td>@Model.MediaType</td>
  23:          </tr>
  24:          <tr>
  25:              <td>Potential Hypermedia</td>
  26:              <td>
  27:                  <table>
  28:                      @foreach (var item in @Model.HypermediaItems)
  29:                      {
  30:                          <tr>
  31:                              <td><a href="@item.Rel">@item.Rel</a></td>
  32:                              <td>@item.ConditionsDescription</td>
  33:                          </tr>
  34:                      }
  35:                  </table>
  36:              </td>
  37:          </tr>
  38:        </table>
  39:   
  40:        <p>
  41:          The following is an example response:
  42:          <pre class="response-xml">@FormatXmlForHtml(Model.Example)</pre>
  43:        </p>
  44:   
  45:        <p>
  46:          The following is the response Schema (XSD):
  47:          <pre class="response-xml">@FormatXmlForHtml(Model.Schema)</pre>
  48:        </p>
  49:      </div>
  50:    </body>
  51:  </html>

 

This gives me the HTML that is shown in the browser screen shot above. There might also be consumers who want to generate client side types based on the XML and XSD shown in the link relations doc. Screen scraping HTML is not the most user friendly thing for this. Therefore, if someone requests with an Accept header of “application/xml” we can also provide this same data in XML format just using built-in Web API functionality:

linkRelDocPageXml

 

This is just a prototype of early thinking. I am very curious to hear what other people think about this approach and how it could potentially be evolved.

The complete code sample for this can be downloaded here.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Media Type Formatters in the WCF Web API provide a way for the consumer of your service to not only specify the format they want for their response, but also specify the format they are using on their request. Typically the desired response format is specified in the “Accept” request header and the request body format is specified in the “Content-Type” request header. Media types are central to building any RESTful service. Two of the most common media types are “application/xml” and “application/json”. However, to build a truly RESTful service that is hypermedia driven, these media types should not be used. Instead, a media type that indicates the specifics of your application domain and has rich semantics for hypermedia is preferred.

REST is an architectural style that is governed by a guiding set of principles. While adhering to these principles, there is no one right way to do things. Recently, Darrel Miller turned me on the HAL (Hypermedia Application Language) which was created by Mike Kelly. I really like the well-structured style that HAL has – making it easy and flexible to embed hypermedia in your resources. Although HAL is an XML-based media type, it is not just “application/xml” because of the specific rules that govern its format. We *could* accomplish this format with some well placed attributes that control XML serialization but instead let’s create our own custom Media Type Formatter to create the format. Media Type Formatters expose OnWritetoStream() and OnReadFromStream() methods to allow serialization/deserialization. Quite often people think of media type formatters as only being used on the server. However, they can be used on the client side as well to control serialization/deserialization of the requests. The following diagram shows the process of an HTTP request/response and the role that the Media Type Formatter plays:

 

mediatypeformatterprocess

 

For my example, I’m going to use the Nerd Dinner domain since it’s something most people are familiar with. I could just use “application/hal” for my media type but instead I’m going to use “application/vnd.nerddinner.hal+xml” to more clearly indicate the specifics of my application’s domain (“vnd” indicates a vendor specific domain). One of the core tenets of REST services is loose coupling between the client and server which allows evolvability. Clients need to know about the bookmark URI (i.e., the “home page” so to speak) but should not have knowledge of any other URIs. Instead clients must understand the link relations (i.e., “rel” attributes of the <link> elements) and just “follow the links.”

If I request my well-known “bookmark URI”, to get a specific dinner, it would look like this:

 

nerddinnerxml

 

Notice I passed an Accept header of “application/vnd.nerddinner.hal+xml”. Also notice the three <link> elements that came back in my response – this is my hypermedia. The Link Relations are in URI format and the client must have knowledge of what these mean.

My Dinner class just looks like this:

   1:  public class Dinner : HalResource
   2:  {
   3:      public int DinnerId { get; set; }
   4:      public string Title { get; set; }
   5:      public string Description { get; set; }
   6:      public string Address { get; set; }
   7:      public string ContactPhone { get; set; }
   8:      public string Country { get; set; }
   9:      public DateTime EventDate { get; set; }
  10:      public string HostedBy { get; set; }
  11:  }

The HalResource base class just defines the standard HAL attributes:

   1:  public abstract class HalResource
   2:  {
   3:      public HalResource()
   4:      {
   5:          this.Links = new List<Link>();
   6:      }
   7:   
   8:      public string Rel { get; set; }
   9:      public string HRef { get; set; }
  10:      public string LinkName { get; set; }
  11:      public List<Link> Links { get; set; }
  12:  }

The code snippet below shows what my custom HalMediaTypeFormatter currently looks like. Notice line #18 in the constructor shows the media types that the formatter is intended to support.

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.IO;
   4:  using System.Linq;
   5:  using System.Net;
   6:  using System.Net.Http.Headers;
   7:  using System.Reflection;
   8:  using System.Xml;
   9:  using System.Xml.Linq;
  10:  using Microsoft.ApplicationServer.Http;
  11:   
  12:  namespace NerdDinnerWebApi.ResourceModel
  13:  {
  14:      public class HalMediaTypeFormatter : MediaTypeFormatter
  15:      {
  16:          public HalMediaTypeFormatter()
  17:          {
  18:              this.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/vnd.nerddinner.hal+xml"));
  19:          }
  20:   
  21:          public override object OnReadFromStream(Type type, Stream stream, HttpContentHeaders contentHeaders)
  22:          {
  23:              var instance = Activator.CreateInstance(type);
  24:              var xml = XElement.Load(stream);
  25:   
  26:              // First set the well-known HAL elements
  27:              type.GetProperty("Rel").SetValue(instance, xml.Attribute("rel").Value, null);
  28:              type.SetPropertyValueFromString("HRef", xml.Attribute("href").Value, instance);
  29:   
  30:              var links = xml.Elements("link");
  31:              Console.WriteLine("links count: " + links.Count());
  32:              var linksList = new List<Link>();
  33:              foreach (var link in links)
  34:              {
  35:                  linksList.Add(new Link { Rel = link.Attribute("rel").Value, HRef = link.Attribute("href").Value });
  36:              }
  37:              type.GetProperty("Links").SetValue(instance, linksList, null);
  38:   
  39:              // Now set the rest of the properties
  40:              foreach (var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty))
  41:              {
  42:                  Console.WriteLine("setting property: " + property.Name);
  43:                  type.SetPropertyValue(property.Name, xml.Element(property.Name), instance);
  44:              }
  45:   
  46:              return instance;
  47:          }
  48:   
  49:          public override void OnWriteToStream(Type type, object value, Stream stream, HttpContentHeaders contentHeaders, TransportContext context)
  50:          {
  51:              XmlWriterSettings settings = new XmlWriterSettings();
  52:              settings.Indent = true;
  53:   
  54:              var writer = XmlWriter.Create(stream, settings);
  55:              var resource = value as HalResource;
  56:              if (resource != null)
  57:              {
  58:                  writer.WriteStartElement("resource");
  59:                  writer.WriteAttributeString("rel", "self");
  60:                  writer.WriteAttributeString("href", resource.HRef);
  61:   
  62:                  foreach (var link in resource.Links)
  63:                  {
  64:                      writer.WriteStartElement("link");
  65:                      writer.WriteAttributeString("rel", link.Rel);
  66:                      writer.WriteAttributeString("href", link.HRef);
  67:                      writer.WriteEndElement();
  68:                  }
  69:   
  70:                  foreach (var property in value.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty))
  71:                  {
  72:                      if (ShouldWriteProperty(property))
  73:                      {
  74:                          var propertyString = GetPropertyString(property, value);
  75:                          if (propertyString != null)
  76:                          {
  77:                              writer.WriteElementString(property.Name, propertyString);
  78:                          }
  79:                      }
  80:                  }
  81:   
  82:                  writer.WriteEndElement();
  83:                  writer.Flush();
  84:              }
  85:          }
  86:   
  87:          private static bool ShouldWriteProperty(PropertyInfo property)
  88:          {
  89:              var nonSerializedProperties = new[] { "Rel", "HRef", "LinkName" };
  90:              var typesToSerialize = new[] { typeof(int), typeof(string), typeof(DateTime) };
  91:   
  92:              if (nonSerializedProperties.Contains(property.Name))
  93:              {
  94:                  return false;
  95:              }
  96:   
  97:              return typesToSerialize.Contains(property.PropertyType);
  98:          }
  99:   
 100:          private static string GetPropertyString(PropertyInfo property, object instance)
 101:          {
 102:              var propertyValue = property.GetValue(instance, null);
 103:              if (property.PropertyType.IsValueType || propertyValue != null)
 104:              {
 105:                  return propertyValue.ToString();
 106:              }
 107:              return null;
 108:          }
 109:      }
 110:  }

 

The code is not yet Production ready because it only handles a few primitives types and it is still incomplete with respect to the way HAL handles child collections but it gives a good flavor of *both* serialization/deserialization directions for a custom media type formatter. To tell the Web API to use this formatter, you can just add this configuration to your start up code (e.g., Global.asax or a PreApplicationStartMethod). The key is on line #20 below:

   1:  using System;
   2:  using System.Web.Routing;
   3:  using Microsoft.ApplicationServer.Http.Activation;
   4:  using Microsoft.ApplicationServer.Http.Description;
   5:  using NerdDinnerWebApi.ResourceModel;
   6:  using NerdDinnerWebApi.Services.Infrastructure;
   7:  using NerdDinnerWebApi.Services.Services;
   8:   
   9:  [assembly: WebActivator.PreApplicationStartMethod(typeof(NerdDinnerWebApi.Services.App_Start.ServicesInitializer), "Start")]
  10:   
  11:  namespace NerdDinnerWebApi.Services.App_Start
  12:  {
  13:      public static class ServicesInitializer
  14:      {
  15:          public static void Start()
  16:          {
  17:              var iocContainer = StructureMapBootstrapper.Initialize();
  18:              var config = HttpHostConfiguration.Create()
  19:                  .SetResourceFactory(new StructureMapResourceFactory(iocContainer))
  20:                  .AddFormatters(new HalMediaTypeFormatter());
  21:              RouteTable.Routes.MapServiceRoute<DinnerService>("dinners", config);
  22:          }
  23:      }
  24:  }

 

Finally, let’s see what the code looks like on this client side:

   1:  using System;
   2:  using System.Net.Http;
   3:  using System.Net.Http.Headers;
   4:  using Microsoft.ApplicationServer.Http;
   5:  using Microsoft.VisualStudio.TestTools.UnitTesting;
   6:  using NerdDinnerWebApi.ResourceModel;
   7:  using FluentAssertions;
   8:   
   9:  namespace WebApiTests
  10:  {
  11:      [TestClass]
  12:      public class DinnerServiceTests
  13:      {
  14:          private const string baseUri = "http://localhost:1700";
  15:          private static readonly MediaTypeWithQualityHeaderValue halMediaTypeHeader = new MediaTypeWithQualityHeaderValue("application/vnd.nerddinner.hal+xml");
  16:          private static readonly MediaTypeFormatter[] formatters = new[] { new HalMediaTypeFormatter() };
  17:   
  18:          [TestMethod]
  19:          public void Hal_formatter_should_serialize_request_for_dinner_resource()
  20:          {
  21:              // arrange
  22:              var httpClient = new HttpClient(baseUri);
  23:              httpClient.DefaultRequestHeaders.Accept.Add(halMediaTypeHeader);
  24:   
  25:              // act
  26:              var response = httpClient.Get("/dinners/1");
  27:              var dinnerResource = response.Content.ReadAs<Dinner>(formatters);
  28:   
  29:              // assert
  30:              dinnerResource.Should().NotBeNull();
  31:              dinnerResource.Rel.Should().Be("self");
  32:              dinnerResource.HRef.Should().EndWith("/dinners/1");
  33:              dinnerResource.DinnerId.Should().Be(1);
  34:              dinnerResource.Title.Should().Be("MVC Dinner");
  35:              dinnerResource.Description.Should().Be("This dinner will be for MVC developers.");
  36:              dinnerResource.Address.Should().Be("123 Main Street");
  37:              dinnerResource.EventDate.Should().Be(new DateTime(2011, 7, 1));
  38:              dinnerResource.Country.Should().Be("USA");
  39:              dinnerResource.Links.Count.Should().Be(3);
  40:          }
  41:      }
  42:  }

 

There are a couple of very important things to note in the code above. First, on line #23 I am setting the Accept header of the request (the variable was defined on line #15). Second, when I deserialize the xml to a .NET object on line #27, I pass the formatters in (which is just my HalMediaTypeFormatter) so that it knows how to deal with this request. If I don’t do this correctly, I’ll get an InvalidOperationException: No 'MediaTypeFormatter' is available to read an object of type <Type Name> with the media type <Media Type of Response>.

As you can see from the example above, I’m using the *same* custom Media Type Formatter on both the server *and* the client.

As I mentioned earlier in this post, the coupling between the client and server should be focused on defining the link relations for your media types. Stay tuned for my next post where I’ll show a mechanism for leveraging a media type formatter (like the one shown in this post) to generate documentation for consumers of your service so that consumers can fully understand all hypermedia link relations.

The complete solution for the code sample above can be downloaded here.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Saturday, May 28, 2011 #

IIS Express is a new web server that replaces the old Visual Studio web server (aka Cassini).  IIS Express provides a number of benefits which you can read about here and they key aspect is that it is IIS. However, that’s not to say that there aren’t any gotchas. One of the things that I ran into recently was that I was getting a 404 when trying to use the PUT and DELETE verbs (which are commonly used in RESTful services).  The reason this is happening is because these verbs are not enabled in the mappings for the handlers by default.

To enable this is the full version of IIS, it is a relatively straight forward task using the IIS Admin tool. First you go to the Handler Mappings:

handlerMappings

 

Then you select the “ExtensionlessUrlHandler-Integrated-4.0 handler:

handlerMappingsListView

 

Select “Request Restrictions”:

editManagedHandler

 

Then add PUT and DELETE on the “Verbs” tab:

requestRestrictions

 

Although the IIS Manager GUI makes this easy when using the full version of IIS, you don’t have the benefit of this GUI when working with IIS Express. But IIS Express *is* IIS so you can configure just about anything. The first thing you need to do is to find the IIS Express Configuration file. This is located in: C:\Users\<YourUserName>\Documents\IISExpress\config\applicationhost.config. Near the bottom of the file, you find the <handlers> section at this path: /configuration/location/system.webServer/handlers. Next, do a Find (Ctrl-F) for “ExtensionlessUrl-Integrated-4.0”. The final step is to add PUT and DELETE to the verb attribute:

<add name="ExtensionlessUrl-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />

At this point, you should be good to go!

UPDATE 8/14/2011: Some people have reported that they had to change their applicationhost.config file inside of the "C:\Program Files (x86)\IIS Express\config" directory (which does *not* match the documentation incidentally). The IIS team updated the documentation at the end of July (about 2 months after I originally posted this) here: http://learn.iis.net/page.aspx/901/iis-express-faq/ (just look for the section called "Q: How do I enable verbs like PUT/DELETE for my web application?").

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Thursday, May 05, 2011 #

I had a great time presenting MVC 3 and the Web Platform at CMAP this week. Thanks to everyone who came out. The code samples and PowerPoint can be downloaded here.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Sunday, May 01, 2011 #

This Tuesday (May 3) I will be presenting MVC 3 and the Web Platform at CMAP. Details can be found here. Hope to see you there!

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Thursday, April 28, 2011 #

I had a great time presenting at the Dayton .NET Developer Group last night. The code samples and PowerPoint can be downloaded here.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Thursday, April 21, 2011 #

Last week at MIX11, Preview 4 of WCF Web API was released. If you missed it, you can watch the video here. One way to get Preview 4 and start playing with it is to download it here. However, an even easier way to to just grab the bits from NuGet:

 

webapinugetdiag

 

When you download the latest Web API bits, there are a couple of sample applications that show off the latest features of the Web API (these are in the CodePlex download, not the NuGet packages). The first one is a Contact Manager “Simple” project which is intended to show just how simple it is to consume the Web API framework. There is also another sample which shows the advanced features such as IoC support, custom media type formatters, channels, and more.

I like to create a lot of “Hello World” applications when I’m learning a new technology for the first time or even when I just want to do some quick tests for a technology I already know pretty well. The existing Web API NuGet packages certainly help us add the references quickly. However, there is an even quicker way to get up and running with the new Web API – sample NuGet packages. Since NuGet has such rich functionality beyond adding references such as adding start code and configuration, there are many packages that exist to get you up and running fast. David Ebbo highlighted this last month in his post: Take NuGet to the next level with sample packages.

Taking all this into account, I created a “WebApi.CrudHttpSample” NuGet package. This allows you to fire up a brand new instance of Visual Studio, File – New Project, add the package and you are up and running. The Web API assemblies are added via NuGet dependencies and starter code is added as well. You can just select an “ASP.NET Empty Web Application” without having to worry about selecting some special WCF project template. This will have nothing in it but an empty web.config file.  Now you can add the package:

PM> Install-Package WebApi.CrudHttpSample

This first thing you’ll see is a “dummy” model class that looks like this:

   1:  // TODO: Use Visual Studio refactoring to rename "MyModelType" to your desired type.
   2:  //       Then you can move the model to its own file.
   3:  public class MyModelType
   4:  {
   5:      public int Id { get; set; }
   6:  }

Use Visual Studio refactoring to rename this class. It’s important to use the VS.NET refactoring because the type is referenced elsewhere in the starter code so this will rename it appropriately everywhere. I’ll rename it to “Contact” and add a couple of properties to it:

   1:  public class Contact
   2:  {
   3:      public int Id { get; set; }
   4:      public string FirstName { get; set; }
   5:      public string LastName { get; set; }
   6:  }

The next thing you’ll see is a resource class called “MyModelResource”. Again, you should use VS.NET refactoring to rename it to something that is sensible for your application. I’ll rename it to “ContactResource” (this is a similar approach to the starter code in the REST Start Kit from a couple years ago – of course they didn’t have NuGet at their disposal!). The code looks like this:

   1:  [ServiceContract]
   2:  public class ContactResource
   3:  {
   4:      // TODO: replace with your own "real" Repository implementation
   5:      private static readonly Dictionary<int, Contact> repository = new Dictionary<int, Contact>();
   6:   
   7:      [WebGet(UriTemplate = "{id}")]
   8:      public HttpResponseMessage<Contact> Get(int id)
   9:      {
  10:          Contact item;
  11:          if (!repository.TryGetValue(id, out item))
  12:          {
  13:              var notFoundResponse = new HttpResponseMessage();
  14:              notFoundResponse.StatusCode = HttpStatusCode.NotFound;
  15:              notFoundResponse.Content = new StringContent("Item not found");
  16:              throw new HttpResponseException(notFoundResponse);
  17:          }
  18:          var response = new HttpResponseMessage<Contact>(item);
  19:   
  20:          // set it to expire in 5 minutes
  21:          response.Content.Headers.Expires = new DateTimeOffset(DateTime.Now.AddSeconds(30));
  22:          return response;
  23:      }
  24:   
  25:      [WebInvoke(UriTemplate = "", Method = "POST")]
  26:      public HttpResponseMessage<Contact> Post(Contact item)
  27:      {
  28:          item.Id = (repository.Keys.Count == 0 ? 1 : repository.Keys.Max() + 1);
  29:          repository.Add(item.Id, item);
  30:   
  31:          var response = new HttpResponseMessage<Contact>(item);
  32:          response.StatusCode = HttpStatusCode.Created;
  33:          response.Headers.Location = new Uri("Contacts/" + item.Id, UriKind.Relative);
  34:          return response;
  35:      }
  36:   
  37:      [WebInvoke(UriTemplate = "{id}", Method = "PUT")]
  38:      public Contact Put(int id, Contact item)
  39:      {
  40:          repository[id] = item;
  41:          return item;
  42:      }
  43:   
  44:      [WebInvoke(UriTemplate = "{id}", Method = "DELETE")]
  45:      public Contact Delete(int id)
  46:      {
  47:          var deleted = repository[id];
  48:          repository.Remove(id);
  49:          return deleted;
  50:      }
  51:  }

There are several things to note about this code. First, I’m just using a static Dictionary for temporary storage. This can be replaced with your “real” repository of choice. The Get() method returns an HttpResponseMessage which is the strongly typed HTTP message available in the Web API. You can see that if the id is not found, we’re able to throw an HttpResponseException which is a much more intuitive way of dealing with exceptions than what we have today. I’m also able to set expiration headers – all without referring to the static WebOperationContext. The other methods are similarly easy to work with. It’s important to point out that this is not a RESTful service – this is merely a CRUD service over HTTP. Although I do set the location header in the Post() method, I’m not leveraging hypermedia and therefore, not RESTful.

At this point, all I have is a single C# file – how do I get this hooked into the WCF pipeline? The next thing I take advantage of is the WebActivator NuGet package. I follow the established pattern for the “App_Start” folder and put my initialization code in here. This code will automatically be invoked when the web site starts up (no need for Global.asax). Then just change the first URI segment from “MyModel” to whatever you want. I’ll change it to “Contacts”:

webapiappstart

At this point, I can now run my app in Fiddler with all VERBs:

  • GET /Contacts/1 – gets an existing contact (404 if it doesn’t exist)
  • POST /Contacts – specify Content-type: application/type and post Contact xml to insert
  • PUT /Contacts/1 – updates existing Contact
  • DELETE /Contacts/1 – deletes existing Context

To see the NuGet package in action as well as executing all methods in Fiddler, watch this short (6 minute) video below (if there is a problem with the embedded video, direct video link is here):

Viewing this content requires Silverlight. You can download Silverlight from http://www.silverlight.net/getstarted/silverlight3.

A logical next step would be to create a NuGet sample package that contains starter code for more advanced features such as IoC, media type formatters, etc. The Web API is getting better and better. It’s now easier and simpler than ever to work with HTTP. Now is the time to start getting familiar with it and provide your feedback to the team.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Monday, March 28, 2011 #

I recently had the pleasure of being the guest on Joe Stagner’s podcast. We discuss several new technologies in the Microsoft technology stack including the new WCF Web APIs, MVC 3, and more. We also talk about being a Microsoft MVP and working for a Managed Microsoft Gold Partner.

The direct link to the podcast is: http://www.msjoe.com/2011/03/podcast-stevemichelotti/

Thanks to Joe for having me on the show!

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati