It's Spann, not spam

Technical blog to provide content that developers find useful.

Building REST-based Services Using WCF - (Part 1)

Building REST-based Services Using WCF - (Part 1)

  • Comments 4

Summary:

This how-to post will introduce you to building REST-based services using WCF.  This series is split into three parts.  Each part is built on the previous part.

Prerequisites:

WCF Web Programming Model (REST)

WCF in .NET 3.5 has added features to its programming model to make it easy to build services which can be invoked using a REST-based approach.  In this first part you will create a WCF endpoint using this new Web programming model.  You will expose data through a URI-based REST mechanism returning XML-formatted data.

Select Start | All Programs | Microsoft Visual Studio 2008 | Microsoft Visual Studio 2008 to load the Visual Studio 2008 development environment.

Inside of Visual Studio 2008 select File | New | Web Site.

Select Empty Web Site as the template, and ensure that .NET Framework 3.5 is selected as the target framework version.

image

Select Location to be HTTP, then type the following as the URL:http://localhost/MusicWeb, select the Language to be Visual C#, and click OK.

image

Right-click on the project node in the Solution Explorer, select Add ASP.NET Folder from the context menu, and select App_Data from the submenu.

image

Repeat the last step, this time selecting App_Code as the ASP.NET Folder to add.

Right-click on the App_Data folder and select Add Existing Item.  Browse to where you saved the Movie.mdf file and add the database file.

Right-click on the App_Code folder and select Add New Item.  Select LINQ to SQL classes as the template, and MovieData.dbml as the Name.  Press the Add button.

Open the Server Explorer (View | Server Explorer menu), expand Movie.mdf, expand the Tables node.

Drag and drop the director and movie tables onto the Object Relational Designer surface.  This action generates classes you can use to work with data from the Music database.

image

Right-click on the App_Code folder and select Add New Item.  Select Class as the template, and name the class DirectorService.cs.  Click Add.

Open the file DirectorService.cs file.

After the using statements, add the following using statements:

using System.ServiceModel;
using System.Runtime.Serialization;
using System.Collections.Generic;
using System.ServiceModel.Web;
using System.ServiceModel.Activation;

Add a ServiceContract attribute to the top of the DirectorService class.  Add an AspNetCompatibilityRequirements attribute, with a RequirementsMode property of AspNetCompatibilityRequirements.Allowed.

[ServiceContract()]
[AspNetCompatibilityRequirements(RequirementsMode=AspNetCompatibilityRequirementsMode.Allowed)]
public class DirectorService
{
    public DirectorService()
    {
        //
        // TODO: Add constructor logic here
        //
    }
}

After the closing brace of the DirectorService class, add a public class named DirectorResult.  Add the DataContract attribute to this class, and set Name property to be "Movie" and the Namespace property to a blank string:

[DataContract(Namespace="", Name="Director")]
public class DirectorResult
{
}

Add two public fields to DirectorResult class, both of type string, one named DirectorName and the other named Link.  Add the DataMember attribute to both of these fields.

[DataContract(Namespace="", Name="Director")]
public class DirectorResult
{
    [DataMember]
    public string DirectorName;

    [DataMember]
    public string Link;
}

After the DirectorResult class, add another public class that derives from List<string>, this one named MovieList.

Add the CollectionDataContract attribute to the MovieLIst class.  Set its ItemName property to "Movie", and the Namespace property to a blank string.

Add a default parameterless constructor to MovieList.

Add another constructor to MovieList, this one takes an IEnumerable<string> parameter, and calls the base class's constructor.

[CollectionDataContract(ItemName="Movie", Namespace="")]
public class MovieList : List<string>
{
    public MovieList()
    {
    }
    public MovieList(IEnumerable<string> movies)
        : base(movies)
    {
    }
}

After the MovieList class, add another public class, this one named DirectorDetail.  Add a DataContract attribute to the ArtistDetail class, and use "Director" as the value for the Name property and a blank string as the value of the Namespace property.

Add two public fields, one of type MovieList named Movies and one of type string named DirectorName.  Add the DataMember attribute to both of these fields, and set the Order property of the DataMember attribute on DirectorName to 0 and the Order property of the DataMember attribute on Movies to 1.

[DataContract(Namespace="", Name="Director")]
public class DirectorDetail
{
    [DataMember(Order=0)]
    public string DirectorName;

    [DataMember(Order=1)]
    public MovieList Movies;
}

Inside of the DirectorService class add a public method named GetAllDirectors that returns an array of DirectorResult.  Add the OperationContract attribute to this method.  Also add the WebGet attribute to this method and specify the UriTemplate property of the WebGet attribute to be "/".

[OperationContract]
[WebGet(UriTemplate="/")]
public DirectorResult[] GetAllDirectors()
{
}

