REST http://rickgaribay.net/category/48.aspx REST en-US Rick G. Garibay rickgaribay@hotmail.com Subtext Version 1.9.5.176 Windows Server AppFabric Cookbook Giveaways http://rickgaribay.net/archive/2012/10/09/windows-server-appfabric-cookbook-giveaways.aspx <p><a href="http://rickgaribay.net/images/rickgaribay_net/Windows-Live-Writer/Windows-Server-AppFabric-Cookbook-Giveaw_BD3E/image_2.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 10px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" align="left" src="http://rickgaribay.net/images/rickgaribay_net/Windows-Live-Writer/Windows-Server-AppFabric-Cookbook-Giveaw_BD3E/image_thumb.png" width="95" height="116" /></a>My friend, and fellow <a href="https://mvp.support.microsoft.com/profile=CDD45B0A-BB05-44F2-A674-B7874CA4D185" target="_blank">Microsoft Integration MVP</a> <a href="twitter.com/@steefjan" target="_blank">Steef-Jan Wiggers</a> has been kind enough to organize a giveaway for my new book <a href="http://www.packtpub.com/microsoft-windows-server-appfabric-cookbook/book" target="_blank">Windows Server AppFabric Cookbook</a>.<a href="http://www.packtpub.com/"><img style="display: inline; float: right" align="right" src="http://www.emanueleferonato.com/wp-content/uploads/2010/09/packt.png" width="115" height="64" /></a></p> <p>You can learn more details about the contest on his blog: <a title="http://soa-thoughts.blogspot.nl/2012/10/microsoft-windows-server-appfabric.html" href="http://soa-thoughts.blogspot.nl/2012/10/microsoft-windows-server-appfabric.html">http://soa-thoughts.blogspot.nl/2012/10/microsoft-windows-server-appfabric.html</a></p> <p>In addition, I’m happy to announce that <a href="http://neudesic.com" target="_blank">Neudesic</a> has teamed up with <a href="http://www.packtpub.com/">Packt Publishing</a> to give away one e-book each week from 10/22 – 11/12 for a total of 3 winners. Be sure to follow <a href="http://twitter.com/neudesic" target="_blank">Neudesic</a> on twitter and stay tuned for rules and regulations beginning on Monday, October 15th. </p> <p>As I shared in <a href="http://rickgaribay.net/archive/2012/07/26/windows-server-appfabric-cookbook-is-out.aspx">my thoughts</a> when I announced the first run of the book, our goal with this book was not to promote the latest shiny object but instead to apply nearly two years of experience into a concise reference that could benefit organizations and the community tasks with building lightweight integration solutions on-premise today. As such, my hope is that what you will find is a <a href="http://neudesic.com"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="neudesic" border="0" alt="neudesic" align="right" src="http://rickgaribay.net/images/rickgaribay_net/Windows-Live-Writer/Windows-Server-AppFabric-Cookbook-Giveaw_BD3E/neudesic_6.jpg" width="160" height="70" /></a>trusty field guide rich with simple to follow guidance for enhancing your career as a WCF and WF developer, architect or administrator. </p> <p>I’d like to thank Steef-Jan and the community for the overwhelmingly positive response to the book so far. Hammad and I worked very hard for nearly a year on this project and it is incredibly rewarding to see praise from world renowned thought leaders in the integration space like Steef-Jan, <a href="http://seroter.wordpress.com/2012/09/14/book-review-microsoft-windows-server-appfabric-cookbook/" target="_blank">Richard Seroter</a> and others who have been very kind in validating our efforts.</p> <p>You can learn more about the book on <a href="http://www.packtpub.com/microsoft-windows-server-appfabric-cookbook/book" target="_blank">Packt’s website</a> or <a href="http://www.amazon.com/Microsoft-Windows-Server-AppFabric-Cookbook/dp/1849684189/ref=sr_1_1?ie=UTF8&amp;qid=1349814924&amp;sr=8-1&amp;keywords=windows+server+appfabric+cookbook" target="_blank">Amazon.com</a>.</p><img src="http://rickgaribay.net/aggbug/346.aspx" width="1" height="1" /> Rick G. Garibay http://rickgaribay.net/archive/2012/10/09/windows-server-appfabric-cookbook-giveaways.aspx Tue, 09 Oct 2012 21:03:57 GMT http://rickgaribay.net/archive/2012/10/09/windows-server-appfabric-cookbook-giveaways.aspx#feedback http://rickgaribay.net/comments/commentRss/346.aspx http://rickgaribay.net/services/trackbacks/346.aspx Windows Server AppFabric Cookbook is Out! http://rickgaribay.net/archive/2012/07/26/windows-server-appfabric-cookbook-is-out.aspx <p>I'm very pleased to announce the release of my new book "Windows Server AppFabric Cookbook" which hit distribution today, July 26, 2012. <a href="http://www.packtpub.com/microsoft-windows-server-appfabric-cookbook/book"><img style="margin: 5px; display: inline; float: right" alt="Microsoft Windows Server AppFabric Cookbook" align="right" src="http://www.packtpub.com/sites/default/files/4187EN_Microsoft%20Windows%20Server%20AppFabric%20Cookbook.jpg" width="357" height="454" /></a></p> <p>Before I get into the details of the book, I want to start by thanking my co-author and friend <a href="http://twitter.com/HammadRajjoub">Hammad Rajjoub</a> for inviting me to participate in this project and trusting me to help carry out his vision for this book. Hammad and I both share a labor of love as it applies to the Microsoft distributed technology stack affectionately (and somewhat nostalgically) known as "Connected Systems" and this project represents nearly a year of work in bringing our collective experience to bear in this book. </p> <p>I would also like to express my appreciation to Adnan Masood and Zubair Ahmed who volunteered their time despite extremely busy schedules reviewing the book as it progressed and providing very valuable technical feedback along the way. Their time and dedication has contributed immensely to the quality of the book and any errors or things we've overlooked are our fault alone. </p> <p>Last but not least, I'd like to thank Ron Jacobs at Microsoft for writing the foreword to the book and providing his support and encouragement along the way.</p> <p><strong><font size="3">Why this book and why now?</font></strong></p> <p>It's hard to believe that Dublin has been in the wild for just over 2 years. The first release of <a href="http://www.microsoft.com/en-us/server-cloud/windows-server/appfabric.aspx">Windows Server AppFabric</a> went to GA in June, 2010 at TechEd in New Orleans (I remember how much fun I had demoing the features at the Microsoft booth during my shifts that seemed to fly by) and signaled an exciting shift in Microsoft's middleware strategy that continues today. Late last year, Microsoft added new caching features and made some branding changes to "<a href="http://msdn.microsoft.com/en-us/windowsserver/ee695849.aspx">AppFabric 1.1 for Windows Server</a>" to align with the the next wave of on-premise capabilities which further extend and build upon the Windows Server platform. Just last week, two new capabilities have shipped in beta which compliment AppFabric on premise: <a href="http://www.microsoft.com/en-us/download/details.aspx?id=30376">Service Bus 1.0 Beta for Windows Server</a> and <a href="http://www.microsoft.com/en-us/download/details.aspx?id=30369">Workflow 1.0 Beta for Windows Server</a>.</p> <p>Hammad and I are fortunate to have both worked very closely with Microsoft during the development of "Dublin", participating in software design reviews and early incubation initiatives. Since its release just over two years ago, we've advised customers of all shapes and sizes and fielded these capabilities in countless projects across various verticals. And herein lies the mission of this book: </p> <blockquote> <p><em><strong>To provide practical, real-world guidance for making the most of the capabilities offered by Windows Server AppFabric and AppFabric 1.1 for Windows Server based on our collective experiences in the field over the last two years since it's release. </strong></em></p> </blockquote> <p>The result (we hope) is not just a book, but a field manual chock-full of practical step-by-step, real-world guidance, tips and techniques that will help you build more maintainable, scalable, reliable, and secure service-oriented applications on the Windows Server Platform today. </p> <p><strong><font size="3">What is Windows Server AppFabric/AppFabric 1.1 for Windows Server?</font></strong></p> <p>Windows Server AppFabric is an extension of the Application Server Role on the Windows Server Platform. In a nutshell, Windows Server AppFabric frees Windows Communication Foundation (WCF) and Windows Workflow Foundation (WF) Service developers from common infrastructure plumbing by providing a robust, secure, composable, and reliable platform which provides caching, hosting, and monitoring capabilities, including support for long running workflow services, all on the Windows Platform. As such, Windows Server AppFabric is an evolution of the Windows Server platform, providing essential building blocks for first-classing WCF (for code-based services) and WF (for declarative workflow services) that are built using the .NET Framework 4 and Visual Studio 2010. <br />As an extension to IIS and WAS, Windows Server AppFabric relies on IIS's proven capabilities for hosting and lifecycle management, adding additional useful capabilities for working with WCF and WF services. In addition, Windows Server AppFabric takes advantage of Windows Server's robust event tracing mechanism (also known as ETW). ETW provides optimized <br />and high-performing kernel-level instrumentation which greatly minimizes impact on the performance of WCF and WF services hosted in IIS with Windows Server AppFabric.</p> <p>Best of all, this key extension to the Windows Server Platform remains available <a href="http://www.microsoft.com/en-us/download/details.aspx?id=27115">free of charge</a>.</p> <p>Below are some helpful resources if you are interested in learning more:</p> <ul> <li><a href="http://msdn.microsoft.com/en-us/windowsserver/gg675185"><font color="#ffc000">Developer Introduction to Windows Server AppFabric (Part 1): Hosting Services</font></a> </li> <li><a href="http://msdn.microsoft.com/en-us/windowsserver/gg675186"><font color="#ffc000">Developer Introduction to Windows Server AppFabric (Part 2): Caching Services</font></a> </li> <li><a href="http://msdn.microsoft.com/en-us/library/hh351389.aspx"><font color="#ffc000">Product Documentation</font></a> </li> <li><a href="http://go.microsoft.com/fwlink/?LinkID=168906"><font color="#ffc000">Architectural Overview</font></a> </li> <li><a href="http://go.microsoft.com/fwlink/?LinkID=168903"><font color="#ffc000">Tutorials</font></a> </li> <li><a href="http://social.technet.microsoft.com/wiki/contents/articles/windows-server-appfabric-portal.aspx"><font color="#ffc000">AppFabric on the TechNet Wiki</font></a> </li> </ul> <p><strong><font size="3">Is this book for you?</font></strong></p> <p>If you are a developer who wants to avoid the same repetitive tasks when preparing your WCF and/or WF services for deployment, or an IT Pro who wants to avoid complex XML for configuring hosting and monitoring options for the services you manage, you will instantly benefit from Windows Server AppFabric.</p> <p>The book is over 400 pages long and includes over 60 recipes within 9 cohesive chapters:</p> <ul> <li><strong>Chapter 1</strong>, Installing Windows Server AppFabric, covers setting up your development environment to use Windows Server AppFabric. You'll learn how to install hosting, persistence and monitoring capabilities, including provisioning repositories, choosing the appropriate storage options, making changes to configuration after installation, and troubleshooting common (and not so common) installation issues you might encounter along the way. <br /></li> <li><strong>Chapter 2</strong>, Getting Started with AppFabric Caching, introduces Caching in Windows Server AppFabric, covering everything you need to get started with introducing this important capability to your composite applications and services. You will learn how to set up and use Caching using code and configuration options, as well as working with Caching within your applications. In addition, you'll learn how easily an existing application that relies on ASP.NET session state can immediately benefit from Windows Server AppFabric Cache, handling common error conditions, using PowerShell commandlets, and building a custom provider model. <br /></li> <li><strong>Chapter 3</strong>, Windows Server AppFabric Caching – Advanced Use Cases, builds on the concepts in the previous chapter, covering the use of Regions and Tags as well as choosing the right concurrency mode and establishing expiration, eviction, and notification policies. You will also learn advanced monitoring concepts including the use of performance counters, configuring high availability, and common troubleshooting techniques for getting the most out of Windows Server AppFabric Cache. <br /></li> <li><strong>Chapter 4</strong>, Windows Server AppFabric Hosting Fundamentals, introduces Windows Server AppFabric's hosting capabilities, covering common deployment, management, and hosting scenarios. You'll learn how to host WCF SOAP and REST services as well as simple WF services along with a number of tips and tricks for moving beyond the service template defaults. <br /></li> <li><strong>Chapter 5</strong>, More Windows Server AppFabric Hosting Features, covers additional hosting topics, including supporting long-running WF services, how your services can benefit from the Auto-Start feature, properly hosting WCF services that take advantage of Windows Azure Service Bus Relay bindings for enabling modern, hybrid scenarios as well as common PowerShell commandlets for scripting many of the tasks covered in this and the previous chapter. <br /></li> <li><strong>Chapter 6</strong>, Utilizing AppFabric Persistence, provides ample coverage of Windows Server AppFabric persistence capabilities, including configuring persistence for WF services, working with multiple persistence stores, and developing instance store, control, and query providers. This chapter also provides an in-depth walkthrough of development and configuration of custom instance, control, and query providers. <br /></li> <li><strong>Chapter 7</strong>, Monitoring Windows Server AppFabric Deployment, provides an introduction to <br />the monitoring capabilities provided by Windows Server AppFabric. Topics include collecting and viewing events from WCF and WF services, enabling tracing and configuring tracking profiles, and leveraging PowerShell cmdlets for monitoring WCF and WF services as well as the Caching service. In addition, you'll learn how to surface monitoring information to any user experience by following the sample recipe for building a custom monitoring dashboard using ASP.NET MVC and OData. <br /></li> <li><strong>Chapter 8</strong>, Scaling AppFabric Hosting, Monitoring, and Persistence, covers a common scenario for scaling Windows Server AppFabric across multiple IIS hosts. You will learn how to prepare two hosts for clustering using Microsoft NLB as well as understand deployment, management, and administration of a multi-host Windows Server AppFabric deployment that shares a common, centralized persistence store. <br /></li> <li><strong>Chapter 9</strong>, Configuring Windows Server AppFabric Security, covers what you need to know about planning and implementing a security model with Windows Server AppFabric. You will learn how to secure the caching, persistence, monitoring, and eventing (via ETW) subsystems of Windows Server AppFabric. </li> </ul> <p>If you've gotten this far, I sincerely appreciate your interest and hope you’ll consider purchasing our book ;-)</p> <p>The book is available in print and across most digital formats including Kindle, Nook, etc.:</p> <p>Packt is running some specials on the book which you can learn more about here: <a title="http://www.packtpub.com/microsoft-windows-server-appfabric-cookbook/book" href="http://www.packtpub.com/microsoft-windows-server-appfabric-cookbook/book">http://www.packtpub.com/microsoft-windows-server-appfabric-cookbook/book</a></p> <p>The book is also available on <a href="http://www.amazon.com/Microsoft-Windows-Server-AppFabric-Cookbook/dp/1849684189/ref=sr_1_sc_1?ie=UTF8&amp;qid=1343337928&amp;sr=8-1-spell&amp;keywords=windows+server+appfabic+cookbook">Amazon.com</a>, <a href="http://www.amazon.co.uk/Microsoft-Windows-Server-AppFabric-Cookbook/dp/1849684189/ref=sr_1_1?ie=UTF8&amp;qid=1343337985&amp;sr=8-1">Amazon.co.uk</a> and <a href="http://www.barnesandnoble.com/s/windows-server-appfabric-cookbook?store=allproducts&amp;keyword=windows+server+appfabric+cookbook">Barnes and Noble</a> (if the book is not immediately available, I’m told by the publisher that all shipments are en-route so any shipping delays should be minimal).</p> <p>If you purchase the book, I'd love to hear from you. Please <a href="http://rickgaribay.net/contact.aspx">drop me a line</a> or connect with me <a href="http://twitter.com/rickggaribay">@rickggaribay</a> and let me know what you think. </p> <ul></ul> <p>References:</p> <ul> <li><a href="http://www.microsoft.com/en-us/download/details.aspx?displaylang=en&amp;id=15848">Windows Server AppFabric 1.0</a></li> <li><a href="http://www.microsoft.com/en-us/download/details.aspx?id=27115">AppFabric 1.0 for Windows Server</a></li> <li><a href="http://www.microsoft.com/en-us/download/details.aspx?id=30376">Service Bus 1.0 Beta for Windows Server</a></li> <li><a href="http://www.microsoft.com/en-us/download/details.aspx?id=30369">Workflow 1.0 Beta for Windows Server</a></li> <li><a href="http://hammadrajjoub.net/2012/03/03/have-you-booked-your-copy-of-windows-server-appfabric-cookbook-yet/">Hammad Rajjoub’s Blog</a></li> <li><a href="http://blog.adnanmasood.com/2012/01/03/microsoft-windows-server-appfabric-cookbook-available-for-pre-order/">Adnan Masood’s Blog</a></li> <li><a href="http://soa-thoughts.blogspot.com/2012/04/more-cookbooks-microsoft-windows-server.html">Steef-Jan Wiggers’ Blog</a></li> <li><a href="http://jeremiedevillard.wordpress.com/2012/04/07/windows-server-appfabric-and-biztalk-cookbook/">Jeremie Devillad’s Blog</a></li> <li><a href="http://paulsomers.blogspot.com/2012/03/windows-server-appfabric-cookbook.html">Paul Somer’s Blog</a> </li> </ul><img src="http://rickgaribay.net/aggbug/340.aspx" width="1" height="1" /> Rick G. Garibay http://rickgaribay.net/archive/2012/07/26/windows-server-appfabric-cookbook-is-out.aspx Thu, 26 Jul 2012 22:12:56 GMT http://rickgaribay.net/archive/2012/07/26/windows-server-appfabric-cookbook-is-out.aspx#feedback 3 http://rickgaribay.net/comments/commentRss/340.aspx http://rickgaribay.net/services/trackbacks/340.aspx Common Service Bus Queue Operations with the REST API http://rickgaribay.net/archive/2012/01/19/common-service-bus-queue-operations-with-the-rest-api.aspx <p>Azure Service Bus Brokered Messaging provides durable pull-based pub-sub, complimenting it’s older sibling Relay Messaging which uses a push messaging model. While both enable hybrid composition across traditional business, trust and network boundaries, they provide unique capabilities in and of themselves. </p> <p>As with Relay Messaging, Brokered Messaging provides first class support for WCF with the NetMessagingBinding, but expands the developer surface to general .NET and cross-platform/mobility scenarios by offering the .NET Client and REST API respectively.</p> <p>Of the 3 APIs, the .NET Client API is the most robust and seems to be the most documented.</p> <p>The simplicity of the WCF programming model (the illusion that messages are being pushed to your endpoint) is balanced with some restrictions that naturally fall out of the scope of one-way messaging including queue/topic/subscription/rule creation and support for peek lock.</p> <p>In this regard, while not as robust as the .NET Client API, the REST API offers a more comprehensive feature set and when working on solutions that must be interoperable across client platforms or due to other restrictions, the REST API is a great choice.</p> <p>Microsoft has documented the REST API in the <a href="http://msdn.microsoft.com/en-us/library/windowsazure/hh367521.aspx#BKMK_REST5prod" target="_blank">Service Bus REST API Reference</a>, but there are not a ton of imperative examples out there that show WebClient or HttpWebRequest, so the purpose of this post is to share some nitty gritty examples of how to get some of the most common operations done in C#.</p> <p>Please note that my goal is not to be elegant or use the tersest or most fluid syntax possible in this samples, but rather to get some quick and dirty examples out there, well, quickly. </p> <p>As such, the unit tests should be self explanatory, but if you have any questions, please don’t hesitate to ask. </p> <p>Feedback, comments related to the API or WebClient techniques welcome <img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://rickgaribay.net/Images/customcontent/Common-Service-Bus-Patterns-with-the-RES_795D/wlEmoticon-smile.png" /></p> <div class="csharpcode"> <pre class="alt"><span class="lnum"> 1: </span><span class="kwrd">using</span> System;</pre> <pre><span class="lnum"> 2: </span><span class="kwrd">using</span> System.Text;</pre> <pre class="alt"><span class="lnum"> 3: </span><span class="kwrd">using</span> System.Collections.Generic;</pre> <pre><span class="lnum"> 4: </span><span class="kwrd">using</span> System.Linq;</pre> <pre class="alt"><span class="lnum"> 5: </span><span class="kwrd">using</span> Microsoft.VisualStudio.TestTools.UnitTesting;</pre> <pre><span class="lnum"> 6: </span><span class="kwrd">using</span> System.Collections.Specialized;</pre> <pre class="alt"><span class="lnum"> 7: </span><span class="kwrd">using</span> System.Net;</pre> <pre><span class="lnum"> 8: </span><span class="kwrd">using</span> System.Runtime.Serialization.Json;</pre> <pre class="alt"><span class="lnum"> 9: </span><span class="kwrd">using</span> System.Runtime.Serialization;</pre> <pre><span class="lnum"> 10: </span><span class="kwrd">using</span> System.IO;</pre> <pre class="alt"><span class="lnum"> 11: </span> </pre> <pre><span class="lnum"> 12: </span><span class="kwrd">namespace</span> RESTAPITests</pre> <pre class="alt"><span class="lnum"> 13: </span>{</pre> <pre><span class="lnum"> 14: </span> [TestClass]</pre> <pre class="alt"><span class="lnum"> 15: </span> <span class="kwrd">public</span> <span class="kwrd">class</span> RESTAPITests</pre> <pre><span class="lnum"> 16: </span> {</pre> <pre class="alt"><span class="lnum"> 17: </span> </pre> <pre><span class="lnum"> 18: </span> <span class="kwrd">static</span> <span class="kwrd">string</span> serviceNamespace = <span class="str">"[NAMESPACE]"</span>;</pre> <pre class="alt"><span class="lnum"> 19: </span> <span class="kwrd">static</span> <span class="kwrd">string</span> issuerName = <span class="str">"owner"</span>;</pre> <pre><span class="lnum"> 20: </span> <span class="kwrd">static</span> <span class="kwrd">string</span> issuerSecret = <span class="str">"[KEY]"</span>;</pre> <pre class="alt"><span class="lnum"> 21: </span> <span class="kwrd">const</span> <span class="kwrd">string</span> sbHostName = <span class="str">"servicebus.windows.net"</span>;</pre> <pre><span class="lnum"> 22: </span> <span class="kwrd">const</span> <span class="kwrd">string</span> acsHostName = <span class="str">"accesscontrol.windows.net"</span>;</pre> <pre class="alt"><span class="lnum"> 23: </span> <span class="kwrd">static</span> <span class="kwrd">string</span> relativeAddress = <span class="str">"[Queue]"</span>;</pre> <pre><span class="lnum"> 24: </span> <span class="kwrd">static</span> <span class="kwrd">string</span> baseAddress;</pre> <pre class="alt"><span class="lnum"> 25: </span> </pre> <pre><span class="lnum"> 26: </span> </pre> <pre class="alt"><span class="lnum"> 27: </span> [TestMethod]</pre> <pre><span class="lnum"> 28: </span> <span class="kwrd">public</span> <span class="kwrd">void</span> SendMessageShouldSucceedWithoutError()</pre> <pre class="alt"><span class="lnum"> 29: </span> {</pre> <pre><span class="lnum"> 30: </span> <span class="kwrd">string</span> body = <span class="str">"foo"</span>;</pre> <pre class="alt"><span class="lnum"> 31: </span> </pre> <pre><span class="lnum"> 32: </span> var token = GetToken(issuerName, issuerSecret);</pre> <pre class="alt"><span class="lnum"> 33: </span> </pre> <pre><span class="lnum"> 34: </span> baseAddress = GetBaseAddress();</pre> <pre class="alt"><span class="lnum"> 35: </span> <span class="kwrd">string</span> fullAddress = baseAddress + relativeAddress + <span class="str">"/messages"</span>;</pre> <pre><span class="lnum"> 36: </span> </pre> <pre class="alt"><span class="lnum"> 37: </span> WebClient webClient = <span class="kwrd">new</span> WebClient();</pre> <pre><span class="lnum"> 38: </span> webClient.Headers[HttpRequestHeader.Authorization] = token;</pre> <pre class="alt"><span class="lnum"> 39: </span> webClient.UploadData(fullAddress, <span class="str">"POST"</span>, Encoding.UTF8.GetBytes(body)); </pre> <pre><span class="lnum"> 40: </span> </pre> <pre class="alt"><span class="lnum"> 41: </span> }</pre> <pre><span class="lnum"> 42: </span> </pre> <pre class="alt"><span class="lnum"> 43: </span> [TestMethod]</pre> <pre><span class="lnum"> 44: </span> <span class="kwrd">public</span> <span class="kwrd">void</span> PeekLockMessageShouldReturnLockId()</pre> <pre class="alt"><span class="lnum"> 45: </span> {</pre> <pre><span class="lnum"> 46: </span> var token = GetToken(issuerName, issuerSecret);</pre> <pre class="alt"><span class="lnum"> 47: </span> </pre> <pre><span class="lnum"> 48: </span> baseAddress = GetBaseAddress();</pre> <pre class="alt"><span class="lnum"> 49: </span> </pre> <pre><span class="lnum"> 50: </span> <span class="rem">// Read and lock the message. Unless released, the lock will expire within the configured lock duration (on the queue)</span></pre> <pre class="alt"><span class="lnum"> 51: </span> <span class="kwrd">string</span> fullAddress = baseAddress + relativeAddress + <span class="str">"/messages/head"</span>;</pre> <pre><span class="lnum"> 52: </span> </pre> <pre class="alt"><span class="lnum"> 53: </span> WebClient webClient = <span class="kwrd">new</span> WebClient();</pre> <pre><span class="lnum"> 54: </span> webClient.Headers[HttpRequestHeader.Authorization] = token;</pre> <pre class="alt"><span class="lnum"> 55: </span> webClient.UploadData(fullAddress, <span class="str">"POST"</span>, <span class="kwrd">new</span> <span class="kwrd">byte</span>[0]{});</pre> <pre><span class="lnum"> 56: </span> </pre> <pre class="alt"><span class="lnum"> 57: </span> var props = webClient.ResponseHeaders[<span class="str">"BrokerProperties"</span>];</pre> <pre><span class="lnum"> 58: </span> </pre> <pre class="alt"><span class="lnum"> 59: </span> <span class="rem">// Deserialize the JSON header to a simple class</span></pre> <pre><span class="lnum"> 60: </span> DataContractJsonSerializer serializer = <span class="kwrd">new</span> DataContractJsonSerializer(<span class="kwrd">typeof</span>(BrokerProperty));</pre> <pre class="alt"><span class="lnum"> 61: </span> <span class="kwrd">using</span> (MemoryStream stream = <span class="kwrd">new</span> MemoryStream(Encoding.Unicode.GetBytes(props)))</pre> <pre><span class="lnum"> 62: </span> {</pre> <pre class="alt"><span class="lnum"> 63: </span> var result = (BrokerProperty)serializer.ReadObject(stream);</pre> <pre><span class="lnum"> 64: </span> </pre> <pre class="alt"><span class="lnum"> 65: </span> Assert.IsNotNull(result.LockToken); </pre> <pre><span class="lnum"> 66: </span> }</pre> <pre class="alt"><span class="lnum"> 67: </span> </pre> <pre><span class="lnum"> 68: </span> }</pre> <pre class="alt"><span class="lnum"> 69: </span> </pre> <pre><span class="lnum"> 70: </span> [TestMethod]</pre> <pre class="alt"><span class="lnum"> 71: </span> <span class="kwrd">public</span> <span class="kwrd">void</span> PeekLockMessageAndAbandonShouldSucceed()</pre> <pre><span class="lnum"> 72: </span> {</pre> <pre class="alt"><span class="lnum"> 73: </span> var token = GetToken(issuerName, issuerSecret);</pre> <pre><span class="lnum"> 74: </span> </pre> <pre class="alt"><span class="lnum"> 75: </span> baseAddress = GetBaseAddress();</pre> <pre><span class="lnum"> 76: </span> </pre> <pre class="alt"><span class="lnum"> 77: </span> <span class="rem">// Read and lock the message. Unless released, the lock will expire within the configured lock duration (on the queue)</span></pre> <pre><span class="lnum"> 78: </span> <span class="kwrd">string</span> fullAddress = baseAddress + relativeAddress + <span class="str">"/messages/head"</span>;</pre> <pre class="alt"><span class="lnum"> 79: </span> </pre> <pre><span class="lnum"> 80: </span> WebClient webClient = <span class="kwrd">new</span> WebClient();</pre> <pre class="alt"><span class="lnum"> 81: </span> webClient.Headers[HttpRequestHeader.Authorization] = token;</pre> <pre><span class="lnum"> 82: </span> webClient.UploadData(fullAddress, <span class="str">"POST"</span>, <span class="kwrd">new</span> <span class="kwrd">byte</span>[0] { });</pre> <pre class="alt"><span class="lnum"> 83: </span> </pre> <pre><span class="lnum"> 84: </span> var props = webClient.ResponseHeaders[<span class="str">"BrokerProperties"</span>];</pre> <pre class="alt"><span class="lnum"> 85: </span> </pre> <pre><span class="lnum"> 86: </span> <span class="rem">// Deserialize the JSON header to a simple class</span></pre> <pre class="alt"><span class="lnum"> 87: </span> DataContractJsonSerializer serializer = <span class="kwrd">new</span> DataContractJsonSerializer(<span class="kwrd">typeof</span>(BrokerProperty));</pre> <pre><span class="lnum"> 88: </span> </pre> <pre class="alt"><span class="lnum"> 89: </span> <span class="kwrd">using</span> (MemoryStream stream = <span class="kwrd">new</span> MemoryStream(Encoding.Unicode.GetBytes(props)))</pre> <pre><span class="lnum"> 90: </span> {</pre> <pre class="alt"><span class="lnum"> 91: </span> var result = (BrokerProperty)serializer.ReadObject(stream);</pre> <pre><span class="lnum"> 92: </span> </pre> <pre class="alt"><span class="lnum"> 93: </span> <span class="rem">// Bail on the message, release the lock so it is available for another consumer</span></pre> <pre><span class="lnum"> 94: </span> fullAddress = baseAddress + relativeAddress + String.Format(<span class="str">"/messages/{0}/{1}"</span>, result.MessageId, result.LockToken);</pre> <pre class="alt"><span class="lnum"> 95: </span> }</pre> <pre><span class="lnum"> 96: </span> </pre> <pre class="alt"><span class="lnum"> 97: </span> webClient = <span class="kwrd">new</span> WebClient();</pre> <pre><span class="lnum"> 98: </span> webClient.Headers[HttpRequestHeader.Authorization] = token;</pre> <pre class="alt"><span class="lnum"> 99: </span> webClient.UploadData(fullAddress, <span class="str">"PUT"</span>, <span class="kwrd">new</span> <span class="kwrd">byte</span>[0] { });</pre> <pre><span class="lnum"> 100: </span> </pre> <pre class="alt"><span class="lnum"> 101: </span> }</pre> <pre><span class="lnum"> 102: </span> </pre> <pre class="alt"><span class="lnum"> 103: </span> [TestMethod]</pre> <pre><span class="lnum"> 104: </span> <span class="kwrd">public</span> <span class="kwrd">void</span> PeekLockMessageAndCompleteShouldSucceed()</pre> <pre class="alt"><span class="lnum"> 105: </span> {</pre> <pre><span class="lnum"> 106: </span> var token = GetToken(issuerName, issuerSecret);</pre> <pre class="alt"><span class="lnum"> 107: </span> </pre> <pre><span class="lnum"> 108: </span> baseAddress = GetBaseAddress();</pre> <pre class="alt"><span class="lnum"> 109: </span> </pre> <pre><span class="lnum"> 110: </span> <span class="rem">// Peek lock the message</span></pre> <pre class="alt"><span class="lnum"> 111: </span> <span class="kwrd">string</span> fullAddress = baseAddress + relativeAddress + <span class="str">"/messages/head"</span>;</pre> <pre><span class="lnum"> 112: </span> </pre> <pre class="alt"><span class="lnum"> 113: </span> WebClient webClient = <span class="kwrd">new</span> WebClient();</pre> <pre><span class="lnum"> 114: </span> webClient.Headers[HttpRequestHeader.Authorization] = token;</pre> <pre class="alt"><span class="lnum"> 115: </span> webClient.UploadData(fullAddress, <span class="str">"POST"</span>, <span class="kwrd">new</span> <span class="kwrd">byte</span>[0] { });</pre> <pre><span class="lnum"> 116: </span> </pre> <pre class="alt"><span class="lnum"> 117: </span> var props = webClient.ResponseHeaders[<span class="str">"BrokerProperties"</span>];</pre> <pre><span class="lnum"> 118: </span> </pre> <pre class="alt"><span class="lnum"> 119: </span> DataContractJsonSerializer serializer = <span class="kwrd">new</span> DataContractJsonSerializer(<span class="kwrd">typeof</span>(BrokerProperty));</pre> <pre><span class="lnum"> 120: </span> </pre> <pre class="alt"><span class="lnum"> 121: </span> <span class="kwrd">using</span> (MemoryStream stream = <span class="kwrd">new</span> MemoryStream(Encoding.Unicode.GetBytes(props)))</pre> <pre><span class="lnum"> 122: </span> {</pre> <pre class="alt"><span class="lnum"> 123: </span> var result = (BrokerProperty)serializer.ReadObject(stream);</pre> <pre><span class="lnum"> 124: </span> </pre> <pre class="alt"><span class="lnum"> 125: </span> <span class="rem">// Complete the read operation, releasing the lock and deleting the message from the queue</span></pre> <pre><span class="lnum"> 126: </span> fullAddress = baseAddress + relativeAddress + String.Format(<span class="str">"/messages/{0}/{1}"</span>, result.MessageId, result.LockToken);</pre> <pre class="alt"><span class="lnum"> 127: </span> }</pre> <pre><span class="lnum"> 128: </span> webClient = <span class="kwrd">new</span> WebClient();</pre> <pre class="alt"><span class="lnum"> 129: </span> webClient.Headers[HttpRequestHeader.Authorization] = token;</pre> <pre><span class="lnum"> 130: </span> webClient.UploadData(fullAddress, <span class="str">"DELETE"</span>, <span class="kwrd">new</span> <span class="kwrd">byte</span>[0] { });</pre> <pre class="alt"><span class="lnum"> 131: </span> }</pre> <pre><span class="lnum"> 132: </span> </pre> <pre class="alt"><span class="lnum"> 133: </span> [TestMethod]</pre> <pre><span class="lnum"> 134: </span> <span class="kwrd">public</span> <span class="kwrd">void</span> DecodeJsonToTypeShouldAllowEasyExtractionOfProps()</pre> <pre class="alt"><span class="lnum"> 135: </span> {</pre> <pre><span class="lnum"> 136: </span> </pre> <pre class="alt"><p><span class="lnum"> 137: </span> <span class="kwrd">string</span> payload = <span class="str">@"{"</span><span class="str">"DeliveryCount"</span><span class="str">":3,"</span><span class="str">"LockToken"</span><span class="str">":"</span><span class="str">"4a1d4c96-9837-42a9-ad91-3ecf704eec40"</span><span class="str">","</span><span class="str">"LockedUntilUtc"</span><span class="str">":"</span><span class="str">"Thu, 19 Jan 2012 01:22:44 GMT"</span><span class="str">",</span></p><p><span class="str"> </span><span class="str">"</span><span class="str">"MessageId"</span><span class="str">":"</span><span class="str">"4a4fa2c7d87a40a7b799625b9de69e42"</span><span class="str">","</span><span class="str">"SequenceNumber"</span><span class="str">":2,"</span><span class="str">"TimeToLive"</span><span class="str">":922337203685}"</span>;</p></pre> <pre><span class="lnum"> 138: </span> </pre> <pre class="alt"><span class="lnum"> 139: </span> DataContractJsonSerializer serializer = <span class="kwrd">new</span> DataContractJsonSerializer(<span class="kwrd">typeof</span>(BrokerProperty));</pre> <pre><span class="lnum"> 140: </span> </pre> <pre class="alt"><span class="lnum"> 141: </span> <span class="kwrd">using</span> (MemoryStream stream = <span class="kwrd">new</span> MemoryStream(Encoding.Unicode.GetBytes(payload)))</pre> <pre><span class="lnum"> 142: </span> {</pre> <pre class="alt"><span class="lnum"> 143: </span> var result = (BrokerProperty)serializer.ReadObject(stream);</pre> <pre><span class="lnum"> 144: </span> </pre> <pre class="alt"><span class="lnum"> 145: </span> Assert.IsNotNull(result.MessageId);</pre> <pre><span class="lnum"> 146: </span> }</pre> <pre class="alt"><span class="lnum"> 147: </span> </pre> <pre><span class="lnum"> 148: </span> }</pre> <pre class="alt"><span class="lnum"> 149: </span> </pre> <pre><span class="lnum"> 150: </span> [DataContract]</pre> <pre class="alt"><span class="lnum"> 151: </span> <span class="kwrd">public</span> <span class="kwrd">class</span> BrokerProperty</pre> <pre><span class="lnum"> 152: </span> {</pre> <pre class="alt"><span class="lnum"> 153: </span> [DataMember]</pre> <pre><span class="lnum"> 154: </span> <span class="kwrd">public</span> <span class="kwrd">string</span> DeliveryCount { get; set; }</pre> <pre class="alt"><span class="lnum"> 155: </span> [DataMember]</pre> <pre><span class="lnum"> 156: </span> <span class="kwrd">public</span> <span class="kwrd">string</span> LockToken { get; set; }</pre> <pre class="alt"><span class="lnum"> 157: </span> [DataMember]</pre> <pre><span class="lnum"> 158: </span> <span class="kwrd">public</span> <span class="kwrd">string</span> LockedUntilUtc { get; set; }</pre> <pre class="alt"><span class="lnum"> 159: </span> [DataMember]</pre> <pre><span class="lnum"> 160: </span> <span class="kwrd">public</span> <span class="kwrd">string</span> MessageId { get; set; }</pre> <pre class="alt"><span class="lnum"> 161: </span> [DataMember]</pre> <pre><span class="lnum"> 162: </span> <span class="kwrd">public</span> <span class="kwrd">string</span> SequenceNumber { get; set; }</pre> <pre class="alt"><span class="lnum"> 163: </span> [DataMember]</pre> <pre><span class="lnum"> 164: </span> <span class="kwrd">public</span> <span class="kwrd">string</span> TimeToLive { get; set; }</pre> <pre class="alt"><span class="lnum"> 165: </span> }</pre> <pre><span class="lnum"> 166: </span> </pre> <pre class="alt"><span class="lnum"> 167: </span> </pre> <pre><span class="lnum"> 168: </span> <span class="rem">// Helper</span></pre> <pre class="alt"><span class="lnum"> 169: </span> <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">string</span> GetBaseAddress()</pre> <pre><span class="lnum"> 170: </span> {</pre> <pre class="alt"><span class="lnum"> 171: </span> <span class="kwrd">return</span> baseAddress = <span class="str">"https://"</span> + serviceNamespace + <span class="str">"."</span> + sbHostName + <span class="str">"/"</span>;</pre> <pre><span class="lnum"> 172: </span> }</pre> <pre class="alt"><span class="lnum"> 173: </span> </pre> <pre><span class="lnum"> 174: </span> <span class="rem">// Helper, warmly borrowed from Service Bus Management Sample :-)</span></pre> <pre class="alt"><span class="lnum"> 175: </span> <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">string</span> GetToken(<span class="kwrd">string</span> issuerName, <span class="kwrd">string</span> issuerSecret)</pre> <pre><span class="lnum"> 176: </span> {</pre> <pre class="alt"><span class="lnum"> 177: </span> var acsEndpoint = <span class="str">"https://"</span> + serviceNamespace + <span class="str">"-sb."</span> + acsHostName + <span class="str">"/WRAPv0.9/"</span>;</pre> <pre><span class="lnum"> 178: </span> </pre> <pre class="alt"><span class="lnum"> 179: </span> <span class="rem">// Note that the realm used when requesting a token uses the HTTP scheme, even though</span></pre> <pre><span class="lnum"> 180: </span> <span class="rem">// calls to the service are always issued over HTTPS</span></pre> <pre class="alt"><span class="lnum"> 181: </span> var realm = <span class="str">"http://"</span> + serviceNamespace + <span class="str">"."</span> + sbHostName + <span class="str">"/"</span>;</pre> <pre><span class="lnum"> 182: </span> </pre> <pre class="alt"><span class="lnum"> 183: </span> NameValueCollection values = <span class="kwrd">new</span> NameValueCollection();</pre> <pre><span class="lnum"> 184: </span> values.Add(<span class="str">"wrap_name"</span>, issuerName);</pre> <pre class="alt"><span class="lnum"> 185: </span> values.Add(<span class="str">"wrap_password"</span>, issuerSecret);</pre> <pre><span class="lnum"> 186: </span> values.Add(<span class="str">"wrap_scope"</span>, realm);</pre> <pre class="alt"><span class="lnum"> 187: </span> </pre> <pre><span class="lnum"> 188: </span> WebClient webClient = <span class="kwrd">new</span> WebClient();</pre> <pre class="alt"><span class="lnum"> 189: </span> <span class="kwrd">byte</span>[] response = webClient.UploadValues(acsEndpoint, values);</pre> <pre><span class="lnum"> 190: </span> </pre> <pre class="alt"><span class="lnum"> 191: </span> <span class="kwrd">string</span> responseString = Encoding.UTF8.GetString(response);</pre> <pre><span class="lnum"> 192: </span> </pre> <pre class="alt"><span class="lnum"> 193: </span> var responseProperties = responseString.Split(<span class="str">'&amp;'</span>);</pre> <pre><span class="lnum"> 194: </span> var tokenProperty = responseProperties[0].Split(<span class="str">'='</span>);</pre> <pre class="alt"><span class="lnum"> 195: </span> var token = Uri.UnescapeDataString(tokenProperty[1]);</pre> <pre><span class="lnum"> 196: </span> </pre> <pre class="alt"><span class="lnum"> 197: </span> <span class="kwrd">return</span> <span class="str">"WRAP access_token=\""</span> + token + <span class="str">"\""</span>;</pre> <pre><span class="lnum"> 198: </span> }</pre> <pre class="alt"><span class="lnum"> 199: </span> </pre> <pre><span class="lnum"> 200: </span> }</pre> <pre class="alt"><span class="lnum"> 201: </span> </pre> <pre><span class="lnum"> 202: </span>}</pre> </div> <style type="text/css"><![CDATA[ .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }]]></style><img src="http://rickgaribay.net/aggbug/326.aspx" width="1" height="1" /> Rick G. Garibay http://rickgaribay.net/archive/2012/01/19/common-service-bus-queue-operations-with-the-rest-api.aspx Thu, 19 Jan 2012 16:23:08 GMT http://rickgaribay.net/archive/2012/01/19/common-service-bus-queue-operations-with-the-rest-api.aspx#feedback http://rickgaribay.net/comments/commentRss/326.aspx http://rickgaribay.net/services/trackbacks/326.aspx Azure Service Bus Connect EAI and EDI &ldquo;Integration Services&rdquo; CTP http://rickgaribay.net/archive/2011/12/16/azure-service-bus-connect-eai-and-edi-ldquointegration-servicesrdquo-ctp.aspx <p>I am thrilled to share in the <a href="http://blogs.msdn.com/b/windowsazure/archive/2011/12/16/announcing-the-service-bus-eai-amp-edi-labs-release.aspx" target="_blank">announcement</a> that the first public CTP of Azure Service Bus Integration Services<strong> is now LIVE</strong> at <a href="http://portal.appfabriclabs.com">http://portal.appfabriclabs.com</a>. </p> <p>The focus of this release is to enable you to build hybrid composite solutions that span on-premise investments such as Microsoft SQL Server, Oracle Database, SAP, Siebel eBusiness Applications, Oracle E-Business Suite, allowing you to compose these mission critical systems with applications, assets and workloads that you have deployed to Windows Azure, enabling first-class hybrid integration across traditional network and trust boundaries. </p> <p>In a web to web world, many of the frictions addressed in these capabilities still exist, albeit to a smaller degree. The reality is that as the web and cloud computing continue to gain momentum, investments on-premise are, and will continue to be critical to realizing the full spectrum of benefits that cloud computing provides both in the short and long term. </p> <p>So, what’s in this CTP?</p> <p><a href="http://msdn.microsoft.com/en-us/library/windowsazure/hh689889.aspx" target="_blank">Azure Service Bus Connect</a> provides a new server explorer experience for LOB integration exposing a management head that can be accessed on-prem via Server Explorer or PowerShell to create, update, delete or retrieve information from LOB targets. This provides a robust extension of the Azure Service Bus relay endpoint concept, which acts a LOB conduit (LobTarget, LobRelay) for bridging these assets by extending the WCF LOB Adapters that ship with BizTalk Server 2010. The beauty of this approach is that you can leverage the LOB Adapters using BizTalk as a host, or, for a lighter weight way approach, use IIS/Windows Server AppFabric to compose business operations on-premise and beyond. </p> <p>In addition, support for messaging between trading partners across traditional trust boundaries in business-to-business (B2B) scenarios using is EDI is also provided in this preview, including AS2 protocol support with X12 chaining for send and receive pipelines, FTP as transport for X12, agreement templates, partners view with profiles per partner, resources view, and an intuitive, metro style <a href="http://i.msdn.microsoft.com/dynimg/IC553343.gif">EDI Portal<img style="display: inline; float: right" title="Transforms Project Design Surface" alt="Transforms Project Design Surface" align="right" src="http://i.msdn.microsoft.com/dynimg/IC553343.gif" width="240" height="165" /></a>.</p> <p>Just as with on-premise integration, friction always exists when integrating different assets which may exist on different platforms, implement different standards and at a minimum have different representations of common entities that are part of your composite solution’s domain. What is needed is a mediation broker that can be leveraged at internet-scale, and apply message and protocol transformations across disparate parties and this is exactly what the <a href="http://msdn.microsoft.com/en-us/library/windowsazure/hh689905.aspx" target="_blank">Transforms</a> capability provides. Taking an approach that will be immediately familiar to the BizTalk developer, a familiar mapper-like experience is provided within Visual Studio for interactively mapping message elements and applying additional processing logic via operations (functoids).</p> <p>In addition, <a href="http://msdn.microsoft.com/en-us/library/windowsazure/hh689768.aspx" target="_blank">XML Bridges</a> which include the XML One-Way Bridge and XML Request-Reply Bridge are an extension to the Azure Service Bus which supports critical patterns such as protocol bridging, routing actions, external data lookup for message enrichment and support for both WS-I and REST endpoints and any combination thereof.</p> <p>As shown below in the MSDN documentation, “bridges are composed of stages and activities where each stage is a message processing unit in itself. Each stage of a bridge is atomic, which means either a message completes a stage or not. A stage can be turned <em>on</em> or <em>off</em>, indicating whether to process a message or simply let it <em>pass through”</em>.</p> <p><img style="margin: 0px 10px 0px 0px; display: inline; float: left" title="Stages of a bridge" alt="Stages of a bridge" align="left" src="http://i.msdn.microsoft.com/dynimg/IC551928.gif" /></p> <p>Taking a familiar VETR approach to validate, extract, transform and route messages from one party to another, along with the ability to enrich messages by composing other endpoint in-flight (supported protocols include HTTP, WS-HTTP and Basic HTTP, HTTP Relay Endpoint, Service Bus Queues/Topics and any other XML bridge) the Bridge is a very important capability and brings very robust capabilities for extending Azure Service Bus as a key messaging broker across integration disciplines. </p> <p>In reality, these patterns have no more to do with EAI than with traditional, contemporary service composition and become necessary once you move from a point-to-point approach and need to elegantly manage integration and composition across assets. As such, this capability acts as a bridge to Azure Service Bus that is very powerful in and of itself, even in non-EAI/EDI scenarios where endpoints can be virtualized increasing decoupling between parties (clients/services). In addition, this capability further enriches what is possible when using the BrokeredMessage property construct as a potential poor-man’s routing mechanism. <br /></p> <p>In closing, the need to address the impedance mismatch that exists between disparate applications that must communicate with each other is a friction that will continue to exist for many years to come, and while traditionally, many of these problems have been solved by expensive, big iron middleware servers, this is changing. </p> <p>As with most technologies, often new possibilities are unlocked that are residual side-effects of something bigger, and this is certainly the case with how both <a href="http://www.code-magazine.com/Article.aspx?quickid=1112041" target="_blank">innovative</a> <a href="http://www.code-magazine.com/Article.aspx?quickid=1112041" target="_blank">and strategic Azure Service Bus is to Microsoft’s PaaS strategy</a>. Azure Service Bus continues to serve as a great example of a welcomed shift to a lightweight capability-based, platform-oriented approach to solving tough distributed messaging/integration problems while honoring the existing investments that organizations have made and benefiting from a common platform approach which is extremely unique in the market. And while this shift will take some time, in the long-run enterprises of all shapes and sizes only stand to benefit.</p> <p>To get started, download the SDK &amp; samples from <a href="http://go.microsoft.com/fwlink/?LinkID=184288">http://go.microsoft.com/fwlink/?LinkID=184288</a> and the tutorial &amp; documentation from <a href="http://go.microsoft.com/fwlink/?LinkID=235197">http://go.microsoft.com/fwlink/?LinkID=235197</a> and watch this and the <a href="http://blogs.msdn.com/b/windowsazure/" target="_blank">Windows Azure</a> blog for more details coming soon.</p> <p>Happy Messaging!</p><img src="http://rickgaribay.net/aggbug/324.aspx" width="1" height="1" /> Rick G. Garibay http://rickgaribay.net/archive/2011/12/16/azure-service-bus-connect-eai-and-edi-ldquointegration-servicesrdquo-ctp.aspx Fri, 16 Dec 2011 18:46:51 GMT http://rickgaribay.net/archive/2011/12/16/azure-service-bus-connect-eai-and-edi-ldquointegration-servicesrdquo-ctp.aspx#feedback 2 http://rickgaribay.net/comments/commentRss/324.aspx http://rickgaribay.net/services/trackbacks/324.aspx Getting the Most out of WCF 4.0 REST Today http://rickgaribay.net/archive/2011/10/20/getting-the-most-out-of-wcf-4.0-rest-today-again.aspx <p>WCF has supported HTTP and RESTful approaches to service design for some time now, and while there are some exciting new enhancements being worked on as part of the <a href="http://wcf.codeplex.com/" target="_blank">WCF Web API project</a>, there is some pretty rich functionality in WCF 4.0 that is definitely worth taking advantage of if you need to build HTTP/REST services today, especially when hosting in Windows Server AppFabric. <a href="http://rickgaribay.net/images/rickgaribay_net/Windows-Live-Writer/41cd8fc99175_1348A/4187_04_25_4.png"><img style="background-image: none; border-right-width: 0px; margin: 2px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="4187_04_25" border="0" alt="4187_04_25" align="right" src="http://rickgaribay.net/images/rickgaribay_net/Windows-Live-Writer/41cd8fc99175_1348A/4187_04_25_thumb_1.png" width="240" height="131" /></a></p> <p>There a number of differences to consider when working with REST services that require some special attention as compared to traditional SOAP services, and those differences are definitely noticeable when working with WCF. In this post, I’d like to highlight some of the most common capabilities that REST developers ask for and how to accomplish them in general and when hosting in IIS or Windows Server AppFabric. The WCF Web API improves upon some of the techniques I cover here and introduces new ones which I’ll be discussing in future posts. </p> <p>The first thing you want to do when working with WCF REST is pick a project template. While WCF 4 supports REST out-of-the-box (including a number of improvements over previous versions and the alignment of out-of-band features first seen in the WCF Starter Kit), the default WCF templates are really designed for SOAP-based services and thus are rather lacking for supporting REST an an intuitive, F5 manner (again, this will get better). </p> <p>Microsoft provides the <a href="http://visualstudiogallery.msdn.microsoft.com/fbc7e5c1-a0d2-41bd-9d7b-e54c845394cd" target="_blank">WCF REST Service Application template</a>  via the Visual Studio 2010 Extension Manager. In addition to some useful scaffolding for providing an F5 experience, some fundamental code and configuration is provided as part of the template which is necessary for working with a host such as IIS or Windows Server AppFabric. <a href="http://twitter.com/ronljacobs" target="_blank">Ron Jacobs</a> also has a great template specifically designed for Server AppFabric that extends the functionality in this template to support end to end monitoring and provides a web-based test harness among other things. I definitely recommend that you <a href="http://visualstudiogallery.msdn.microsoft.com/a685f193-ed1e-4ad4-938f-f0bd8212d53d" target="_blank">check it out as well</a>. </p> <p>To keep things focused on the basic aspects of WCF REST 4.0, I’ve taken the <a href="http://visualstudiogallery.msdn.microsoft.com/fbc7e5c1-a0d2-41bd-9d7b-e54c845394cd" target="_blank">WCF REST Service Application template</a> with very minor modifications and created a simple read-only GET service to illustrate some of the most common things you’re likely to hit when starting out with REST in WCF 4. </p> <p>Out of the box, the WCF REST Service Application template provides some basic scaffolding including a functional read-only (GET) REST service. While “SampleItem” is certainly not the most interesting domain, I am going to leave the sample unaltered for simplicity sake as we are going to focus more on the hosting aspects of WCF REST than the design and the code.  </p> <p>Once you create a project with the WCF REST Service Application template, there are 4 files that are created in the project:</p> <p><a href="http://rickgaribay.net/images/rickgaribay_net/Windows-Live-Writer/41cd8fc99175_1348A/image_16.png"><img style="background-image: none; border-right-width: 0px; margin: 2px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" align="left" src="http://rickgaribay.net/images/rickgaribay_net/Windows-Live-Writer/41cd8fc99175_1348A/image_thumb_7.png" width="192" height="175" /></a></p> <ul> <li>The Service1.cs file includes the definition and implementation of the service. </li> <li>The SampleItem.cs file includes the Data Contract that models a resource. </li> <li>The Global.asax file defines some key events that we’ll hook into to enable dynamic routing. </li> <li>The Web.config file includes some key configuration for enabling dynamic routing and supporting extension-less (svc-less) URIs among other things. </li> </ul> <p>The first thing you’ll probably notice in the template is that its missing an .svc file. Most REST developers would rather work with clean URIs as opposed to having a file extension get in the way. Fortunately, with a little bit of help from ASP.NET, we can leverage some pretty sophisticated routing capabilities that not only allow us to eliminate the need for the .svc extension, but in addition enable us to factor our URIs across a number of services and have some pretty fine grained control over URI routes using a templated approach.</p> <p>If you hit F5 at this point, the service will run in Cassini, generating a rather glum response (note that you may not see XML immediately depending on the browser you are using; a brute force approach is to view source or, in the case of IE9, which I am using here, leverage the browser targeting capabilities provided by the F12 developer tools):</p> <p><a href="http://rickgaribay.net/images/rickgaribay_net/Windows-Live-Writer/41cd8fc99175_1348A/image_18.png"><img style="background-image: none; border-right-width: 0px; margin: 2px auto; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://rickgaribay.net/images/rickgaribay_net/Windows-Live-Writer/41cd8fc99175_1348A/image_thumb_8.png" width="1187" height="229" /></a></p> <p> </p> <p>If you take a look inside the Global.asax.cs files, you’ll see what makes this magic happen:</p> <pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 1: RouteTable.Routes.Add(<span style="color: #0000ff">new</span> ServiceRoute("Service1<span style="color: #8b0000"></span>", <span style="color: #0000ff">new</span> WebServiceHostFactory(), <span style="color: #0000ff">typeof</span>(Service1))); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 2: </pre></pre> <p> </p> <p>As shown above, the template automatically added an entry to the System.Web.Routing.RouteTable. The Add method takes a ServiceRoute instance for which we provide 3 parameters:</p> <ul> <li>The first parameter is known as a route prefix and signals the root path that will be mapped to a given WCF service type. In this case, the URI segment of “Service1” will route to the Service1 class as specified in the third parameter. </li> <li>The second parameter is also interesting. Unlike traditional SOAP services that use a ServiceHost, the WebServiceHostFactory was designed to deal with HTTP-based services exclusively. </li> </ul> <p>This default code can immediately be improved upon in my opinion by replacing the route prefix with a simple empty string. This will invoke the GetCollection method in the service implementation which provides a nice, intuitive user experience when interacting with the service without knowing much about it.</p> <p>Taking a look at the service class and the GetCollection method, you will see some familiar attributes, along with the AspNetCompatabilityRequirements attribute which, among other things enables support for routing:</p> <pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 1: [ServiceContract] </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 2: [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 3: [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 4: <span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> Service1 </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 5: { </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 6: [WebGet(UriTemplate = "<span style="color: #8b0000"></span>")] </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 7: <span style="color: #0000ff">public</span> List&lt;SampleItem&gt; GetCollection() </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 8: { </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 9: <span style="color: #008000">// TODO: Replace the current implementation to return a collection of SampleItem instances</span> </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 10: <span style="color: #0000ff">return</span> <span style="color: #0000ff">new</span> List&lt;SampleItem&gt;() { <span style="color: #0000ff">new</span> SampleItem() { Id = 1, StringValue = "<span style="color: #8b0000">Hello</span>" } }; </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 11: } </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 12: }</pre></pre> <p> </p> <p>All of this also requires that ASP.NET compatibility is enabled declaratively in the Web.config by setting the aspNetCompatibilityEnabled attribute to true in the serviceHostingEnvironment element:</p> <pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 1: &lt;system.serviceModel&gt; </pre><pre style="background-color: #ffff00; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 2: &lt;serviceHostingEnvironment aspNetCompatibilityEnabled="<span style="color: #8b0000">true</span>"/&gt; </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 3: &lt;standardEndpoints&gt; </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 4: &lt;webHttpEndpoint&gt; </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 5: &lt;standardEndpoint name="<span style="color: #8b0000"></span>" helpEnabled="<span style="color: #8b0000">true</span>" automaticFormatSelectionEnabled="<span style="color: #8b0000">true</span>"/&gt; </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 6: &lt;/webHttpEndpoint&gt; </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 7: &lt;/standardEndpoints&gt; </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 8: &lt;/system.serviceModel&gt;</pre></pre> <p> </p> <p>You will also notice that the web.config is absent of the boilerplate service and endpoint configuration including the address, binding and contract attributes. WCF 4 introduces the concept of default endpoints to simplify the approach for hosting services in WCF 4, which in effect automates the creation of common endpoint configurations for getting your WCF services up and running quickly and easily. Standard Endpoints build on this simplicity by providing common configurations packaged into an element and exercising convention over configuration. By using the WebHttpEndpoint standard endpoint, you are provided some common configuration knobs such as supporting multiple encoding types and help documentation that is automatically generated provided you enable the helpEnabled attribute in line 5 above:</p> <p><a href="http://rickgaribay.net/images/rickgaribay_net/Windows-Live-Writer/41cd8fc99175_1348A/image_26.png"><img style="background-image: none; border-right-width: 0px; margin: 2px auto; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://rickgaribay.net/images/rickgaribay_net/Windows-Live-Writer/41cd8fc99175_1348A/image_thumb_12.png" width="640" height="340" /></a></p> <p>While all of this works just fine in Cassini, it won’t work in IIS/Windows Server AppFabric as without the additional configuration I am going to cover next because it (rightfully) assumes that you are asking to browse the contents of the root directory which is fortunately forbidden unless you explicitly allow it:</p> <p><a href="http://rickgaribay.net/images/rickgaribay_net/Windows-Live-Writer/41cd8fc99175_1348A/image_20.png"><img style="background-image: none; border-right-width: 0px; margin: 2px auto; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://rickgaribay.net/images/rickgaribay_net/Windows-Live-Writer/41cd8fc99175_1348A/image_thumb_9.png" width="640" height="399" /></a></p> <p>Note that had I left the route prefix with the default “Service1”, a 404 would instead be thrown because without the correct modules, IIS has no way of routing this to the class by the same name.</p> <p>The remedy to these problems is provided by setting the runAllManagedModulesForAllRequests attribute in the modules element to true, which ensures that any requests that come into the request pipeline that are not mapped to an extension are passed on to the modules in the pipeline for processing. Specifically, the  route that was added to the Application_Start method implementation in the Global class will be used to resolve to the Service1 class by the UrlRoutingModule managed module which is registered using the configuration below and enables this routing for services that do not use the .svc extension and are hosted in IIS/Windows Server AppFabric: </p> <pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 1: <span style="color: #0000ff">&lt;</span><span style="color: #800000">system.webServer</span><span style="color: #0000ff">&gt;</span> </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 2: <span style="color: #0000ff">&lt;</span><span style="color: #800000">modules</span> <span style="color: #ff0000">runAllManagedModulesForAllRequests</span>=<span style="color: #0000ff">"true"</span><span style="color: #0000ff">&gt;</span> </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 3: <span style="color: #0000ff">&lt;</span><span style="color: #800000">add</span> <span style="color: #ff0000">name</span>=<span style="color: #0000ff">"UrlRoutingModule"</span> <span style="color: #ff0000">type</span>=<span style="color: #0000ff">"System.Web.Routing.UrlRoutingModule, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"</span> <span style="color: #0000ff">/&gt;</span> </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 4: <span style="color: #0000ff">&lt;/</span><span style="color: #800000">modules</span><span style="color: #0000ff">&gt;</span> </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 5: <span style="color: #0000ff">&lt;/</span><span style="color: #800000">system.webServer</span><span style="color: #0000ff">&gt;</span></pre></pre> <p>It is possible, depending on your IIS configuration that the UrlRoutingModule has already been registered, in which case line 3 above is superfluous. If you comment it out and re-deploy, things will continue to work as expected unless you either remove it declaratively in the web.config or explicitly remove it from the Modules manager.</p> <p>With this configuration in place, the service will result in the request being correctly routed and the response presented in the browser:</p> <p><a href="http://rickgaribay.net/images/rickgaribay_net/Windows-Live-Writer/41cd8fc99175_1348A/image_22.png"><img style="background-image: none; border-right-width: 0px; margin: 2px auto; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://rickgaribay.net/images/rickgaribay_net/Windows-Live-Writer/41cd8fc99175_1348A/image_thumb_10.png" width="640" height="397" /></a></p> <p>If you’re like me, you likely find the XML, or at least the root node abhorrent. We can improve upon this significantly by creating a second class to represent the SampleItem that inherits from the original List&lt;SampleItem&gt; found in the template and decorate it with a CollectionDataContract attribute. </p> <pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 1: [CollectionDataContract(Name = "<span style="color: #8b0000">SampleItems</span>",Namespace = "<span style="color: #8b0000"></span>")] </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 2: <span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> SampleItems : List&lt;SampleItem&gt; </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 3: { </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 4: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 5: }</pre></pre> <p> </p> <p>Further, if we override the Namespace by setting the Namespace parameter of the attribute and setting it to an empty string, we get a much nice, cleaner result:</p> <p><a href="http://rickgaribay.net/images/rickgaribay_net/Windows-Live-Writer/41cd8fc99175_1348A/image_24.png"><img style="background-image: none; border-right-width: 0px; margin: 2px auto; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://rickgaribay.net/images/rickgaribay_net/Windows-Live-Writer/41cd8fc99175_1348A/image_thumb_11.png" width="640" height="427" /></a></p> <p align="center"><font size="1">Note: I have to credit this technique to <a href="http://twitter.com/#!/jonflanders" target="_blank">Jon Flanders</a>, who’s excellent book </font><a href="http://www.amazon.com/RESTful-NET-Build-Consume-Services/dp/0596519206" target="_blank"><font size="1">“Restful .NET”</font></a><font size="1">  is where I first learned this technique a couple of years ago. </font></p> <p>Some developers and administrators may be concerned about the potential performance implications that enabling the runAllManagedModulesForAllRequests attribute introduces for static requests such as HTML pages, image files, etc. since each of these requests must run through all of the configured modules unnecessarily. Fortunately, Microsoft introduced an alternative to this approach in a QFE Hotfix which enables dynamic routing without impacting static requests. You can download and install the Hotfix from here: http://support.microsoft.com/kb/980368. After installing the hotfix, three new handlers with a name prefix of ExtnesionlessUrlHandler are installed in IIS which correspond to 32, 64 bit and integrated modes and applied to all applications. With these handlers installed, you can remove or disable the runAllManagedModulesForAllRequests attribute and all routing will continue to function as expected provided the handlers remain registered as shown below.</p> <p><a href="http://rickgaribay.net/images/rickgaribay_net/Windows-Live-Writer/41cd8fc99175_1348A/4187_04_31_2.png"><img style="background-image: none; border-right-width: 0px; margin: 2px auto; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="4187_04_31" border="0" alt="4187_04_31" src="http://rickgaribay.net/images/rickgaribay_net/Windows-Live-Writer/41cd8fc99175_1348A/4187_04_31_thumb.png" width="640" height="357" /></a></p> <p>As I was walking through the standard endpoint configuration, you may have noticed an attribute on the standard endpoint element called automaticFormattingEnabled. When set to true, this allows you to manipulate whether the service should return XML or JSON. According to MSDN, the determination is based on the following in order:</p> <ol> <li>The media types in the request message’s Accept header. </li> <li>The content-type of the request message. </li> <li>The default format setting in the operation. </li> <li>The default format setting in the WebHttpBehavior. <br /></li> </ol> <p>Using Fiddler, I’ve set the Accept header to application/json which has the result of returning JSON without me having to do anything to the service itself:</p> <p><a href="http://rickgaribay.net/images/rickgaribay_net/Windows-Live-Writer/41cd8fc99175_1348A/image_28.png"><img style="background-image: none; border-right-width: 0px; margin: 2px auto; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://rickgaribay.net/images/rickgaribay_net/Windows-Live-Writer/41cd8fc99175_1348A/image_thumb_13.png" width="640" height="367" /></a></p> <p>Of course, you can have the service return plain text or a stream, but to do so today, you need to implement a custom mechanism for passing the format you need such as a querystring  and then writing some code to read it and return the appropriate expected format.</p> <p>Finally, one of the biggest benefits of designing REST services, or services that leverage the HTTP protocol exclusively, is that you get all of the features inherent to the HTTP protocol including support for caching requests, or GET requests. By adding an attribute called AspNetCacheProfile to the GetCollection method and mapping the profile name in the web.config, I can leverage the caching capabilities in ASP.NET to cache GET requests:</p> <pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 1: [WebGet(UriTemplate = "<span style="color: #8b0000"></span>")] </pre><pre style="background-color: #ffff00; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 2: [AspNetCacheProfile("<span style="color: #8b0000">MyCacheProfile</span>")] </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 3: <span style="color: #0000ff">public</span> SingleTracks GetCollection() </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 4: { </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 5: <span style="color: #0000ff">return</span> GetSingleTracks(); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 6: } </pre></pre> <p> </p> <p>As I hope I’ve shown, there is pretty strong support for REST in WCF 4, both in the box and as provided by the WCF REST specific templates which allows you to easily host your WCF REST services on any host, including Windows Server AppFabric which allows you to take advantage of all of the great management and monitoring capabilities it provides. New features in the WCF Web API will make it even easier to host HTTP/REST services with WCF, so watch this space for some upcoming posts and be sure to keep up with the latest developments on the WCF Community Site at <a title="http://wcf.codeplex.com/" href="http://wcf.codeplex.com/">http://wcf.codeplex.com/</a>.</p><img src="http://rickgaribay.net/aggbug/319.aspx" width="1" height="1" /> Rick G. Garibay http://rickgaribay.net/archive/2011/10/20/getting-the-most-out-of-wcf-4.0-rest-today-again.aspx Fri, 21 Oct 2011 06:09:10 GMT http://rickgaribay.net/archive/2011/10/20/getting-the-most-out-of-wcf-4.0-rest-today-again.aspx#feedback http://rickgaribay.net/comments/commentRss/319.aspx http://rickgaribay.net/services/trackbacks/319.aspx Azure AppFabric Service Bus Brokered Messaging GA &amp; Rude CTP Diffs http://rickgaribay.net/archive/2011/09/14/azure-appfabric-service-bus-brokered-messaging-ga-amp-rude-ctp.aspx <p>Today at the Build conference in Anaheim California, Satya Nadella, President Server and Tools business announced general availability of the production release of AppFabric Queues and Topics, otherwise known as Brokered Messaging.</p> <p>Brokered Messaging introduces durable queue capabilities and rich, durable pub-sub with topics and subscriptions that compliment the existing Relayed Messaging capabilities.  </p> <p>I covered Brokered Messaging following the <a href="http://rickgaribay.net/archive/2011/05/17/appfabric-service-bus-v2-ctp.aspx" target="_blank">May CTP release</a> of <a href="http://rickgaribay.net/archive/2011/05/17/appfabric-service-bus-v2-ctp.aspx" target="_blank">Queues</a> and followed up shortly with an overview and exploration of <a href="http://rickgaribay.net/archive/2011/05/31/exploring-appfabric-service-bus-v2-may-ctp-topics.aspx" target="_blank">Topics</a> (please see some other great resources at the end of this post).</p> <p>Since then, there was a June CTP release which included the new AppFabric Application and no visible changes to Brokered Messaging, however since its release, the AppFabric Messaging team has been hard at work refining the API and behaviors based on feedback from Advisors, MVPs and the community at large. </p> <p>Since I’ve already covered Queues and Topics in the aforementioned posts, I’ll dive right in to some terse examples which demonstrate the API changes. Though not an exhaustive review of all of the changes, I’ve covered the types that your most likely to come across and will cover Queues, Topics and Subscriptions extensively in my upcoming article in <a href="http://www.code-magazine.com/SearchResults.aspx?search=garibay" target="_blank">CODE Magazine</a> which will also include more in-depth walk-throughs of the .NET Client API, REST API and WCF scenarios.</p> <p>Those of you who have worked with the CTPs will find some subtle and not so subtle changes, but all in all I think all of the refinements are for the best and I think you’ll appreciate them as I have. For those new to Azure AppFabric Service Bus Brokered Messaging, you’ll benefit most from reading my first two posts based on the May CTP (or any of the resources at the end of this post) to get an idea of the why behind queues and topics and then come back here to explore the what and how.</p> <p><strong><font size="3">A Quick Note on Versioning</font></strong></p> <p>In the CTPs that preceded the release of the new Azure AppFabric Service Bus features, a temporary assembly called “Microsoft.ServiceBus.Messaging.dll” was added to serve a container for new features and deltas that were introduced during the development cycle. The final release includes a single assembly called “Microsoft.ServiceBus.dll” which contains all of the existing relay capabilities that you’re already familiar with as well as the addition of support for queues and topics. If you are upgrading from the CTPs, you’ll want to get ahold of the new Microsoft.ServiceBus.dll version 1.5 which includes everything plus the new queue and topic features.</p> <p>The new 1.5 version of the Microsoft.ServiceBus.dll assembly targets the .NET 4.0 framework. Customers using .NET 3.5 can continue using the existing Microsoft.ServiceBus.dll  assembly (version 1.0.1123.2) for leveraging the relay capabilities, but must upgrade to .NET 4.0 to take advantage of the latest features presented here.</p> <p><strong><font size="4">.NET Client API</font></strong></p> <p><strong><font size="3">Queues</font></strong></p> <table border="1" cellspacing="0" cellpadding="2" width="1072"><tbody> <tr> <td valign="top" width="251"><strong>May/June CTP</strong></td> <td valign="top" width="251"><strong>General Availability</strong></td> <td valign="top" width="568"><strong>Comments</strong></td> </tr> <tr> <td valign="top" width="251">ServiceBusNamespaceClientSettings</td> <td valign="top" width="251">NamespaceManagerSettings</td> <td valign="top" width="568">New class for encapsulating endpoint and security settings.</td> </tr> <tr> <td valign="top" width="251">N/A</td> <td valign="top" width="251">TokenProvider</td> <td valign="top" width="568">New class for acquiring a WRAP token from ACS.</td> </tr> <tr> <td valign="top" width="251">ServiceBusNamespaceClient</td> <td valign="top" width="251">NamespaceManager</td> <td valign="top" width="568">Root management object for creating Queues, Topics, Subscriptions.</td> </tr> <tr> <td valign="top" width="251">Queue</td> <td valign="top" width="251">QueueDescription</td> <td valign="top" width="568">In May/June CTP, Topic / Queue / Subscription were management objects. All create/delete operations were moved to NamespaceManager and the state operations are now on TopicDescription/QueueDescription etc.</td> </tr> <tr> <td valign="top" width="251">MessagingFactorySettings</td> <td valign="top" width="251">MessagingFactorySettings</td> <td valign="top" width="568">New class for encapsulating security settings.</td> </tr> <tr> <td valign="top" width="251">MessagingFactory</td> <td valign="top" width="251">MessagingFactory</td> <td valign="top" width="568"> </td> </tr> <tr> <td valign="top" width="251">BrokeredMessage</td> <td valign="top" width="251">BrokeredMessage</td> <td valign="top" width="568">No longer a factory. Simply instantiate a BrokeredMessage.</td> </tr> <tr> <td valign="top" width="251">MessageSender</td> <td valign="top" width="251">MessageSender</td> <td valign="top" width="568">Optional, for use when you want to abstract away queue or topic.</td> </tr> <tr> <td valign="top" width="251">MessageReceiver</td> <td valign="top" width="251">MessageReceiver</td> <td valign="top" width="568">Optional, for use when you want to abstract away queue or topic.</td> </tr> </tbody></table> <p><strong></strong></p> <p>Below is a representative sample for creating, configuring, sending and receiving a message on a queue:</p> <p><strong>Administrative Operations</strong></p> <pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 817px; padding-right: 5px; height: 397px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 1: </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 2: <span style="color: #008000">// Configure and create NamespaceManager for performing administrative operations</span> </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 3: NamespaceManagerSettings settings = <span style="color: #0000ff">new</span> NamespaceManagerSettings(); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 4: TokenProvider tokenProvider = settings.TokenProvider = TokenProvider.CreateSharedSecretTokenProvider(issuer,key); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 5: </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 6: NamespaceManager manager = <span style="color: #0000ff">new</span> NamespaceManager(ServiceBusEnvironment.CreateServiceUri("<span style="color: #8b0000">sb</span>", serviceNamespace, <span style="color: #0000ff">string</span>.Empty), settings); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 7: </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 8: <span style="color: #008000">// Check for existence of queues on the fabric</span> </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 9: var qs = manager.GetQueues(); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 10: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 11: var result = from q <span style="color: #0000ff">in</span> qs </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 12: where q.Path.Equals(queueName, StringComparison.OrdinalIgnoreCase) </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 13: select q; </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 14: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 15: <span style="color: #0000ff">if</span> (result.Count() == 0) </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 16: { </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 17: Console.WriteLine("<span style="color: #8b0000">Queue does not exist</span>"); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 18: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 19: <span style="color: #008000">// Create Queue</span> </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 20: Console.WriteLine("<span style="color: #8b0000">Creating Queue...</span>"); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 21: </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 22: manager.CreateQueue(<span style="color: #0000ff">new</span> QueueDescription(queueName) { LockDuration = TimeSpan.FromSeconds(5.0d) }); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 23: </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 24: }</pre></pre> <p><strong>Runtime Operations</strong></p> <pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 815px; padding-right: 5px; height: 716px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 1: <span style="color: #008000">// Create and Configure Messaging Factory to provision QueueClient</span> </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 2: MessagingFactorySettings messagingFactorySettings = <span style="color: #0000ff">new</span> MessagingFactorySettings(); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 3: messagingFactorySettings.TokenProvider = settings.TokenProvider = TokenProvider.CreateSharedSecretTokenProvider(issuer, key); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 4: MessagingFactory messagingFactory = MessagingFactory.Create(ServiceBusEnvironment.CreateServiceUri("<span style="color: #8b0000">sb</span>", serviceNamespace, <span style="color: #0000ff">string</span>.Empty), messagingFactorySettings); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 5: </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 6: QueueClient queueClient = messagingFactory.CreateQueueClient(queueName, ReceiveMode.PeekLock); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 7: </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 8: Order order = <span style="color: #0000ff">new</span> Order(); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 9: order.OrderId = 42; </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 10: order.Products.Add("<span style="color: #8b0000">Kinect</span>", 70.50M); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 11: order.Products.Add("<span style="color: #8b0000">XBOX 360</span>", 199.99M); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 12: order.Total = order.Products["<span style="color: #8b0000">Kinect</span>"] + order.Products["<span style="color: #8b0000">XBOX 360</span>"]; </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 13: </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 14: <span style="color: #008000">// Create a Brokered Message from the Order object</span> </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 15: BrokeredMessage msg = <span style="color: #0000ff">new</span> BrokeredMessage(order); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 16: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 17: <span style="color: #008000">/*********************** </span></pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 18: *** Send Operations *** </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 19: ************************/ </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 20: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 21: queueClient.Send(msg); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 22: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 23: <span style="color: #008000">/************************** </span></pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 24: *** Receive Operations *** </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 25: ***************************/ </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 26: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 27: BrokeredMessage recdMsg; </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 28: Order recdOrder; </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 29: </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 30: <span style="color: #008000">// Receive and lock message</span> </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 31: recdMsg = queueClient.Receive(); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 32: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 33: <span style="color: #0000ff">if</span>(recdMsg != <span style="color: #0000ff">null</span>) </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 34: { </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 35: <span style="color: #008000">// Convert from BrokeredMessage to native Order</span> </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 36: recdOrder = recdMsg.GetBody&lt;Order&gt;(); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 37: </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 38: Console.ForegroundColor = ConsoleColor.Green; </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 39: Console.WriteLine("<span style="color: #8b0000">Received Order {0} \n\t with Message Id {1} \n\t and Lock Token:{2} \n\t from {3} \n\t with total of ${4}</span>", recdOrder.OrderId, recdMsg.MessageId, recdMsg.LockToken, "<span style="color: #8b0000">Receiver 1</span>", recdOrder.Total); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 40: recdMsg.Complete(); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 41: } </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 42: queueClient.Close();</pre></pre> <p> </p> <p>Note that MessageSender and MessageReceiver are now optional. Here’s an example that shows PeekLocking a message, simulating an exception and trying again:</p> <pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 828px; padding-right: 5px; height: 533px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 1: </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 2: <span style="color: #008000">// Alternate receive approach using agnostic MessageReceiver</span> </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 3: MessageReceiver receiver = messagingFactory.CreateMessageReceiver(queueName); <span style="color: #008000">// Recieve, complete, and delete message from the fabric</span> </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 4: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 5: <span style="color: #0000ff">try</span> </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 6: { </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 7: <span style="color: #008000">// Receive and lock message</span> </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 8: recdMsg = receiver.Receive(); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 9: </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 10: <span style="color: #008000">// Convert from BrokeredMessage to native Order</span> </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 11: recdOrder = recdMsg.GetBody&lt;Order&gt;(); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 12: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 13: <span style="color: #008000">// Complete read, release and delete message from the fabric</span> </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 14: receiver.Complete(recdMsg.LockToken); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 15: </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 16: Console.ForegroundColor = ConsoleColor.Green; </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 17: Console.WriteLine("<span style="color: #8b0000">Received Order {0} \n\t with Message Id {1} \n\t and Lock Token:{2} \n\t from {3} \n\t with total of ${4} \n\t at {5}</span>", recdOrder.OrderId, recdMsg.MessageId, recdMsg.LockToken, "<span style="color: #8b0000">Receiver 2</span>", recdOrder.Total, DateTime.Now.Hour + "<span style="color: #8b0000">:</span>" + DateTime.Now.Minute + "<span style="color: #8b0000">:</span>" + DateTime.Now.Second); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 18: } </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 19: <span style="color: #0000ff">catch</span> </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 20: { </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 21: <span style="color: #008000">// Should processing fail, release the lock from the fabric and make message available for later processing.</span> </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 22: <span style="color: #0000ff">if</span> (recdMsg != <span style="color: #0000ff">null</span>) </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 23: { </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 24: receiver.Abandon(recdMsg.LockToken); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 25: </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 26: Console.ForegroundColor = ConsoleColor.Red; </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 27: Console.WriteLine("<span style="color: #8b0000">Message could not be processed.</span>"); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 28: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 29: } </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 30: } </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 31: <span style="color: #0000ff">finally</span> </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 32: { </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 33: receiver.Close(); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 34: }</pre></pre> <p><strong></strong></p> <p>As shown below, this sample results in order 42 being received by the QueueClient:</p> <p><a href="http://rickgaribay.net/images/rickgaribay_net/Windows-Live-Writer/AppFabric-Service-Bus-Queues--Topics-Rel_D1C0/image_2.png"><img style="background-image: none; border-right-width: 0px; margin: 2px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://rickgaribay.net/images/rickgaribay_net/Windows-Live-Writer/AppFabric-Service-Bus-Queues--Topics-Rel_D1C0/image_thumb.png" width="807" height="127" /></a></p> <br /> <p><strong><font size="3">Topics</font></strong></p> <table border="1" cellspacing="0" cellpadding="0"><tbody> <tr> <td valign="top" width="268"> <p><b>May/June CTP</b></p> </td> <td valign="top" width="239"> <p><b>General Availability</b></p> </td> <td valign="top" width="566"> <p><b>Comments</b></p> </td> </tr> <tr> <td valign="top" width="268"> <p>Topic</p> </td> <td valign="top" width="239"> <p>TopicDescription</p> </td> <td valign="top" width="566"> <p>In May/June CTP, Topic / Queue / Subscription were management objects. All create/delete operations were moved to NamespaceManager and the state operations are now on TopicDescription/QueueDescription etc.</p> </td> </tr> <tr> <td valign="top" width="268"> <p>TopicClient</p> </td> <td valign="top" width="239"> <p>TopicClient</p> </td> <td valign="top" width="566"> <p>As noted in the Queues section, you can use TopicClient or MessageSender in the event you want to abstract details of using Topics.</p> </td> </tr> <tr> <td valign="top" width="268"> <p>SubscriptionClient</p> </td> <td valign="top" width="239"> <p>SubscriptionClient</p> </td> <td valign="top" width="566"> <p>As noted in the Queues section, you can use SubscriptionClient or MessageReceiver in the event you want to abstract details of using a Topic/Subscription.</p> </td> </tr> <tr> <td valign="top" width="268"> <p>Subscription</p> </td> <td valign="top" width="239"> <p>SubscriptionDescription</p> </td> <td valign="top" width="566">Changes to constructors and use of properties (see code samples below), but intent is the same.</td> </tr> <tr> <td valign="top" width="268"> <p>RuleDescription</p> </td> <td valign="top" width="239"> <p>RuleDescription</p> </td> <td valign="top" width="566">Changes to constructors and use of properties (see code samples below), but intent is the same.</td> </tr> <tr> <td valign="top" width="268"> <p>FilterExpression</p> </td> <td valign="top" width="239"> <p>Filter</p> </td> <td valign="top" width="566"> <p>Base for Filter types such as SqlFilter</p> </td> </tr> <tr> <td valign="top" width="268"> <p>SqlFilterExpression</p> </td> <td valign="top" width="239"> <p>SqlFilter</p> </td> <td valign="top" width="566"> </td> </tr> <tr> <td valign="top" width="268"> <p>FilterAction</p> </td> <td valign="top" width="239"> <p>RuleAction</p> </td> <td valign="top" width="566"> </td> </tr> </tbody></table> <p> </p> <p>Below is a representative sample for creating, configuring, sending and receiving a message on a topic:</p> <p><strong>Administrative Operations</strong></p> <pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 836px; padding-right: 5px; height: 632px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 1: <span style="color: #008000">// Configure and create NamespaceManager for performing administrative operations</span> </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 2: NamespaceManagerSettings settings = <span style="color: #0000ff">new</span> NamespaceManagerSettings(); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 3: settings.TokenProvider = TokenProvider.CreateSharedSecretTokenProvider(issuer, key); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 4: NamespaceManager manager = <span style="color: #0000ff">new</span> NamespaceManager(ServiceBusEnvironment.CreateServiceUri("<span style="color: #8b0000">sb</span>", serviceNamespace, <span style="color: #0000ff">string</span>.Empty), settings); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 5: </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 6: <span style="color: #008000">// Check for existence of topics on the fabric</span> </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 7: var topics = manager.GetTopics(); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 8: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 9: var result = from t <span style="color: #0000ff">in</span> topics </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 10: where t.Path.Equals(topicName, StringComparison.OrdinalIgnoreCase) </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 11: select t; </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 12: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 13: <span style="color: #0000ff">if</span> (result.Count() == 0) </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 14: { </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 15: Console.WriteLine("<span style="color: #8b0000">Topic does not exist</span>"); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 16: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 17: <span style="color: #008000">// Create Queue</span> </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 18: Console.WriteLine("<span style="color: #8b0000">Creating Topic...</span>"); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 19: </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 20: TopicDescription topic = manager.CreateTopic(topicName); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 21: } </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 22: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 23: <span style="color: #008000">// Create Subscriptions for InventoryServiceSubscription and CreditServiceSubscription and associate to OrdersTopic:</span> </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 24: SubscriptionDescription inventoryServiceSubscription = <span style="color: #0000ff">new</span> SubscriptionDescription(topicName, "<span style="color: #8b0000">InventoryServiceSubscription</span>"); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 25: SubscriptionDescription creditServiceSubscription = <span style="color: #0000ff">new</span> SubscriptionDescription(topicName, "<span style="color: #8b0000">CreditServiceSubscription</span>"); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 26: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 27: </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 28: <span style="color: #008000">// Set up Filters for NorthAmericaFulfillmentServiceSubscription</span> </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 29: RuleDescription northAmericafulfillmentRuleDescription = <span style="color: #0000ff">new</span> RuleDescription(); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 30: northAmericafulfillmentRuleDescription.Filter = <span style="color: #0000ff">new</span> SqlFilter("<span style="color: #8b0000">CountryOfOrigin = 'USA' OR CountryOfOrigin ='Canada' OR CountryOfOrgin ='Mexico'</span>"); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 31: northAmericafulfillmentRuleDescription.Action = <span style="color: #0000ff">new</span> SqlRuleAction("<span style="color: #8b0000">set FulfillmentRegion='North America'</span>"); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 32: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 33: </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 34: <span style="color: #008000">// Create Subscriptions</span> </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 35: SubscriptionDescription northAmericaFulfillmentServiceSubscription = <span style="color: #0000ff">new</span> SubscriptionDescription(topicName, "<span style="color: #8b0000">NorthAmericaFulfillmentServiceSubscription</span>"); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 36: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 37: <span style="color: #008000">// Delete existing subscriptions</span> </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 38: <span style="color: #0000ff">try</span> { manager.DeleteSubscription(topicName, inventoryServiceSubscription.Name); } <span style="color: #0000ff">catch</span> { }; </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 39: <span style="color: #0000ff">try</span> { manager.DeleteSubscription(topicName, creditServiceSubscription.Name); } <span style="color: #0000ff">catch</span> { }; </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 40: <span style="color: #0000ff">try</span> { manager.DeleteSubscription(topicName, northAmericaFulfillmentServiceSubscription.Name); } <span style="color: #0000ff">catch</span> { }; </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 41: </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 42: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 43: <span style="color: #008000">// Add Subscriptions and Rules to Topic</span> </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 44: manager.CreateSubscription(inventoryServiceSubscription); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 45: manager.CreateSubscription(creditServiceSubscription); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 46: manager.CreateSubscription(northAmericaFulfillmentServiceSubscription, northAmericafulfillmentRuleDescription); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 47: </pre></pre> <p><strong></strong></p> <p><strong>Runtime Operations</strong></p> <p><strong></strong></p> <pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 842px; padding-right: 5px; height: 631px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 1: <span style="color: #008000">// Create and Configure Messaging Factory to provision TopicClient</span> </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 2: MessagingFactorySettings runtimeSettings = <span style="color: #0000ff">new</span> MessagingFactorySettings(); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 3: runtimeSettings.TokenProvider = TokenProvider.CreateSharedSecretTokenProvider(issuer, key); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 4: MessagingFactory messagingFactory = MessagingFactory.Create(ServiceBusEnvironment.CreateServiceUri("<span style="color: #8b0000">sb</span>",serviceNamespace,String.Empty),runtimeSettings); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 5: </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 6: <span style="color: #008000">// Create Topic Client for sending messages to the Topic:</span> </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 7: TopicClient client = messagingFactory.CreateTopicClient(topicName); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 8: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 9: <span style="color: #008000">/*********************** </span></pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 10: *** Send Operations *** </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 11: ***********************/ </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 12: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 13: <span style="color: #008000">// Prepare BrokeredMessage and corresponding properties</span> </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 14: Order order = <span style="color: #0000ff">new</span> Order(); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 15: order.OrderId = 42; </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 16: order.Products.Add("<span style="color: #8b0000">Kinect</span>", 70.50M); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 17: order.Products.Add("<span style="color: #8b0000">XBOX 360</span>", 199.99M); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 18: order.Total = order.Products["<span style="color: #8b0000">Kinect</span>"] + order.Products["<span style="color: #8b0000">XBOX 360</span>"]; </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 19: </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 20: <span style="color: #008000">// Set the body to the Order data contract</span> </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 21: BrokeredMessage msg = <span style="color: #0000ff">new</span> BrokeredMessage(order); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 22: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 23: <span style="color: #008000">// Set properties for use in RuleDescription</span> </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 24: msg.Properties.Add("<span style="color: #8b0000">CountryOfOrigin</span>", "<span style="color: #8b0000">USA</span>"); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 25: msg.Properties.Add("<span style="color: #8b0000">FulfillmentRegion</span>", "<span style="color: #8b0000"></span>"); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 26: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 27: <span style="color: #008000">// Send the message to the OrdersTopic</span> </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 28: client.Send(msg); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 29: client.Close(); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 30: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 31: <span style="color: #008000">/************************** </span></pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 32: *** Receive Operations *** </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 33: ****************************/ </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 34: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 35: BrokeredMessage recdMsg; </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 36: Order recdOrder; </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 37: </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 38: <span style="color: #008000">// Inventory Service Subscriber</span> </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 39: SubscriptionClient inventoryServiceSubscriber = messagingFactory.CreateSubscriptionClient(topicName, "<span style="color: #8b0000">InventoryServiceSubscription</span>",ReceiveMode.PeekLock); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 40: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 41: <span style="color: #008000">// Read the message from the OrdersTopic</span> </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 42: <span style="color: #0000ff">while</span> ((recdMsg = inventoryServiceSubscriber.Receive(TimeSpan.FromSeconds(5))) != <span style="color: #0000ff">null</span>) </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 43: { </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 44: <span style="color: #008000">// Convert from BrokeredMessage to native Order</span> </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 45: recdOrder = recdMsg.GetBody&lt;Order&gt;(); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 46: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 47: <span style="color: #008000">// Complete read, release and delete message from the fabric</span> </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 48: inventoryServiceSubscriber.Complete(recdMsg.LockToken); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 49: </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 50: Console.ForegroundColor = ConsoleColor.Green; </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 51: Console.WriteLine("<span style="color: #8b0000">Received Order {0} \n\t on {1} \n\t with Message Id {2} \n\t and Lock Token {3}.</span>", recdOrder.OrderId, "<span style="color: #8b0000">Inventory Service Subscriber</span>", recdMsg.MessageId, recdMsg.LockToken); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 52: } </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 53: inventoryServiceSubscriber.Close(); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 54: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 55: <span style="color: #008000">// Credit Service Subscriber</span> </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 56: SubscriptionClient creditServiceSubscriber = messagingFactory.CreateSubscriptionClient(topicName, "<span style="color: #8b0000">CreditServiceSubscription</span>"); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 57: </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 58: <span style="color: #008000">// Read the message from the OrdersTopic</span> </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 59: recdMsg = creditServiceSubscriber.Receive(); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 60: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 61: <span style="color: #008000">// Convert from BrokeredMessage to native Order</span> </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 62: recdOrder = recdMsg.GetBody&lt;Order&gt;(); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 63: </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 64: <span style="color: #008000">// Complete read, release and delete message from the fabric</span> </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 65: creditServiceSubscriber.Complete(recdMsg.LockToken); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 66: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 67: Console.ForegroundColor = ConsoleColor.Green; </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 68: Console.WriteLine("<span style="color: #8b0000">Received Order {0} \n\t on {1} \n\t with Message Id {2} \n\t and Lock Token {3}.</span>", recdOrder.OrderId, "<span style="color: #8b0000">Credit Service Subscriber</span>", recdMsg.MessageId, recdMsg.LockToken); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 69: </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 70: creditServiceSubscriber.Close(); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 71: </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 72: <span style="color: #008000">// Fulfillment Service Subscriber for the North America Fulfillment Service Subscription</span> </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 73: SubscriptionClient northAmericaFulfillmentServiceSubscriber = messagingFactory.CreateSubscriptionClient(topicName, "<span style="color: #8b0000">northAmericaFulfillmentServiceSubscription</span>"); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 74: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 75: <span style="color: #008000">// Read the message from the OrdersTopic for the North America Fulfillment Service Subscription</span> </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 76: recdMsg = northAmericaFulfillmentServiceSubscriber.Receive(TimeSpan.FromSeconds(5)); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 77: </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 78: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 79: <span style="color: #0000ff">if</span>(recdMsg != <span style="color: #0000ff">null</span>) </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 80: { </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 81: <span style="color: #008000">// Convert from BrokeredMessage to native Order</span> </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 82: recdOrder = recdMsg.GetBody&lt;Order&gt;(); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 83: </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 84: <span style="color: #008000">// Complete read, release and delete message from the fabric</span> </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 85: northAmericaFulfillmentServiceSubscriber.Complete(recdMsg.LockToken); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 86: </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 87: Console.ForegroundColor = ConsoleColor.Green; </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 88: Console.WriteLine("<span style="color: #8b0000">Received Order {0} \n\t on {1} \n\t with Message Id {2} \n\t and Lock Token {3}.</span>", recdOrder.OrderId, "<span style="color: #8b0000">North America Fulfillment Service Subscriber</span>", recdMsg.MessageId, recdMsg.LockToken); </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 89: } </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 90: <span style="color: #0000ff">else</span> </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 91: { </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 92: Console.ForegroundColor = ConsoleColor.Yellow; </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 93: Console.WriteLine("<span style="color: #8b0000">No messages for North America found.</span>"); </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 94: } </pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 95: </pre><pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 96: northAmericaFulfillmentServiceSubscriber.Close();</pre></pre> <p><strong><font size="3"></font></strong></p> <p>When running this sample, you’ll see that I have received Order 42 on my Inventory, Credit and North America Fulfillment Service subscriptions:</p> <p><a href="http://rickgaribay.net/images/rickgaribay_net/Windows-Live-Writer/AppFabric-Service-Bus-Queues--Topics-Rel_D1C0/image_6.png"><img style="background-image: none; border-right-width: 0px; margin: 2px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://rickgaribay.net/images/rickgaribay_net/Windows-Live-Writer/AppFabric-Service-Bus-Queues--Topics-Rel_D1C0/image_thumb_2.png" width="802" height="244" /></a></p> <p><strong><font size="3"></font></strong></p> <p><strong><font size="3"></font></strong></p> <p><strong><font size="3"></font></strong></p> <p><strong><font size="3"></font></strong></p> <p><strong><font size="3"></font></strong></p> <p><strong><font size="3"></font></strong></p> <p><strong><font size="3"></font></strong></p> <p><strong><font size="3"></font></strong></p> <p><strong><font size="4">WCF</font></strong></p> <p>One of the great things about the WCF programming model is that it abstracts much of the underlying communication details and as such, other than dropping in a new assembly and and refactoring the binding and configuration, it is not greatly affected by the API changes from the May/June CTP to GA.</p> <p>As I mentioned, one thing that has changed is that the ServiceBusMessagingBinding has been renamed to NetMessagingBinding. I’ll be covering and end to end example of using the NetMessagingBinding in my upcoming article in <a href="http://www.code-magazine.com/SearchResults.aspx?search=garibay" target="_blank">CODE Magazine</a>.</p> <p><strong><font size="4">REST API</font></strong></p> <p>The REST API is key to delivering these new capabilities across a variety of client platforms and remains largely unchanged, however one key change is how message properties are handled. Instead of individual headers for each, there is now one header with  all the properties JSON encoded. Please refer to the updated REST API Reference doc for details. I’ll also be covering and end-to-end example of using the REST API to write an read to/from a queue in my upcoming article in <a href="http://www.code-magazine.com/SearchResults.aspx?search=garibay" target="_blank">CODE Magazine</a>.</p> <p><strong><font size="4">More Coming Soon</font></strong></p> <p>As I mentioned, in my upcoming article in <a href="http://www.code-magazine.com/SearchResults.aspx?search=garibay" target="_blank">CODE Magazine</a>, I’ll cover the Why, What, and How behind Azure AppFabric Service Bus Brokered Messaging including end to end walkthroughs with the .NET Client API, REST API and WCF Binding. The November/December issue should be on newsstands (including Barnes and Noble) or your mailbox towards the end of October. You can also find the article online at <a href="http://code-magazine.com">http://code-magazine.com</a></p> <p><strong><font size="4">Resources</font></strong></p> <p>You can learn more about this exciting release as well as download the GA SDK version 1.5 by visiting the following resources:</p> <ul> <li>Azure AppFabric SDK 1.5:<a title="http://www.microsoft.com/download/en/details.aspx?id=27421" href="http://www.microsoft.com/download/en/details.aspx?id=27421">http://www.microsoft.com/download/en/details.aspx?id=27421</a> </li> <li><a href="http://twitter.com/clemensv" target="_blank">Clemens Vasters</a> on the May CTP: <a title="http://vasters.com/clemensv/2011/05/16/Introducing+The+Windows+Azure+AppFabric+Service+Bus+May+2011+CTP.aspx" href="http://vasters.com/clemensv/2011/05/16/Introducing+The+Windows+Azure+AppFabric+Service+Bus+May+2011+CTP.aspx">http://vasters.com/clemensv/2011/05/16/Introducing+The+Windows+Azure+AppFabric+Service+Bus+May+2011+CTP.aspx</a>  </li> <li>Great video by <a href="http://twitter.com/clemensv" target="_blank">Clemens Vasters</a> on Brokered Messaging: <a title="http://vasters.com/clemensv/2011/06/11/Understanding+Windows+Azure+AppFabric+Queues+And+Topics.aspx" href="http://vasters.com/clemensv/2011/06/11/Understanding+Windows+Azure+AppFabric+Queues+And+Topics.aspx">http://vasters.com/clemensv/2011/06/11/Understanding+Windows+Azure+AppFabric+Queues+And+Topics.aspx</a>  </li> <li><a href="http://twitter.com/#!/dingha" target="_blank">David Ingham</a> on Queues: <a title="http://blogs.msdn.com//b/appfabric/archive/2011/05/17/an-introduction-to-service-bus-queues.aspx" href="http://blogs.msdn.com//b/appfabric/archive/2011/05/17/an-introduction-to-service-bus-queues.aspx">http://blogs.msdn.com//b/appfabric/archive/2011/05/17/an-introduction-to-service-bus-queues.aspx</a> </li> <li><a href="http://twitter.com/#!/dingha" target="_blank">David Ingham</a> on Topics: <a title="http://blogs.msdn.com//b/appfabric/archive/2011/05/25/an-introduction-to-service-bus-topics.aspx" href="http://blogs.msdn.com//b/appfabric/archive/2011/05/25/an-introduction-to-service-bus-topics.aspx">http://blogs.msdn.com//b/appfabric/archive/2011/05/25/an-introduction-to-service-bus-topics.aspx</a>  </li> <li><a href="http://twitter.com/rickggaribay" target="_blank">My</a> Introduction to Queues: <a title="http://rickgaribay.net/archive/2011/05/17/appfabric-service-bus-v2-ctp.aspx" href="http://rickgaribay.net/archive/2011/05/17/appfabric-service-bus-v2-ctp.aspx">http://rickgaribay.net/archive/2011/05/17/appfabric-service-bus-v2-ctp.aspx</a>  </li> <li><a href="http://twitter.com/rickggaribay" target="_blank">My</a> Introduction to Topics:<a title="http://rickgaribay.net/archive/2011/05/31/exploring-appfabric-service-bus-v2-may-ctp-topics.aspx" href="http://rickgaribay.net/archive/2011/05/31/exploring-appfabric-service-bus-v2-may-ctp-topics.aspx">http://rickgaribay.net/archive/2011/05/31/exploring-appfabric-service-bus-v2-may-ctp-topics.aspx</a> </li> </ul><img src="http://rickgaribay.net/aggbug/315.aspx" width="1" height="1" /> Rick G. Garibay http://rickgaribay.net/archive/2011/09/14/azure-appfabric-service-bus-brokered-messaging-ga-amp-rude-ctp.aspx Wed, 14 Sep 2011 16:46:52 GMT http://rickgaribay.net/archive/2011/09/14/azure-appfabric-service-bus-brokered-messaging-ga-amp-rude-ctp.aspx#feedback 2 http://rickgaribay.net/comments/commentRss/315.aspx http://rickgaribay.net/services/trackbacks/315.aspx A Middle-Tier Guy&rsquo;s Take on HTML 5 http://rickgaribay.net/archive/2011/08/22/a-middle-tier-guyrsquos-take-on-html-5.aspx <p><strong></strong></p> <p><strong>(My) Early Beginnings</strong></p> <p>I started my career in software development as a very junior web developer in 1999. I taught myself HTML, VBScript and JavaScript. The browser wars between Microsoft and Netscape were raging. I still remember how exciting my first Classic ASP page was. The fact that I was able to connect to an Access or SQL Server 7 database with just a few lines of code inside my markup was incredible at the time. I consumed new recipes from “4 Guys from Rolla” with relish and kept Scott Mitchell’s titles like “Teach Yourself Classic ASP 3.0 in 21 Days” on my desk at all times (it’s still on my bookshelf which itself has become a sort of Smithsonian for software development over the last decade). Even more exciting was that fact that it seemed like the beginning of a new era in which I could relegate JavaScript as a necessary evil for handling tricks like focus and validation on the UI. </p> <p>At the time, I was doing some really fun and interesting work as a young Padawan for the credit card division inside the #1 Visa issuer in the country (we didn’t have a fancy name for it other than “reports” back then but we were doing very early work on what would become “BI”). By rendering data-driven operational reports dynamically on the browser, we had revolutionized how metrics like Occupancy, Average Handle Time, and Multiple-Call-Rate were disseminated within the bank ushering in a new era of productivity, transparency and accountability for everyone from agent to VP. Through this experience, we built a center of excellence which served as a benchmark for other call centers to follow (in fact, we had the likes of Amex come in and review how we did it). Sure, we had displaced an army of Excel Macro and Access developers, but such was the price of progress.  As this little rogue IT shop basking in our success, I remember a number of “true programmer” personas in the “Real IT” group that tended to undermine what was happening. These were programmers who came from C++ or Java (and whose managers felt threatened by what we were able to do with such few resources) and mostly thumbed their nose at things like lack of strong typing, OO, etc. They looked at JavaScript as just a tool for dirty hippie web masters (remember that term) and VBScript as as something OK for administrators to use to walk AD hives, but being inferior for lacking OO and being handicapped by things like variants. Despite our incredibly visible success (at the CEO level and above) by applying these scripting technologies, I was hungry to see the forest for the trees and experimented a bit with COM and COM+, learning how to encapsulate business logic in components and delighting in being able to wire up my COM libraries with Classic ASP even though with the exception of my manager and mentor at the time, no one else even had the tools to debug my components. </p> <p><strong>The Server Era</strong></p> <p>Then, this thing called Windows DNA came along which promised to marry Windows, ActiveX and Internet into one big cluster… well you know. Fortunately, it’s fate was short-lived, but I remember attending a couple MSDN events where it seemed like concurrency and single threaded apartments would become mainstream topics on the web. Maybe us script kiddies would earn some respect after all? Then, just like that, this new, new thing called .NET happened. All of a sudden, just like that, I had a ton to learn. All my Classic ASP and JavaScript skills were superseded by Web Forms. I still remember stepping through every line of code in the I Buy Spy reference app and being completely blow away. ASP.NET offered something that was OO, strongly typed, and would even render JavaScript for you. Cumbersome JavaScript validation was replaced by server-side templates and controls. Form fields magically remembered their values across post backs. And, as I learned, WebForms offered a better separation of concerns with a nice, clean code-behind model that I would later leverage to introduce patterns like MVP, MVC Page Controller and Front Controller. I built a nice CMS portal for a multi-national bank (which according to Forbes Magazine is the largest public trading company in the world today) with these new skills and I hear it is still running today. Life was good. This was the age of the web server, and the only major argument within the Microsoft web community at that time was “C# or VB.NET”? </p> <p>At this point in my career, I’d grown a bit bored with web development. I felt like I’d accomplished everything I wanted to with ASP.NET, and the roles I found myself in started dealing with problems at a more holistic, program level which would involve a handful of web apps and coordination between them and new and existing enterprise resources. I discovered Web Services, and the problems I was now trying to solve led to the gradual gravitation to enterprise architecture and middleware and before I knew it, I was hooked. Admittedly, it was a great time to make the shift. SOA was king. COM+ had grown up with support for Enterprise Services in .NET and in parallel, this amazing new messaging framework codenamed “Indigo” was in development that would provide a black belt for hungry ninjas like me who wanted to take over the world with SOA. When it came to Indigo, there were two types of members in the community: Those on this inside, and the rest of the world. I was very much part of the rest of the world, but I consumed every bit of content I could get my hands on from folks like Don Box, Juval Lowy, Wenlong Dong, Michele Bustamante and Dr. Nick. </p> <p>Around the same time, a major re-engineering of a product called BizTalk Server was nearing release which took full advantage of the .NET Framework. My employer then, a mid-sized auto retail and finance company was one of the first BizTalk Server 2004 customers in Phoenix. For a fledging enterprise integration architect, this was an awesome opportunity. I learned a ton from my friend Todd Sussman, Brian Loesgen and Adam Smith, the latter of the two I wouldn’t meet in person for a few years, but I had read “BizTalk Server 2004 Unleashed” and “The Blogger’s Guide to BizTalk” from cover to cover more than once. Even better was that I was leading the development of our first SOA and 802.11 enterprise mobility project. We had decided to build the mobile apps- which were a superset of a desktop control center- with ASP.NET. Users would hit the same URL whether they were on the desktop or in the field with their device, and the right screen would render. All of our business logic was wrapped in an ASMX façade which then communicated with our BizTalk orchestrations. With my first real enterprise program under my belt, and WCF nearing GA, I decided that this was what I wanted to do when I grew up, or at least for the next 5 years. </p> <p>Along with WCF, WPF was nearing release. WPF offered a completely different paradigm on which to build traditional Windows apps. Support for rich media like video and sound, flat controls, new gradients all with an incredibly “webby” DHTML-looking design aesthetic. At the time, I remember introspecting that if presentation technologies like this were successful at winning over users, then one day, users won’t care if they are using a browser or an OS to interact with software. What I didn’t realize was to what extent <em><strong>everyone’s</strong></em> cheese was about to be moved. Here we had two tremendously powerful additions to the .NET Framework, poised to revolutionize how we write software from a presentation and back-end perspective, and yet, something subtle was happening that was bigger than Microsoft, bigger than the marvel that is .NET.</p> <p><strong>The Web Reborn</strong></p> <p>Content building SOA solutions in the walled gardens of my employers and clients, almost overnight, I remember when web developers started insisting on me starting to expose JSON endpoints on my services. Apparently, while I was in messaging la la land, users had grown tired of refreshing their browsers and posting back to the server every time they submitted a form. Turns out, I too was one of them! Users were demanding not just a dynamic web experience, but one that was interactive, and felt more like a rich client (a great example at this time was Outlook Web Access). But if you wanted a rich experience, isn’t that why you stuck to the desktop and used WPF? Following the promulgation of XML as the second coming, wasn’t JSON nothing more than an esoteric relic of JavaScript? AJAX had arrived. What followed was a complete disruption of the seeming balance between intended purpose that would shift the pendulum once again to the web. </p> <p>This was about the same time that Microsoft had shared its vision for Software + Services, first unveiled at Mix 07. On the outside, the Mix conference was all about the web, but the reality was that this was also part of a pretty massive campaign to court and win over designers from Adobe/Macromedia to a new technology: WPF/Everywhere, aka Silverlight. While many had been signaling WPF as the return of the smart client, users were accepting an alternate, even degraded user experience in exchange for interop. Silverlight offered a superset of WPF capabilities, delivering a somewhat equally productive design time and development experience as .NET and thus began penetrating Apple and Linux via the ubiquity of the browser. This was the first time I saw Microsoft really understanding that it wasn’t only about .NET and Windows anymore. This was evidenced by prominent PMs on stage demonstrating Silverlight apps on Macs, and running Linux distros on VMs to show that you could write the app once, and run it (almost) everywhere. A number of incredible apps were released on Silverlight including examples like Netflix and Hard Rock Café Memorabilia which were each both a sign of the times and a hint at what was to come.</p> <p>To be sure, this had indeed become a software + services world, and for a while Silverlight looked promising despite the tremendous market footprint that Flash had and continues to have. I remember <a href="http://rickgaribay.net/archive/2007/04/30/Let-There-Be-Silverlight.aspx" target="_blank">writing</a> about how remarkable Silverlight was and what a game changer it could be. But then, an interesting thing happened. JavaScript and REST started appearing more and more in web apps, particularly in the consumer space. At first, despite the popularity of Fielding’s paper, REST seemed like a fringe thing, and in many ways a step backward. Here we had a tremendously powerful consortium of standards built around SOAP representing the intersection of the very few things big players like Microsoft, IBM, Sun and Oracle agreed on. What’s more, it seemed that Microsoft had timed this SOAP bubble (no pun intended) perfectly, with its shiny, new, equally efficacious messaging stack called WCF which was, and still today remains unrivaled by other platform vendors. In addition to HTTP, WCF brought TCP, MSMQ and IPC to the enterprise, offering (proprietary) binary encoding and MTOM for optimizing message exchanges. The programming model had (and continues to have) a learning curve over ASMX, but once you got over the hump, you were on a high summit and could see the world for miles around from this new vantage point. So, why in the world would anyone want to go back to using HTTP POST and POX? How could it be that the world was settling for REST and JavaScript? </p> <p>Simple. The world (and the internet) was changing. A gradual, yet viral shift was taking place fueled by the success of Ruby on Rails and PHP which built the foundation for what is today known as Web 2.0. All of a sudden, anyone with a laptop and an internet connection could download a few packages and get an app up and running in no time. The barrier to entry was financially negligible and because these languages fully embraced HTTP, a tremendous community was born that was as smart as they were entrepreneurial. Interop and reuse were mere side-effects that led to tremendous adoption by everyone with a browser. Fully embracing JavaScript with their productivity boosting libraries that took the sting out of writing JavaScript, similar approaches to packaging robust functionality into libraries such as JQuery followed. In addition, while at first, Ruby on Rails embraced SOAP, it was later replaced with REST. Ask your mother or grandmother what <a href="http://twitter.com/rickggaribay" target="_blank">Twitter</a> or Groupon is and you’ll have the answer as to why REST and JavaScript have persevered. </p> <p>In response to all of this, WCF added support for JSON first, followed by REST, and by the release of .NET 4, both were in the box. In addition, WCF RIA Services was introduced, adding an easy button for integrating with Silverlight clients with the stack, and WCF Data Services provided a REST-friendly approach to managing CRUD operations using ATOM as the message contract. The success of the ASP.NET MVC framework, which has all but subsumed its older, less cool ASP.NET Web Forms sibling, is further evidence of the developer and user community embracing the browser as a conduit for interoperability on the client.</p> <p><strong>The Mobility Wars</strong></p> <p>Even amidst the mobile revolution, which has been largely built on the ubiquity of broadband connections and increasingly capable handheld devices, proprietary platforms have emerged which in many ways are more restrictive, and costly than any other platform. Want to build apps for iOs? Learn Objective C. Android? Got Java? Windows Phone? .NET. Even though they all sit on similar devices and depend on the same infrastructure for messaging (the internet), apps are hardly interoperable with one another. I am sure you know at least two people that carry multiple headsets with them for this very reason, and tablets, sure to be the next wave of mobile innovation suffer from the same dilemma (if you ask me why HP abandoned WebOS, I think it has more to do with the writing on the wall regarding HTML5 than anything else, but more on that shortly). At first, this dilemma seems somewhat benign, perhaps only affecting developers. The truth is it affects everyone. Talk to any iOS developer (that’s not a complete Apple zealot) and they’ll tell you that Objective C isn’t the most productive language to write apps with. Aside from Java not being too sexy these days, I don’t hear many Android (or WP7) users raving about the selection of apps in Android Market. Same goes for WP7 and Windows Marketplace- I remember how long I had to wait to get Angry Birds on my Windows Phone 7! But the most salient example I can think of is the fact that after a decade of browser wars, tremendous innovation on the client and the server, I still can’t play Flash videos on my iPad or WP7. My iPad refuses to run Silverlight apps, even though its browser on the desktop is fully capable of doing so. This is a situation that is just plain broken, and it isn’t just me that feels this way… </p> <p><strong>The World Wants Native Interoperability on the Client, and Today, the Answer is HTML 5.</strong></p> <p>Like it or not, HTTP has become the ubiquitous interface for both the client and its conduit to the backend. This incredibly simple protocol has had more influence on software over the last decade than any other technology, completely reshaping the strategies of the biggest players. I don’t have to tell you that without HTTP, you don’t have cloud computing. For example, who would have thought that Amazon, after pioneering e-commerce would get into the PaaS business by being the first to truly innovate in commercial cloud computing at scale? Who would think that Microsoft would completely reinvent itself on Windows Azure and invest as deeply in REST as it has, not only with standards and technologies like OData and WCF Data Services, but also in exposing their incredibly rich and powerful Azure APIs as REST heads? Again, the answer is simple. HTTP has become the lingua franca of the interconnected world and the disruption started with the first packet in the early 60s. </p> <p>Just as SOAP was developed to aid in interop between vendor platforms, banks and partners, REST has increased the native interoperability of applications on the web. Hold your rotten tomatoes, but I am afraid that so too is the fate of iOS, Android, WP7, WPF, ASP.NET and Silverlight. Are they going away tomorrow, next year or 5 years from now? Nope. SOAP still has a very important place in back-end systems and I don’t mean just for legacy applications. When you you want to work with contracts and interfaces (very important when designing critical message exchanges for business processes), need support for heavy lifting such as distributed transactions, reliable messaging, multiple transports and the like, SOAP is your tool. Case in point as I mentioned briefly above is Windows Azure. While the investment in REST has been significant, these REST endpoints are merely designed for optimizing interop allowing any client or platform to take advantage of the services offered by Microsoft’s cloud. Want to start or stop a compute instance? Need to write a file to blob storage, retrieve an entity from table storage or publish a message for hundreds of subscribers to consume over the AppFabric Service Bus? There’s a REST API for that. While adoption is key to the success of any product or platform, the API, and thus REST is not the end itself but merely a means to the end, and as such is only the tip of the iceberg. Below the water’s surface, there is, and will continue to be a ton of SOAP and .NET.</p> <p>The same is happening on the client with HTML5. While Silverlight and ASP.NET MVC were a step in the right direction and aren’t going to just vanish tomorrow, HTML5 offers true interop at the native (browser) level, and since native interop is what the world wants, it will win, at least for now. I say at least for now because as tempting as it is to chock this up to just another trend, unlike the crusty programmer personas I mentioned when I started this stream of consciousness that has become a rather long post (thanks for staying with me this far, btw), I’ve been doing this long enough to have seen software reinvent itself a few times now. I’ve learned that rather than cry over spilled milk, it is important to embrace change and this means you have to expect and be prepared for anything. HTML 5 could fail, and companies that have already invested significantly in ASP.NET, Silverlight, Flash and one (or several) mobile platforms aren’t going to just jump in right away, but they are going to watch very, very carefully. If I am building a web app or a rich client app today from scratch though, I’m going to think very, very hard before I decide to do so in anything but HTML 5.</p> <p><strong>Who Moved my Cheese?</strong></p> <p>Who would have thought that Microsoft, with an incredibly lucrative productivity, OS, server and tools business would bet the farm on Windows Azure? As innovative as I think Microsoft’s (PaaS) cloud story is, in many ways, it is the software giant’s response to its cheese being moved by the web. And make no mistake, it is a massive bet. Initial buzz around Windows 8 has so far been met with both positive and quite negative feedback after the revelation that Windows 8 will make HTML 5 a first class citizen on the desktop and the tablet. Viewed simplistically, the seams between client and server/backend are exposed with Windows 8 and Microsoft Azure respectively. At first, this seems quite alarming (<a href="http://www.joelonsoftware.com/articles/APIWar.html" target="_blank">Joel Spolsky saw this coming</a> over 8 years ago), but if you think about it, it makes perfect sense. If the client is moving to the browser, the value proposition of a beefy desktop or a rack of servers in an opaque data center is diminished significantly. However, all that data, records, images, videos, files still have to be stored and served up some where, and that somewhere needs to be natively interoperable with the the client at the iceberg and get the heavy lifting done below the water’s surface. The need for middleware- integration between the client, that somewhere and its data, applications and systems has never been greater. </p> <p>Even though I’ve joked to friends that stayed on the front end that I didn’t miss anything by skipping WPF and Silverlight because we’re back to where I first began with HTML and JavaScript, the reality is that the last decade has been incredibly important in reinforcing that innovation is bigger than any platform vendor or standards body because unlike them, it is you and me that determine the fate of technology, and for that we should all be proud.</p> <p><strong>So, What Now?</strong></p> <p>I provide no value without designing distributed solutions that can be consumed by the client applications and automate the business processes they serve. So just as before, its time to buckle down once again and learn the client technologies that one of my primary customers- the UI developer- will soon be using. First in line is Mango. Next is HTML 5. And who knows, after specializing in integration for the last 5 years, I just might start generalizing a bit and get back into web development again.</p> <p>See you at the other end of the wire.</p><img src="http://rickgaribay.net/aggbug/314.aspx" width="1" height="1" /> Rick G. Garibay http://rickgaribay.net/archive/2011/08/22/a-middle-tier-guyrsquos-take-on-html-5.aspx Mon, 22 Aug 2011 22:50:58 GMT http://rickgaribay.net/archive/2011/08/22/a-middle-tier-guyrsquos-take-on-html-5.aspx#feedback 6 http://rickgaribay.net/comments/commentRss/314.aspx http://rickgaribay.net/services/trackbacks/314.aspx