Friday, June 29, 2012

Combo RESTful WCF with Windows Service Hosting and Dynamic Response Format

The Goal
I have been working through the plausibility of multipurpose WCF services that are hosted in a windows hosting environment.  As part of my research, I wanted to prove that you could host a single service as a standard service to be consumed by a client proxy and scale it out from there to webHTTP and RESTful behavior.  The biggest goal I had was to make the service dynamically reply in the same format in which it was consumed without having a drawn out implementation to handle the messaging.

The Project
After some reading and messing around I have completed the following project which does exactly what I had hoped.  This single WCF implementation will allow for a straight service call, a RESTful call and respond dynamically with xml or json to the REST query based on the content type value of the request header.  All while being hosted in a windows service that can be dynamically deployed.  I came up with a very simple project that allows for interaction with a listing of albums.  The example is simple, but the devil of this was not in the actual data elements, so I flagged the scalability of that as irrelevant to the goal of illustrating the mechanism.

The Services
I created a basic WCF service to perform CRUD on my album repository. You will notice the service decorations on the interface indicating both an operation contract and a WebInvoke/WebGet behavior and template.


[ServiceContract(Name = "AlbumContract", 
     Namespace = "RESTCombo.Services", 
     SessionMode = SessionMode.Allowed)]
public interface IAlbumSvc:IMetadataExchange
{
    [OperationContract]
    [WebGet(UriTemplate = "/Albums/{id}"), 
        Description("Returns the album with the passed ID")]
    Album GetAlbum(String id);
 
    [OperationContract]
    [WebGet(UriTemplate = "/Albums"), 
        Description("Returns the entire list of albums")]
    List<Album> GetAlbums();
 
    [OperationContract]
    [WebInvoke(Method = "POST", UriTemplate = "/Albums"), 
         Description("Adds a new album to list of albums")]
    void AddAlbum(Album album);
 
    [OperationContract]
    [WebInvoke(Method = "PUT", UriTemplate = "/Albums"), 
         Description("Updates an existing album")]
    void UpdateAlbum(Album album);
 
    [OperationContract]
    [WebInvoke(Method = "DELETE", UriTemplate = "/Albums/{id}"), 
         Description("Removes an album from list of albums")]
    void DeleteAlbum(String id);
}
 
The WebGet and WebInoke decoration allows the services to respond as a RESTful WCF service based on the URI template.  The service implementation should be decorated as follows:


[ServiceBehavior(Name = "RESTCombo.Services.AlbumSvc", 
    ConcurrencyMode = ConcurrencyMode.Single, 
    InstanceContextMode = InstanceContextMode.Single,
    IncludeExceptionDetailInFaults = true)]    
[AspNetCompatibilityRequirements(
    RequirementsMode=AspNetCompatibilityRequirementsMode.Allowed)]
public class AlbumSvc : IAlbumSvc

I'm going to skip posting the implementation of the services themselves as they are actually irrelevant to the discussion.  The entire project is attached at the end of the post if you would like to review the code.

The Configuration
While most of the configuration is fairly straight-forward, there are a couple of items worth pointing out.  Notice the multiple bindings for the single service.  Each must respond on its own port.  You can have as many bindings as needed up to one per protocol.  The webHttp endpoint behavior is vital to this mechanism.  helpEnabled allows users to use the '/help' switch at the end of a query to get a service overview page as shown here.


defaultOutgoingResponseFormat is our selection for the default response to a webHttp request. automaticFormatSelectionEnabled allows the response to dynamically detect the request format and respond in kind.

<?xml version="1.0"?>
<configuration>
  
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
  </startup>
  <system.serviceModel>
    <services>
      <service name="RESTCombo.Services.AlbumSvc">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8080/AlbumSvc/" />
            <add baseAddress="net.tcp://localhost:2122" />
          </baseAddresses>
        </host>
        <endpoint  binding="webHttpBinding" contract="RESTCombo.Services.IAlbumSvc"
                  bindingConfiguration="RESTBindingConfiguration" 
                   behaviorConfiguration="RESTEndpointBehavior"/>      
        <endpoint address="net.tcp://localhost:2122/AlbumSvc/" binding="netTcpBinding"
                  contract="RESTCombo.Services.IAlbumSvc"/>
      </service>
    </services>    
    <bindings>
     <webHttpBinding>
        <binding name="RESTBindingConfiguration">
          <security mode="None" />          
        </binding>
      </webHttpBinding>      
      <netTcpBinding>
        <binding name="DefaultBinding">
          <security mode="None"/>
        </binding>        
      </netTcpBinding>
    </bindings>
    <behaviors>      
      <endpointBehaviors>
        <behavior name="RESTEndpointBehavior">           
          <webHttp helpEnabled="true" defaultOutgoingResponseFormat="Xml"
                   automaticFormatSelectionEnabled="true"/>
        </behavior>
      </endpointBehaviors>
      
      <serviceBehaviors>                        
        <behavior name="DefaultBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>       
      </serviceBehaviors>
    </behaviors>  
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" 
                               aspNetCompatibilityEnabled="true" />
  </system.serviceModel>