Within the GetAllDirectors method, create an instance of the MovieDataDataContext class, named dc:

MovieDataDataContext dc = new MovieDataDataContext();

Get the URI of the incoming request and put it into a string variable.  You can get this value from WebOperationContext.Current.IncomingRequest.UriTemplateMatch.RequestUri.

string currentUrl = WebOperationContext.Current.IncomingRequest.UriTemplateMatch.RequestUri.ToString();

Add a LINQ query to get all the directors from the data context, and select it into new instances of DirectorResults, selecting the name from the data and the link by creating a string from the directorname and the currentUri.  Convert the result of the LINQ query to an array and return it.  The contents of the GetAllDirectors procedure should look like the following:

MovieDataDataContext dc = new MovieDataDataContext();

string currentUrl = WebOperationContext.Current.IncomingRequest.UriTemplateMatch.RequestUri.ToString();

var result = from aDirector in dc.directors
      select new DirectorResult
      {
             DirectorName = aDirector .director_name,
             Link = String.Format("{0}{1}", currentUrl, aDirector .director_name)
      };

return result.ToArray();

Inside of the DirectorService class add a public method names GetDirector that returns an DirectorDetail class and takes a string parameter named director.  Add the OperationContract attribute to this method.  Also add the WebGet attribute to this method - and specify the UriTemplate property of the WebGet attribute to be "/{director}"

    [OperationContract]
    [WebGet(UriTemplate="/{director}")]
    public DirectorDetail GetDirector(string director)
    {
    }

Inside of the GetDirector method, create an instance of the MovieDataDataContext object, named dc.

Use the MovieDataDataContext.directors with a LINQ query to find the particular director that is being queried.  Create a DirectorDetail and use a subquery to fill in the MovieList property.  Return the first item from the collection.  The completed contents of the procedure should look like the following:

[OperationContract]
[WebGet(UriTemplate="/{director}")]
public DirectorDetail GetDirector(string director)
{
    MovieDataDataContext dc = new MovieDataDataContext();

    var result = from aDirector in dc.directors
                 where aDirector.director_name == director
                 select new DirectorDetail
                 {
                     DirectorName = aDirector.director_name,
                     Movies = new MovieList(
                         (from movie in aDirector.movies
                          select movie.movie_name)
                          )
                 };

    return result.First();
}

Right-click on the project in the Solution Explorer and select Add New Item.  Select Text File as the template, and specify the name as DirectorSerivce.svc.  Click Add.

image

Inside of the DirectorService.svc file, add a ServiceHost declaration with the following attributes and properties:

Attribute Value
Language C#
Service DirectorService
Factory System.ServiceModel.Activation.WebServiceHostFactory

<%@ ServiceHost Language="C#" Service="DirectorService" Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>

Save all open files.  Right-click on the MovieWeb project in the Solution Explorer and select Build Web Site.

Right-click on the DirectorService.svc file in the Solution Explorer and select View in Browser.

Your browser window should look similar to this (if you see an error message, refresh the content by pressing F5).

image

(Note - Now you have a REST service that returns XML that could be consumed by any REST client (typically that would not be a browser).

Click the menu next to the Tools menu item on the Internet Explorer toolbar and select Web Development Helper.

image

(Note - The Web Development Helper is a tracing tool which will allow you to see the requests going from the browser to the WCF Service).

Check the checkbox next to Enable Logging.  Copy the value of the first Link element from the browser (http://visualstudio2k8/MovieWeb/DirectorService.svc/George Clooney), put that link in the address bar of your browser and press enter.  This should take you to the second method.

image

Double-click on the URL in the bottom pane of the Web Development Helper, then click on the Response Content tab in the bottom pane, so you can see what the response looks like.

image

Close the Http Log View dialog.

Summary

In this post we created a simple WCF REST-based Service.  The service returned custom XML serialized data - and used the URIs to map client invocations to methods using WebGet and UriTemplate.

In the next part (Part 2) we will look at JSON.  Until next time...

Happy Coding!

 

  • Summary: This how-to post will introduce you to building REST-based services using WCF.&#160; This series

  • Overview: This how-to post will introduce you to building REST-based services using WCF.&#160; This series

  • In the sample project, Movie.zip doesn't seem available any more for download. Is there an alternative link somewhere?

    Besides, 'MusicWeb' as a project name should have been 'MovieWeb' instead, as read from the context.  

    Good work!

  • Humm, well I am not sure what is going on there.  The files are on my skydrive account and the zip file is still there.  It must be a permissions thing.  I will look into it more.

    Thanks!

Page 1 of 1 (4 items)
Leave a Comment
  • Please add 8 and 6 and type the answer here:
  • Post