Alik Levin's

Clarity, Technology, and Solving Problems | PracticeThis.com 

June, 2010

  • Alik Levin's

    RESTful WCF Architecture – Hosting RESTful WCF Services in IIS

    • 0 Comments

    Inspired by the book RESTful .NET: Build and Consume RESTful Web Services with .NET 3.5.

    Hosting in IIS [managed hosting] offers the following advantages:

    • Process setup and shutdown.
    • Process pooling and recycling.
    • Application restart [recycle] when configuration changed.
    • Enhanced security model.
    • Management tools.
    • Caching management.
    • Proven hosting platform written, debugged by A-team @MS.
    • Officially supported MS product/technology.

    Hosting WCF in IIS – Quick & Dirty

    Following are quick steps to expose WCF service via IIS and svc file using Visual Studio.

    • Create ASP.NET Empty Web Application. The application will provide a container for RESTful WCF services – files with svc extension. When IIS receives a request to resource with svc extension it routes to WCF handler. Look for *.svc extension as a path and its corresponding handler which is System.ServiceModel.Activation.HttpModule in IIS manager under Handler Mappings.
    • Add WCF Service. Visual Studio creates three files. For example, if you create RESTfulWCF service these files are created:
      • RESTfulWCF.svc – the file that glues the request routed by IIS and the service implementation. This is a simple text file that should look similar to this:

    <%@ ServiceHost Language="C#"
                    Debug="true"
                    Service="RESTfulWCFHostedInIIS.RESTfulWCF"
                    CodeBehind="RESTfulWCF.svc.cs" %>

      • IRESTfulWCF.csservice’s interface with contract attributes decoration. It’s a common WCF practice to separate the interface and the implementation when building WCF services.
      • RESTfulWCF.svc.csthe code behind file that implements the service based on the IRESTfulWCF.cs.
    • Configure web.config.

    Hosting WCF in IIS – Componentaized Approach

    Another approach is to componentize the service into separate assembly. The main benefit of the approach is complete separationg or componentization of the service and how it’s exposed to the external world. Another huge benefit is this approach eliminates the need of messing with web.config.

    Following are the steps needed to expose the WCF component that implements RESTful WCF service via svc file hosted in IIS:

    Summary of steps:

    • Step 1 - Create class library project.
    • Step 2 - Implement RESTful resource.
    • Step 3 - Define RESTful WCF service interface.
    • Step 4 - Implement RESTful WCF service based on the interface.
    • Step 5 - Create empty web project.
    • Step 6 - Create new svc file.
    • Step 7 - Edit web.config file.
    • Step 8 - Test RESTful WCF service hosted in IIS.

    Rest of the post is the detailed walkthrough of the above steps.

    • Step 1 - Create class library project. The purpose of the class library to hold the implementation of the RESTful WCF service. It will hold all related artifacts – entities, service interfaces, and the service implementation. Another approach would be separating all three into three different class libraries [assemblies]. This is even better approach for componentization and reuse which I have taken in my previous posts for solution architecture - Step 1: Structure Your Solution, Step 2: Design Your Entities & Business Components, Step 3: Design Your Cross Cutting Utilities, Step 4: Design Your Presentation Layer – Part I , Step 4: Design Your Presentation Layer – Part II. For now I’ll keep it simpler but still componentized into one single class library but still separated from how it’s exposed – in my case svc file hosted in IIS. Create ether Class Library or WCF Service Library which just adds required for WCF references saving few clicks and adding namespaces. Call it RESTfulWCFLibrary. Delete IService.cs and Service.cs created by default. Add reference to System.ServiceModel.Web.
    • Step 2 - Implement RESTful resource. Create new cs class and call it User. It will represent the entity, the resource being exposed and manipulated by the RESTful WCF service. Paste the following implementation:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;
    using System.Runtime.Serialization;

     

    namespace RESTfulWCFHostedInIIS
    {
        //SINCE I USE DATA CONTRACT THE SERIALIZED XML WILL BE 
        //BUILT BASED ON ELEMENTS vs. ATTRIBUTES
        [CollectionDataContract(Name="users",Namespace="")]
        public class Users: List<User>
        { }

        [DataContract(Name = "user", Namespace = "")]
        public class User
        {
            [DataMember(Name = "id", Order = 1)]
            public string UserId;
            [DataMember(Name = "firstname", Order = 2)]
            public string FirstName;
            [DataMember(Name = "lastname", Order = 3)]
            public string LastName;
            [DataMember(Name = "email", Order = 4)]
            public string Email;
        }
    }

    • Step 3 - Define RESTful WCF service interface. It’s common practice to separate WCF decorated interface from it’s implementation. I follow the practice here. Create new cs interface file, call it IUserService, and paste the following interface definition:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Web;

     

    namespace RESTfulWCFLibrary
    {
        [ServiceContract]
        interface IUserService
        {
            [WebGet(UriTemplate = "/users",
                    ResponseFormat = WebMessageFormat.Xml)]
            [OperationContract]
            Users GetAllUsers();

            [WebInvoke(UriTemplate = "/users",
                       Method = "POST",
                       RequestFormat = WebMessageFormat.Xml,
                       ResponseFormat = WebMessageFormat.Xml)]
            [OperationContract]
            User AddNewUser(User u);

     

            [WebGet(UriTemplate = "/users/{user_id}",
                    ResponseFormat = WebMessageFormat.Xml)]
            [OperationContract]
            User GetUser(string user_id);
        }
    }

    • Step 4 - Implement RESTful WCF service based on the interface. Next step is adding actual implementation of the RESTful WCF service based on the interface I have just defined in previous step. Create new cs class file, name it UserService, and paste the following code:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Web;

     

    namespace RESTfulWCFLibrary
    {
        public class UserService : IUserService
        {
            static Users _users = new Users();
            public Users GetAllUsers()
            {
                GenerateFakeUsers();
                return _users;
            }
            public User AddNewUser(User u)
            {
                u.UserId = Guid.NewGuid().ToString();
                _users.Add(u);
                return u;
            }
            public User GetUser(string user_id)
            {
                var u = FindUser(user_id);
                return u;
            }
            private User FindUser(string user_id)
            {
                return new User() { FirstName = "alik",
                              
         LastName = "levin"
                              
         Email = alikl@microsoft.com
                                    UserId = "1" };
            }
            private void GenerateFakeUsers()
            {
                _users.Add(new User() { FirstName = "alik"
                                        LastName = "levin"
                                        Email = alikl@microsoft.com
                                        UserId = "1" });
                _users.Add(new User() { FirstName = "alik"
                                    
       LastName = "levin"
                                    
       Email = alikl@microsoft.com
                                        UserId = "1" });
            }
        }
    }

     

    • Step 5 - Create empty web project. Create ASP.NET empty web application project. Name it RESTfulWCFEndPointsHostedIIS. It will hold the svc files hosted in IIS. These files will serve as actual end points where incoming requested will be routed. Switch to RESTfulWCFLibrary project and configure to build its assmebly, RESTfulWCFLibrary.dll, into RESTfulWCFEndPointsHostedIIS bin folder. To do so, go to RESTfulWCFLibrary’s property page, click on Build tab, and provide this path in Output path: ..\RESTfulWCFEndPointsHostedIIS\bin\
    • Step 6 - Create new svc file. While in RESTfulWCFEndPointsHostedIIS create new WCF Service, name it RESTfulWCFUsersServiceEndPoint. Delete IRESTfulWCFUsersServiceEndPoint.cs and RESTfulWCFUsersServiceEndPoint.svc.cs files created by default. Open RESTfulWCFUsersServiceEndPoint.svc’s file markup by double clicking it and paste the following markup. Notice the Factory attribute.

    <%@ ServiceHost Service="RESTfulWCFLibrary.UserService" 
                    Factory="System.ServiceModel.Activation.WebServiceHostFactory"%>

    • Step 7 - Edit web.config file. No changes needed for the web.config which is fantastic – no massive mess in it, leave it as is. It’s due to the fact we added Factory attribute in the svc file which take care if it all. Once more – no web.config mess! Done.
    • Step 8 - Test RESTful WCF service hosted in IIS. Follow the procedures similar to those outlined in Walkthrough: Build, Host, and Test Simple RESTful WCF Service – Step 4, Step 5, Step 6 to test the implementation. To identify the URI, right click on RESTfulWCFUsersServiceEndPoint.svc and then choose “Wiew In Browser” option. Copy the URL from the browser’s Address bar and paste it to Request Builder in Fiddler adding proper URI, for example, this URL http://localhost:49852/RESTfulWCFUsersServiceEndPoint.svc/users should return all users.

    Related Books

  • Alik Levin's

    Walkthrough: Build, Host, and Test Simple RESTful WCF Service

    • 0 Comments

    This post summarizes the steps needed to create basic self hosted RESTful WCF service based on the book RESTful .NET: Build and Consume RESTful Web Services with .NET 3.5.

    Summary of steps

    Following are the summary of steps needed to be taken to create and test self hosted RESTful WCF services.

    • Step1 - Create a class that represent resource – user.
    • Step2 - Create a service that expose functionality to manipulate the resource
    • Step3 - Create self-host to host the service
    • Step4 - Use fiddler to test the solution – get all users
    • Step5 - Use fiddler to test the solution  - get specific user
    • Step6 - Use fiddler to test the solution  - update user

    Rest of the post is the details for each step. Create new console project in Visual Studio.

    Step1 - Create a class that represent resource – user.

     

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;
    using System.Runtime.Serialization;

    namespace ReadWriteREST
    {
        //SINCE I USE DATA CONTRACT THE SERIALIZED XML WILL BE 
        //BUILT BASED ON ELEMENTS vs. ATTRIBUTES
        [CollectionDataContract(Name="users",Namespace="")]
        public class Users: List<User>
        {
        }
        [DataContract(Name = "user", Namespace = "")]
        public class User
        {
            [DataMember(Name = "id", Order = 1)]
            public string UserId;
            [DataMember(Name = "firstname", Order = 2)]
            public string FirstName;
            [DataMember(Name = "lastname", Order = 3)]
            public string LastName;
            [DataMember(Name = "email", Order = 4)]
            public string Email;
        }
    }

     

    Step 2 - Create a service that exposes functionality to manipulate the resource

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Web;

    namespace
    ReadWriteREST
    {
        [ServiceContract]
        public class UserService
        {
            static Users _users = new Users();

            [WebGet(UriTemplate = "/users")]
            [OperationContract]
            public Users GetAllUsers()
            {
                GenerateFakeUsers();
                return _users;
            }

            [WebInvoke(UriTemplate = "/users", Method = "POST")]
            [OperationContract]
            public User AddNewUser(User u)
            {
                u.UserId = Guid.NewGuid().ToString();
                _users.Add(u);
                return u;
            }

     

            [WebGet(UriTemplate = "/users/{user_id}")]
            [OperationContract]
            public User GetUser(string user_id)
            {
                var u = FindUser(user_id);
                return u;
            }

            private User FindUser(string user_id)
            {
                return new User() { FirstName = "alik"
                                    LastName = "levin",
                                    Email = "alikl@microsoft.com",
                                    UserId = "1" };
            }

            private void GenerateFakeUsers()
            {

                _users.Add(new User() { FirstName = "alik",
                                        LastName = "levin",
                                        Email = "alikl@microsoft.com",
                                        UserId = "1" });
            }
        }
    }

    Step 3 - Create self-host to host the service

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Description;

    namespace ReadWriteREST
    {
        class Program
        {
            static void Main(string[] args)
            {
                ServiceHost sh = new ServiceHost(typeof(UserService),
                                                 new Uri("http://localhost:8089/"));
                bool openSucceeded = false;
                //TRY OPENINNG, IF FAILS THE HOST WILL BE ABORTED
                try
                {
                    ServiceEndpoint sep = sh.AddServiceEndpoint(typeof(UserService),
                                                                new WebHttpBinding(),
                                                                "Hosting");
                    sep.Behaviors.Add(new WebHttpBehavior());
                    sh.Open();
                    openSucceeded = true;
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Service host failed to open {)}"
                                      ex.ToString());
                }
                finally
                {
                    if (!openSucceeded)
                    {
                        sh.Abort();
                    }
                }
                if (sh.State == CommunicationState.Opened)
                {
                    Console.WriteLine("The Service is running. Press Enter to stop.");
                    Console.ReadLine();
                }
                else
                {
                    Console.WriteLine("Server failed to open");
                }
                //TRY CLOSING, IF FAILS THE HOST WILL BE ABORTED
                bool closeSucceed = false;
                try
                {
                    sh.Close();
                    closeSucceed = true;
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Service failed to close. Exception {0}",
                                      ex.ToString());
                }
                finally
                {
                    if (!closeSucceed)
                    {
                        sh.Abort();
                    }
                }
            }
        }
    }

    Step 4 - Use fiddler to test the solution – get all users

    This functionality is handled by the following method:

    [WebGet(UriTemplate = "/users")]
    [OperationContract]
    public Users GetAllUsers()

    Run your service. Use Fiddler’s Request Builder to issue a request similar to the following

    RESTful WCF

    Use Inspectors tab to review the response.

    Step 5 - Use fiddler to test the solution  - get specific user

    The functionality is handled by the following method

    [WebGet(UriTemplate = "/users/{user_id}")]
    [OperationContract]
    public User GetUser(string user_id)

    RESTful WCF

    Use Inspectors tab to verify the response.

    Step 6 - Use fiddler to test the solution  - update user

    The functionality is handled by the following method:

    [WebInvoke(UriTemplate = "/users", Method = "POST")]
    [OperationContract]
    public User AddNewUser(User u)

    RESTful WCF

    Notice three main attributes of this request:

    • the method is POST although submitted to the same URL.
    • Content-Type is text/xml.
    • Request body contains serialized User object as the method expects.

    Related Books

  • Alik Levin's

    Notes On RESTful Architecture - I

    • 0 Comments

    This post is a summary of notes I am taking while reading a book RESTful .NET: Build and Consume RESTful Web Services with .NET 3.5.

    Resources and URI’s

    • RESTful services model the interaction with user agents based on resource.
    • The first thing to do is to determine which resources you’re going to expose.
    • A resource is any information that you want to make available to others.
    • Some resources are static…, and some resources are dynamic.
    • Once you’ve identified the resources you’ll map then to URI’s.

    URI design

    • All resources are uniquely identified by a URI.
    • The idea behind REST is to design your URIs in a way that makes logical sense based on your resource set (vs. GUIDS or/and funky query strings)
    • When designing the associations between resources and URI’s, it may be useful to map them as if you were designing a browsable website.

    Uniform Interface

    • User agents only interact with resources using the prescribed HTTP verbs.
    • The four main verbs are:
      • GET
        • Retrieves a resource.
        • Guaranteed not to cause side-effects (SAFE).
        • Cacheable.
      • POST
        • Creates a new resource.
        • Unsafe, effect of this verb isn’t defined by HTTP.
      • PUT
        • Updates an existing resource.
        • Used for resource creating when client knows URI.
        • Can call N times, same thing will always happen (idempotent).
      • DELETE
        • Removes a resource.
        • Can call N times, same thing will always happen (idempotent).

    Checklist for building RESTFul architecture:

    • Decide what your recourses are.
    • Map the resources to URIs.
    • For each URI define it’s media types [HTTP Content-Type]:
      • XML [application/xml, text/xml - deprecated].
      • RSS/Atom [atom more recent, devs like it, APP or AtomPub protocol].
      • XHTML [application/xhtml+xml].
      • JSON [application/json]
      • More at www.microformats.org

    Related Books

Page 1 of 2 (5 items) 12