</configuration>

The Testing
We will just fast-forward through the hosting setup and service implementation.  Now that services are configured, built and running, we can perform the response testing and see how it all comes together.  When browsing to the webHttp base address and invoking the services via RESTful queries, I receive the following responses for the list and single respectively.




Then, to prove the JSON / XML switch, I used a fiddler software to create and review requests and responses.  First, I constructed an XML request and trapped the response.



Then, I constructed a JSON request and trapped the response.




As you can see, the service is responding to me in the request format.  For the client proxy implementation, review the source code attached at the end of the post.  The big victory here is the open and scalable approach to an SOA.  By doing dynamic communication in this manner, we are enabling a service to be consumed in the way that an integrator can best leverage.  This allows us to have a single implementation of intelligence and functionality while allowing any integrating software to choose the manner in which it interacts.  This is very powerful and very scalable and should allow your services to be consumer agnostic and focus strictly on intelligence.  For further review, download the entire project here.

17 comments:

  1. It's a pity you don't have a donate button! I'd most certainly donate to this superb blog! I suppose for now i'll settle for bookmarking and adding your RSS
    feed to my Google account. I look forward to new updates
    and will share this website with my Facebook group. Talk soon!


    Also visit my web site: barcode printers

    ReplyDelete
  2. I'm really loving the theme/design of your blog. Do you ever run into any browser compatibility issues? A couple of my blog readers have complained about my blog not working correctly in Explorer but looks great in Safari. Do you have any tips to help fix this issue?

    my web-site :: Motorola MC9090

    ReplyDelete
  3. It is not my first time to visit this site, i am browsing this website dailly
    and get good data from here everyday.

    Also visit my website: barcode scanner repair

    ReplyDelete
  4. Hello there! Do you know if they make any plugins to help with Search Engine Optimization?
    I'm trying to get my blog to rank for some targeted keywords but I'm not seeing
    very good gains. If you know of any please share.
    Thank you!

    my web blog :: Inventory Management System

    ReplyDelete
  5. Hello to every one, the contents present at this web site
    are truly amazing for people experience, well, keep up the good
    work fellows.

    Also visit my blog ... about

    ReplyDelete
  6. I was recommended this website by my cousin. I'm not sure whether this post is written by him as no one else know such detailed about my difficulty. You're wonderful!
    Thanks!

    Feel free to visit my web blog ... diet products

    ReplyDelete
  7. Pretty! This has been a really wonderful post. Thank you for supplying
    these details.

    My web page - more Info

    ReplyDelete
  8. Whats up very nice web site!! Man .. Excellent .

    . Amazing .. I will bookmark your blog and take the feeds also?
    I'm happy to search out numerous helpful info right here within the post, we need work out extra techniques on this regard, thank you for sharing. . . . . .

    Visit my site ... more info

    ReplyDelete
  9. you are truly a good webmaster. The website loading velocity is incredible.
    It sort of feels that you're doing any unique trick. Moreover, The contents are masterwork. you have performed a magnificent task on this topic!

    my web-site; more Info

    ReplyDelete
  10. WOW just what I was looking for. Came here by searching for social security age

    My weblog: www.best-Moving-quotes.com

    ReplyDelete
  11. Wow! After all I got a webpage from where I be able to truly obtain
    valuable information regarding my study and knowledge.


    Here is my web site http://www.mumbaiescort.biz

    ReplyDelete
  12. Project file has been deleted from fileden :(

    ReplyDelete

  13. If you’re a business owner, you will encounter the need to find a web hosting provider for hosting your website. It is essential to any business that they reach out to the public the best they can.1 Dollar Hosting

    ReplyDelete
  14. Because the SBA has some stringent requirements with each loan they offer, seeking
    the help of an SBA counselor is recommended, especially if you've never prepared a
    loan package before. These loans can be fixed rate, ARM or even a line
    of credit. And by availing these loans, borrowers can borrow
    anything from five thousand pound to twenty five thousand pound.

    ReplyDelete
  15. Excellent post. I was checking continuously this
    blog and I'm impressed! Very useful info specifically the last part :
    ) I care for such information much. I was seeking this certain information for a long time.
    Thank you and best of luck.

    My website ... smålån uten sikkerhet

    ReplyDelete
  16. By keeping up on your regular payments, you are helping your credit history.

    They have professional negotiators that will agree with your lenders
    a reduction on your debt and a new more affordable repayment program.

    that they could obtain a mortgage or remortgage of up to as much as $If he earned enough money.


    Here is my blog post; loans

    ReplyDelete