<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-3586668274215233910</atom:id><lastBuildDate>Sun, 31 Jul 2011 07:26:21 +0000</lastBuildDate><category>BizTalk</category><category>Queues</category><category>Quadrant</category><category>.NET Services</category><category>BizUnit</category><category>WCF</category><category>Oslo</category><category>REST</category><category>Azure</category><title>Bits of the old in-out in-out</title><description>Connecting Systems with Microsoft Technology.</description><link>http://bitsinout.blogspot.com/</link><managingEditor>noreply@blogger.com (Paul Arundel)</managingEditor><generator>Blogger</generator><openSearch:totalResults>13</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/bitsinout" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="bitsinout" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3586668274215233910.post-2547551329989982576</guid><pubDate>Fri, 15 Jan 2010 10:49:00 +0000</pubDate><atom:updated>2010-01-15T11:31:31.852Z</atom:updated><category domain="http://www.blogger.com/atom/ns#">BizTalk</category><category domain="http://www.blogger.com/atom/ns#">Azure</category><category domain="http://www.blogger.com/atom/ns#">WCF</category><title>Inserting an Entity into Azure Table Storage from BizTalk</title><description>&lt;div&gt;Following on from my previous &lt;a href="http://bitsinout.blogspot.com/2009/10/using-biztalk-wcf-custom-adapter-to.html"&gt;post&lt;/a&gt; where I used a custom WCF adapter to insert a BizTalk message into Azure blob storage I wanted to try the same but with Azure Table storage. This would of course have been more meaningful if it had followed immediately after my previous post and not three months after. I blame Christmas.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;An Azure table is not like the familiar relational tables we get with SQL Server. If you want one of those in the cloud try &lt;a href="http://www.microsoft.com/windowsazure/sqlazure/"&gt;SQL Azure&lt;/a&gt;. Azure tables are schema-less and designed for scalability. As an individual table has no schema you can insert different entity types with different properties into the same table and it won't mind a bit. This allows you to store types that are naturally retrieved at the same time (say an Order and it's Order items) in the same table and optimize your queries appropriately. This is partly achieved by each table entity having two keys, a partition key and a row key, which jointly make up an entity's unique key. The partition key plays the important role in that entities with the same partition key will be stored consecutively on the same storage node, therefore avoiding queries having to scan multiple storage nodes for entities with a particular partition key. This is, at least, how I understand it. (This is also possibly irrelevant unless you are dealing with a lot of entity rows).&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Inserting a record into an Azure table is detailed in the API &lt;a href="http://msdn.microsoft.com/en-us/library/dd179433.aspx"&gt;here&lt;/a&gt;. This is similar to that detailed for inserting to blob storage: we set a few HTTP headers, include our data in the body of the message and make a REST like call. It differs in that the HTTP method is a POST rather than a PUT, additional HTTP headers are required and the message body (our entity data) has to be inserted as an Atom feed entry. So my first task was to map my message instance to the required Atom entry format:&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_Sc3uxihjOeo/S1BIqOHsJ4I/AAAAAAAAAFg/WZJ-KCKFm4I/s1600-h/mapatom.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 174px;" src="http://3.bp.blogspot.com/_Sc3uxihjOeo/S1BIqOHsJ4I/AAAAAAAAAFg/WZJ-KCKFm4I/s400/mapatom.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5426917441163503490" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;As there are no defined XSD for the Atom format I had to create my own schema for the various elements/namespaces required. I'm a little frustrated with the schema I ended up with as it's quite unsophisticated and doesn't leave much room for re-use (i.e. wrapping entities other than my sample 'customer' schema):&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="xml:nogutter"&gt;&lt;br /&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-16&amp;quot;?&amp;gt;&lt;br /&gt;&amp;lt;xs:schema xmlns:m=&amp;quot;http://schemas.microsoft.com/ado/2007/08/dataservices/metadata&amp;quot; xmlns:b=&amp;quot;http://schemas.microsoft.com/BizTalk/2003&amp;quot; xmlns=&amp;quot;http://www.w3.org/2005/Atom&amp;quot; elementFormDefault=&amp;quot;qualified&amp;quot; targetNamespace=&amp;quot;http://www.w3.org/2005/Atom&amp;quot; xmlns:xs=&amp;quot;http://www.w3.org/2001/XMLSchema&amp;quot;&amp;gt;&lt;br /&gt;  &amp;lt;xs:import schemaLocation=&amp;quot;.\dataservicescustomermeta.xsd&amp;quot; namespace=&amp;quot;http://schemas.microsoft.com/ado/2007/08/dataservices/metadata&amp;quot; /&amp;gt;&lt;br /&gt;  &amp;lt;xs:annotation&amp;gt;&lt;br /&gt;    &amp;lt;xs:appinfo&amp;gt;&lt;br /&gt;      &amp;lt;b:references&amp;gt;&lt;br /&gt;        &amp;lt;b:reference targetNamespace=&amp;quot;http://schemas.microsoft.com/ado/2007/08/dataservices/metadata&amp;quot; /&amp;gt;&lt;br /&gt;        &amp;lt;b:reference targetNamespace=&amp;quot;http://schemas.microsoft.com/ado/2007/08/dataservices&amp;quot; /&amp;gt;&lt;br /&gt;      &amp;lt;/b:references&amp;gt;&lt;br /&gt;    &amp;lt;/xs:appinfo&amp;gt;&lt;br /&gt;  &amp;lt;/xs:annotation&amp;gt;&lt;br /&gt;  &amp;lt;xs:complexType name=&amp;quot;AtomEntryType&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;xs:sequence&amp;gt;&lt;br /&gt;      &amp;lt;xs:element name=&amp;quot;title&amp;quot; type=&amp;quot;xs:string&amp;quot; /&amp;gt;&lt;br /&gt;      &amp;lt;xs:element name=&amp;quot;updated&amp;quot; type=&amp;quot;xs:string&amp;quot; /&amp;gt;&lt;br /&gt;      &amp;lt;xs:element name=&amp;quot;author&amp;quot;&amp;gt;&lt;br /&gt;        &amp;lt;xs:complexType&amp;gt;&lt;br /&gt;          &amp;lt;xs:sequence&amp;gt;&lt;br /&gt;            &amp;lt;xs:element name=&amp;quot;name&amp;quot; type=&amp;quot;xs:string&amp;quot; /&amp;gt;&lt;br /&gt;          &amp;lt;/xs:sequence&amp;gt;&lt;br /&gt;        &amp;lt;/xs:complexType&amp;gt;&lt;br /&gt;      &amp;lt;/xs:element&amp;gt;&lt;br /&gt;      &amp;lt;xs:element name=&amp;quot;id&amp;quot; type=&amp;quot;xs:string&amp;quot; /&amp;gt;&lt;br /&gt;      &amp;lt;xs:element name=&amp;quot;content&amp;quot;&amp;gt;&lt;br /&gt;        &amp;lt;xs:complexType&amp;gt;&lt;br /&gt;          &amp;lt;xs:sequence&amp;gt;&lt;br /&gt;            &amp;lt;xs:element ref=&amp;quot;m:properties&amp;quot; /&amp;gt;&lt;br /&gt;          &amp;lt;/xs:sequence&amp;gt;&lt;br /&gt;          &amp;lt;xs:attribute default=&amp;quot;application/xml&amp;quot; name=&amp;quot;type&amp;quot; type=&amp;quot;xs:string&amp;quot; /&amp;gt;&lt;br /&gt;        &amp;lt;/xs:complexType&amp;gt;&lt;br /&gt;      &amp;lt;/xs:element&amp;gt;&lt;br /&gt;    &amp;lt;/xs:sequence&amp;gt;&lt;br /&gt;  &amp;lt;/xs:complexType&amp;gt;&lt;br /&gt;  &amp;lt;xs:element name=&amp;quot;entry&amp;quot; type=&amp;quot;AtomEntryType&amp;quot; /&amp;gt;&lt;br /&gt;&amp;lt;/xs:schema&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-16&amp;quot;?&amp;gt;&lt;br /&gt;&amp;lt;xs:schema xmlns:b=&amp;quot;http://schemas.microsoft.com/BizTalk/2003&amp;quot; xmlns=&amp;quot;http://schemas.microsoft.com/ado/2007/08/dataservices&amp;quot; elementFormDefault=&amp;quot;qualified&amp;quot; targetNamespace=&amp;quot;http://schemas.microsoft.com/ado/2007/08/dataservices&amp;quot; xmlns:xs=&amp;quot;http://www.w3.org/2001/XMLSchema&amp;quot;&amp;gt;&lt;br /&gt;  &amp;lt;xs:element name=&amp;quot;RowKey&amp;quot; type=&amp;quot;xs:string&amp;quot; /&amp;gt;&lt;br /&gt;  &amp;lt;xs:element name=&amp;quot;PartitionKey&amp;quot; type=&amp;quot;xs:string&amp;quot; /&amp;gt;&lt;br /&gt;  &amp;lt;xs:element name=&amp;quot;TimeStamp&amp;quot; type=&amp;quot;xs:string&amp;quot; /&amp;gt;&lt;br /&gt;  &amp;lt;xs:element name=&amp;quot;FirstName&amp;quot; type=&amp;quot;xs:string&amp;quot; /&amp;gt;&lt;br /&gt;  &amp;lt;xs:element name=&amp;quot;LastName&amp;quot; type=&amp;quot;xs:string&amp;quot; /&amp;gt;&lt;br /&gt;  &amp;lt;xs:element name=&amp;quot;Email&amp;quot; type=&amp;quot;xs:string&amp;quot; /&amp;gt;&lt;br /&gt;&amp;lt;/xs:schema&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-16&amp;quot;?&amp;gt;&lt;br /&gt;&amp;lt;xs:schema xmlns=&amp;quot;http://schemas.microsoft.com/ado/2007/08/dataservices/metadata&amp;quot; xmlns:b=&amp;quot;http://schemas.microsoft.com/BizTalk/2003&amp;quot; xmlns:d=&amp;quot;http://schemas.microsoft.com/ado/2007/08/dataservices&amp;quot; elementFormDefault=&amp;quot;qualified&amp;quot; targetNamespace=&amp;quot;http://schemas.microsoft.com/ado/2007/08/dataservices/metadata&amp;quot; xmlns:xs=&amp;quot;http://www.w3.org/2001/XMLSchema&amp;quot;&amp;gt;&lt;br /&gt;  &amp;lt;xs:import schemaLocation=&amp;quot;.\dataservicescustomer.xsd&amp;quot; namespace=&amp;quot;http://schemas.microsoft.com/ado/2007/08/dataservices&amp;quot; /&amp;gt;&lt;br /&gt;  &amp;lt;xs:annotation&amp;gt;&lt;br /&gt;    &amp;lt;xs:appinfo&amp;gt;&lt;br /&gt;      &amp;lt;b:references&amp;gt;&lt;br /&gt;        &amp;lt;b:reference targetNamespace=&amp;quot;http://schemas.microsoft.com/ado/2007/08/dataservices&amp;quot; /&amp;gt;&lt;br /&gt;      &amp;lt;/b:references&amp;gt;&lt;br /&gt;    &amp;lt;/xs:appinfo&amp;gt;&lt;br /&gt;  &amp;lt;/xs:annotation&amp;gt;&lt;br /&gt;  &amp;lt;xs:element name=&amp;quot;properties&amp;quot; type=&amp;quot;PropertiesType&amp;quot; /&amp;gt;&lt;br /&gt;  &amp;lt;xs:complexType name=&amp;quot;PropertiesType&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;xs:sequence&amp;gt;&lt;br /&gt;      &amp;lt;xs:element ref=&amp;quot;d:PartitionKey&amp;quot; /&amp;gt;&lt;br /&gt;      &amp;lt;xs:element ref=&amp;quot;d:RowKey&amp;quot; /&amp;gt;&lt;br /&gt;      &amp;lt;xs:element ref=&amp;quot;d:TimeStamp&amp;quot; /&amp;gt;&lt;br /&gt;      &amp;lt;xs:element ref=&amp;quot;d:FirstName&amp;quot; /&amp;gt;&lt;br /&gt;      &amp;lt;xs:element ref=&amp;quot;d:LastName&amp;quot; /&amp;gt;&lt;br /&gt;      &amp;lt;xs:element ref=&amp;quot;d:Email&amp;quot; /&amp;gt;&lt;br /&gt;    &amp;lt;/xs:sequence&amp;gt;&lt;br /&gt;  &amp;lt;/xs:complexType&amp;gt;&lt;br /&gt;&amp;lt;/xs:schema&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;To configure the send port we can directly set the port URL to the table end point address http://[accountname].table.core.windows.net/[tablename]. Unlike Blob storage we don't need to include a unique Id in the URL we just need to use the table address. Therefore my custom WCF behavior does not need to use manual addressing in this case nor does it need to set the HTTP method as it is POST by default.&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Sc3uxihjOeo/S1BMYD6ClKI/AAAAAAAAAF4/Kg-iM9tb8Ho/s1600-h/manualaddressingfalse.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 334px; height: 400px;" src="http://1.bp.blogspot.com/_Sc3uxihjOeo/S1BMYD6ClKI/AAAAAAAAAF4/Kg-iM9tb8Ho/s400/manualaddressingfalse.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5426921527230764194" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;This simplifies the code in the behavior somewhat (Apart from the two methods below, the code remains as my previous post). &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp:nogutter"&gt;&lt;br /&gt;public object BeforeSendRequest(ref Message request, IClientChannel channel)&lt;br /&gt;{&lt;br /&gt;    HttpRequestMessageProperty httpProp = GetOrCreateHttpProperty(request);&lt;br /&gt;    &lt;br /&gt;    string contentType = &amp;quot;application/atom+xml&amp;quot;;&lt;br /&gt;&lt;br /&gt;    //we need the same date in both the auth string and http headers&lt;br /&gt;    DateTime date = DateTime.Now;&lt;br /&gt;&lt;br /&gt;    string authorizationHeader =&lt;br /&gt;        AzureAuthorizationHeader.GetAuthorizationString(_azureAccountName,&lt;br /&gt;                         Convert.FromBase64String(_azureAccountKey),&lt;br /&gt;                         _httpMethod,&lt;br /&gt;                         contentType,&lt;br /&gt;                         date,&lt;br /&gt;                         channel.RemoteAddress.Uri.AbsolutePath);&lt;br /&gt;                                                                &lt;br /&gt;          &lt;br /&gt;    httpProp.Headers.Add(&amp;quot;Authorization&amp;quot;, authorizationHeader);&lt;br /&gt;    httpProp.Headers.Add(&amp;quot;x-ms-date&amp;quot;,AzureAuthorizationHeader.GetFormattedDate(date));&lt;br /&gt;    httpProp.Headers.Add(&amp;quot;Content-Type&amp;quot;, contentType);&lt;br /&gt;    httpProp.Headers.Add(&amp;quot;DataServiceVersion&amp;quot;, &amp;quot;1.0;NetFx&amp;quot;);&lt;br /&gt;    httpProp.Headers.Add(&amp;quot;MaxDataServiceVersion&amp;quot;, &amp;quot;1.0;NetFx&amp;quot;);&lt;br /&gt;    httpProp.Headers.Add(&amp;quot;Accept&amp;quot;, &amp;quot;application/atom+xml,application/xml&amp;quot;);&lt;br /&gt;    httpProp.Headers.Add(&amp;quot;Accept-Charset&amp;quot;, &amp;quot;UTF-8&amp;quot;);&lt;br /&gt;    return null;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public static string GetSignatureString(string accountName,&lt;br /&gt;                                        string method,&lt;br /&gt;                                        string contentType,&lt;br /&gt;                                        DateTime date,&lt;br /&gt;                                        string resourcePath)&lt;br /&gt;{&lt;br /&gt;    string CanonicalizedResource = string.Format(&amp;quot;/{0}{1}&amp;quot;,accountName,resourcePath);&lt;br /&gt;&lt;br /&gt;    return string.Format(&amp;quot;{0}\n{1}\n{2}\n{3}\n{4}&amp;quot;,&lt;br /&gt;                         method.ToUpper(),&lt;br /&gt;                         string.Empty, //ContentMD5 empty&lt;br /&gt;                         contentType,&lt;br /&gt;                         GetFormattedDate(date), //can use x-ms-Date&lt;br /&gt;                         CanonicalizedResource);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;A few other changes from Blob storage. We need to set additional headers as shown in the code. The authorization header string is also structured differently and does not include the &lt;a href="http://msdn.microsoft.com/en-us/library/dd179428.aspx"&gt;CanonicalizedHeaders part&lt;/a&gt;. &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Finally let's set Fiddler as a proxy on the send port and see what we send on the wire on a successful insert:&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_Sc3uxihjOeo/S1BMin9lr6I/AAAAAAAAAGA/63yXMffyVIg/s1600-h/fiddlerraw.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 254px;" src="http://2.bp.blogspot.com/_Sc3uxihjOeo/S1BMin9lr6I/AAAAAAAAAGA/63yXMffyVIg/s400/fiddlerraw.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5426921708708016034" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3586668274215233910-2547551329989982576?l=bitsinout.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bitsinout.blogspot.com/2010/01/inserting-entity-into-azure-table.html</link><author>noreply@blogger.com (Paul Arundel)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_Sc3uxihjOeo/S1BIqOHsJ4I/AAAAAAAAAFg/WZJ-KCKFm4I/s72-c/mapatom.jpg" height="72" width="72" /><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3586668274215233910.post-5214420053321544336</guid><pubDate>Wed, 28 Oct 2009 22:12:00 +0000</pubDate><atom:updated>2009-10-30T22:16:19.994Z</atom:updated><category domain="http://www.blogger.com/atom/ns#">BizTalk</category><category domain="http://www.blogger.com/atom/ns#">REST</category><category domain="http://www.blogger.com/atom/ns#">Azure</category><category domain="http://www.blogger.com/atom/ns#">WCF</category><title>Using a BizTalk WCF-Custom adapter to directly send messages to Azure Storage</title><description>&lt;div&gt;In this post I want to look at sending a message from BizTalk directly to Azure blob storage. Accessing Azure Storage is exclusively via a REST API so we should hopefully be able to do this with the standard adapters (HTTP or WCF) and not need to resort to writing our own custom adapters.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;To store a message in Blob storage, the &lt;a href="http://msdn.microsoft.com/en-us/library/dd179451.aspx"&gt;API&lt;/a&gt; defines the destination URL as: http://myaccount.blob.core.windows.net/mycontainer/myblob. Presuming we already have the a blob storage container created it doesn't seem unreasonable to set the URL including the container in the send port config.  However the 'myblob' part will need to be our unique key for the blob so we will have to set that programmatically. We will also need to set the HTTP method to 'PUT' rather than POST (the default) to store our message. Finally the API defines a number of required HTTP headers: Authorization, Date (or x-ms-date), Content-Length and Content-Type.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Using the HTTP adapter to get around these issues would appear to be awkward. We could set the HTTP headers by using the HTTP Adapter Property 'UserHttpHeaders' in an orchestration or custom pipeline. However the Authorization header encoded string needs to include (see later) our destination URL, something I want to have stored in our port. We could try a dynamic port (and annoyingly store our URL config elsewhere) but we would then have to get around the problem of the HTTP adapter using the HTTP 'POST' method.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;WCF's configuration and extensibility options appear to be a better option. Though the obvious choice, using the 'REST friendly' webHttpBinding, does not appear to work. I could not get a simple BizTalk WCF-Custom send port, using the webHttpBinding (with webHttpBehavior added) and all default config to send a message of any kind without error. A few blog/forum posts relating to 2006 R2 indicate the binding is not supported (due to the contracts BizTalk defines). Presumably it's still not supported for 2009 but maybe I'm missing something?&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Happily I found Jon Flanders &lt;a href="http://www.masteringbiztalk.com/blogs/jon/PermaLink,guid,90f1db62-b42f-4be3-b9d7-36cd4319c97c.aspx"&gt;presentation&lt;/a&gt; on using BizTalk 2006 R2 with a REST service (the approach is also detailed &lt;a href="http://msdn.microsoft.com/en-us/library/aa738456.aspx"&gt;here&lt;/a&gt;). Without going into the full details of the presentation, he wants to use a WCF send adapter to send a 'GET' request to a REST service. Firstly he uses a customBinding with HTTPTransport to get around BizTalk not playing nice with the webHTTPBinding and sets the MessageVersion to 'None' to remove the SOAP wrapper. Secondly he codes up a WCF behavior extension to set the HTTP method to 'GET' as the message is passed through the WCF channel stack. This is exactly what I need to do.&lt;/div&gt; &lt;br /&gt;&lt;div&gt;The code for my WCF behavior extension is further below, but I will show you the BizTalk send port configuration:&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Sc3uxihjOeo/SujCz_bLuUI/AAAAAAAAAFE/5Aw9E4_rkMU/s1600-h/sendport.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 291px;" src="http://1.bp.blogspot.com/_Sc3uxihjOeo/SujCz_bLuUI/AAAAAAAAAFE/5Aw9E4_rkMU/s400/sendport.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5397778351858104642" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;The next dialog shows the customBinding with TextMessageEncodingElement and HttpTransportElement (note manualAddressing is set to 'true'):&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_Sc3uxihjOeo/SujC-WGSDgI/AAAAAAAAAFM/VWjKSaRlTgA/s1600-h/binding.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 332px; height: 400px;" src="http://2.bp.blogspot.com/_Sc3uxihjOeo/SujC-WGSDgI/AAAAAAAAAFM/VWjKSaRlTgA/s400/binding.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5397778529743146498" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;Configuring the WCF behavior extension I have added:&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Sc3uxihjOeo/SujDGY648oI/AAAAAAAAAFU/q33WhZTGPxA/s1600-h/behavior.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 326px; height: 400px;" src="http://4.bp.blogspot.com/_Sc3uxihjOeo/SujDGY648oI/AAAAAAAAAFU/q33WhZTGPxA/s400/behavior.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5397778667939623554" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;The code for the behavior performs a few tasks and is all completed in the BeforeSendRequest method of a IClientMessageInspector. First it sets the HTTP method to the supplied verb as in John's presentation. It then creates a new destination address by concatenating the current remote address with a unique ID acting as the blob storage key. I use a GUID for the key, but for BizTalk messaging this could be updated to something more useful, possibly from the message data. The new address is then set on the &lt;b&gt;request.Headers.To&lt;/b&gt; property. This can change the destination address as having manual addressing set to 'true' allows us to change the address after the channel stack has been created. I then create the signature for the Authorization header (see below) and set the other HTTP headers required by Azure Storage. (note: I haven't shown the other empty interface methods)&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp:nogutter"&gt;&lt;br /&gt;public class AzureStorageBehavior : IEndpointBehavior, IClientMessageInspector&lt;br /&gt;{&lt;br /&gt;    public string _httpMethod;&lt;br /&gt;    public string _azureAccountName;&lt;br /&gt;    public string _azureAccountKey;&lt;br /&gt;&lt;br /&gt;    public AzureStorageBehavior(string method, string account, string key)&lt;br /&gt;    {&lt;br /&gt;        _httpMethod = method;&lt;br /&gt;        _azureAccountName = account;&lt;br /&gt;        _azureAccountKey = key;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public object BeforeSendRequest(ref Message request, IClientChannel channel)&lt;br /&gt;    {&lt;br /&gt;        HttpRequestMessageProperty httpProp = GetOrCreateHttpProperty(request);&lt;br /&gt;        httpProp.Method = _httpMethod;&lt;br /&gt;&lt;br /&gt;        //todo just create a guid blob item name for the moment&lt;br /&gt;        string id = Guid.NewGuid().ToString();&lt;br /&gt;&lt;br /&gt;        //manually address&lt;br /&gt;        request.Headers.To = new Uri(channel.RemoteAddress.Uri, id);&lt;br /&gt;&lt;br /&gt;        //todo set content&lt;br /&gt;        string contentType = &amp;quot;text/xml&amp;quot;;&lt;br /&gt;&lt;br /&gt;        //we need the same date in both the auth string and http headers&lt;br /&gt;        DateTime date = DateTime.Now;&lt;br /&gt;&lt;br /&gt;        string authorizationHeader =&lt;br /&gt;            AzureAuthorizationHeader.GetAuthorizationString(_azureAccountName,&lt;br /&gt;                                                            Convert.FromBase64String(_azureAccountKey),&lt;br /&gt;                                                            _httpMethod,&lt;br /&gt;                                                            contentType,&lt;br /&gt;                                                            date,&lt;br /&gt;                                                            request.Headers.To.AbsolutePath);&lt;br /&gt;        //required for Azure Blob Storage&lt;br /&gt;        httpProp.Headers.Add(&amp;quot;Authorization&amp;quot;, authorizationHeader);&lt;br /&gt;        httpProp.Headers.Add(&amp;quot;x-ms-date&amp;quot;, AzureAuthorizationHeader.GetFormattedDate(date));&lt;br /&gt;        httpProp.Headers.Add(&amp;quot;Content-Type&amp;quot;, contentType);&lt;br /&gt;&lt;br /&gt;        return null;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)&lt;br /&gt;    {&lt;br /&gt;        clientRuntime.MessageInspectors.Add(this);&lt;br /&gt;    }&lt;br /&gt;    //snip&lt;br /&gt;}&lt;br /&gt;public class AzureStorageBehaviorExtension : BehaviorExtensionElement&lt;br /&gt;{&lt;br /&gt;    protected override object CreateBehavior()&lt;br /&gt;    {&lt;br /&gt;        return new AzureStorageBehavior(HTTPMethod, AzureAccountName, AzureAccountKey);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    [ConfigurationProperty(&amp;quot;httpMethod&amp;quot;)]&lt;br /&gt;    public string HTTPMethod&lt;br /&gt;    {&lt;br /&gt;        get { return (string)base[&amp;quot;httpMethod&amp;quot;]; }&lt;br /&gt;        set { base[&amp;quot;httpMethod&amp;quot;] = value; }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    [ConfigurationProperty(&amp;quot;azureAccountName&amp;quot;)]&lt;br /&gt;    public string AzureAccountName&lt;br /&gt;    {&lt;br /&gt;        get { return (string)base[&amp;quot;azureAccountName&amp;quot;]; }&lt;br /&gt;        set { base[&amp;quot;azureAccountName&amp;quot;] = value; }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    [ConfigurationProperty(&amp;quot;azureAccountKey&amp;quot;)]&lt;br /&gt;    public string AzureAccountKey&lt;br /&gt;    {&lt;br /&gt;        get { return (string)base[&amp;quot;azureAccountKey&amp;quot;]; }&lt;br /&gt;        set { base[&amp;quot;azureAccountKey&amp;quot;] = value; }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public override Type BehaviorType&lt;br /&gt;    {&lt;br /&gt;        get { return typeof(AzureStorageBehavior); }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;The code below shows the few static methods I have created to form the Authorization signature for the HTTP header. The code is a minimal implementation to meet the requirements as detailed in the Authentication Schemes &lt;a href="http://msdn.microsoft.com/en-us/library/dd179428.aspx"&gt;reference&lt;/a&gt; and from looking at the StorageClient sample in the Azure SDK. It's mostly a matter of concatenating the various required elements and signing the resultant string with the Azure key:&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp:nogutter"&gt;&lt;br /&gt;public class AzureAuthorizationHeader&lt;br /&gt;{&lt;br /&gt;    public static string GetAuthorizationString(string accountName,&lt;br /&gt;                                        byte[] key,&lt;br /&gt;                                        string method,&lt;br /&gt;                                        string contentType,&lt;br /&gt;                                        DateTime date,&lt;br /&gt;                                        string resourcePath)&lt;br /&gt;    {&lt;br /&gt;        string signatureString = GetSignatureString(accountName, method, contentType, date, resourcePath);&lt;br /&gt;&lt;br /&gt;        return string.Format(&amp;quot;SharedKey {0}:{1}&amp;quot;, accountName, EncodeSignature(signatureString, key));&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    //from api sample&lt;br /&gt;    public static string EncodeSignature(string signatureString, byte[] key)&lt;br /&gt;    {&lt;br /&gt;&lt;br /&gt;        byte[] dataToMAC = System.Text.Encoding.UTF8.GetBytes(signatureString);&lt;br /&gt;&lt;br /&gt;        using (HMACSHA256 hmacsha1 = new HMACSHA256(key))&lt;br /&gt;        {&lt;br /&gt;            return System.Convert.ToBase64String(hmacsha1.ComputeHash(dataToMAC));&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public static string GetSignatureString(string accountName,&lt;br /&gt;                                            string method,&lt;br /&gt;                                            string contentType,&lt;br /&gt;                                            DateTime date,&lt;br /&gt;                                            string resourcePath)&lt;br /&gt;    {&lt;br /&gt;        //just the date header &lt;br /&gt;        string canonicalizedHeaders = string.Format(&amp;quot;x-ms-date:{0}&amp;quot;, GetFormattedDate(date));&lt;br /&gt;        string CanonicalizedResource = string.Format(&amp;quot;/{0}{1}&amp;quot;, accountName, resourcePath);&lt;br /&gt;&lt;br /&gt;        return string.Format(&amp;quot;{0}\n{1}\n{2}\n{3}\n{4}\n{5}&amp;quot;,&lt;br /&gt;                               method.ToUpper(),&lt;br /&gt;                               string.Empty, //ContentMD5 empty&lt;br /&gt;                               contentType,&lt;br /&gt;                               String.Empty, //Date HTTP header empty - have to use x-ms-Date&lt;br /&gt;                               canonicalizedHeaders,&lt;br /&gt;                               CanonicalizedResource);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public static string GetFormattedDate(DateTime date)&lt;br /&gt;    {&lt;br /&gt;        return date.ToString(&amp;quot;R&amp;quot;, CultureInfo.InvariantCulture);&lt;br /&gt;    } &lt;br /&gt;} &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;As I've used a standard WCF behavior to achieve this, it doesn't have to be used along with BizTalk and could be used just as easily from a normal WCF client. But in either case the entire mechanism is abstracted away within the WCF endpoint configuration.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3586668274215233910-5214420053321544336?l=bitsinout.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bitsinout.blogspot.com/2009/10/using-biztalk-wcf-custom-adapter-to.html</link><author>noreply@blogger.com (Paul Arundel)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_Sc3uxihjOeo/SujCz_bLuUI/AAAAAAAAAFE/5Aw9E4_rkMU/s72-c/sendport.JPG" height="72" width="72" /><thr:total>5</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3586668274215233910.post-2285521790201988101</guid><pubDate>Wed, 30 Sep 2009 14:42:00 +0000</pubDate><atom:updated>2009-09-30T16:36:08.851+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Azure</category><category domain="http://www.blogger.com/atom/ns#">.NET Services</category><title>Using an Azure Worker Process to Read and Store Messages from a Service Bus Queue</title><description>&lt;div&gt;Well, the forthcoming &lt;a href="http://blogs.msdn.com/netservices/archive/2009/09/18/update-on-the-next-microsoft-net-services-ctp.aspx"&gt;October &lt;/a&gt;updates to the .NET Services CTP have just about scuppered the project I have been working on and blogging about. Routers are being 'Temporarily' removed, Queues are being replaced with 'Message Buffers' and we can no longer subscribe external endpoints to Routers, doing away with the means to &lt;a href="http://bitsinout.blogspot.com/2009/07/net-services-routers-pushing-to.html"&gt;push messages&lt;/a&gt; to services outside of the service bus. Presumably these features have been temporarily dropped so the .NET Services developers can focus on the remaining features for the first release. But in that case why replace Queues with the new Message Buffers? And when Routers, which share a common API to Queues, re-appear will they also be in a changed form? No update yet from &lt;a href="http://vasters.com/clemensv/default.aspx"&gt;Clemens&lt;/a&gt;.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Anyway I still want to continue getting a feel for running processes in the Azure cloud and the possibilities it offers. For this post I'm going to switch my attention to the Windows Azure part of the Windows Azure Platform and take a look at worker roles and storage. In my last &lt;a href="http://bitsinout.blogspot.com/2009/09/net-services-queues.html"&gt;post&lt;/a&gt; I looked at an external client retrieving messages from a .NET Services Queue which was, in turn, receiving messages from a Router. Now my aim is to have a worker process running on the Azure cloud pulling messages from a .NET Services Queue at regular intervals and securely storing the messages with the Azure Blob service. This could act as a message archiving service for backup or auditing requirements and could be easily hooked up to any process using .NET Services Routers. It is similar in aim to &lt;a href="http://geekswithblogs.net/michaelstephenson/archive/2009/04/02/130659.aspx"&gt;Mike Stephenson's&lt;/a&gt; Azure Pipeline Component for BizTalk, though in this case all the processes are running in the cloud: message routers, queues and storage. Taking the diagram from my last post I will now add an additional process to archive any messages published to the router:&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Sc3uxihjOeo/SsNvM_VHz-I/AAAAAAAAAEU/8YCXCYIL7bc/s1600-h/archivediag.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 244px;" src="http://4.bp.blogspot.com/_Sc3uxihjOeo/SsNvM_VHz-I/AAAAAAAAAEU/8YCXCYIL7bc/s400/archivediag.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5387271848214384610" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;I will use an Azure worker role to continuously check the Queue for messages. A worker role is basically a background process running in the cloud that does not expose any endpoints and therefore executes at its own schedule. Once the Azure tools are installed, you can create a worker process project by using one of the cloud service templates, 'Worker Cloud Service' in this case. This creates some sample code for your worker process:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp:nogutter"&gt;&lt;br /&gt;public class WorkerRole : RoleEntryPoint&lt;br /&gt;{&lt;br /&gt;    public override void Start()&lt;br /&gt;    {&lt;br /&gt;        // This is a sample worker implementation. Replace with your logic.&lt;br /&gt;        RoleManager.WriteToLog(&amp;quot;Information&amp;quot;, &amp;quot;Worker Process entry point called&amp;quot;);&lt;br /&gt;&lt;br /&gt;        while (true)&lt;br /&gt;        {&lt;br /&gt;            Thread.Sleep(10000);&lt;br /&gt;            RoleManager.WriteToLog(&amp;quot;Information&amp;quot;, &amp;quot;Working&amp;quot;);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public override RoleStatus GetHealthStatus()&lt;br /&gt;    {&lt;br /&gt;        // This is a sample worker implementation. Replace with your logic.&lt;br /&gt;        return RoleStatus.Healthy;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;My worker process, will need to complete two tasks, check the Service Bus queue for new messages and store any new messages in blob storage. I've implemented a couple of simple classes to do these tasks and updated the worker process code:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp:nogutter"&gt;&lt;br /&gt;public override void Start()&lt;br /&gt;{&lt;br /&gt;    RoleManager.WriteToLog(&amp;quot;Information&amp;quot;, &amp;quot;Worker Process entry point called&amp;quot;);&lt;br /&gt;    QueueReader qr = new QueueReader(&amp;quot;bitsinout&amp;quot;, &amp;quot;/ProductUpdate/QueueSubscriber/&amp;quot;);&lt;br /&gt;    MessageArchive ma = new MessageArchive(&amp;quot;testarchive&amp;quot;);&lt;br /&gt;    while (true)&lt;br /&gt;    {&lt;br /&gt;        Thread.Sleep(10000);&lt;br /&gt;        RoleManager.WriteToLog(&amp;quot;Information&amp;quot;, &amp;quot;Checking Queue.&amp;quot;);&lt;br /&gt;        string response = qr.CheckQueue();&lt;br /&gt;               &lt;br /&gt;        if (!String.IsNullOrEmpty(response))&lt;br /&gt;        {&lt;br /&gt;            RoleManager.WriteToLog(&amp;quot;Information&amp;quot;, response);&lt;br /&gt;            ma.StoreMessage(Guid.NewGuid().ToString(),response);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;My QueueReader class uses the .NET Services API and helper functions as in my last post. I construct the QueueReader with the name of my .NET Services solution and the path to the Queue we are interested in. Obviously this information should really be retrieved from a configuration store. It also wouldn't be too much work to supply a number of queue addresses enabling a single worker process to check multiple queues. (Note: when using the .NET Services API from a worker role project you will get a 'partially trusted' assembly error unless you set  enableNativeCodeExecution="true" in the ServiceDefinition.csdef file.)&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp:nogutter"&gt;&lt;br /&gt;public string CheckQueue()&lt;br /&gt;{&lt;br /&gt;    QueueClient client = GetOrCreateQueue(_queueUri);&lt;br /&gt;    string response = null;&lt;br /&gt;&lt;br /&gt;    try&lt;br /&gt;    {&lt;br /&gt;        Message m = client.Retrieve(new TimeSpan(0, 0, 5));&lt;br /&gt;        response = m.GetBody&amp;lt;string&amp;gt;();&lt;br /&gt;    }&lt;br /&gt;    catch (TimeoutException){}&lt;br /&gt;&lt;br /&gt;    return response;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;For simplicity I use the client.Retrieve() method but as discussed before we could retrieve multiple messages or use the Peek/Lock methods for better reliability. I'll have to update this to use Message Buffers when the new CTP arrives.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Finally my MessageArchive class stores the message (a string) in blob storage. I use the StorageClient sample provided with the Azure SDK to store my messages. This sample is actually a wrapper around a REST interface which is currently the only way to interact with azure storage. The StorageClient is &lt;a href="http://social.msdn.microsoft.com/Forums/en-US/windowsazure/thread/e1f749bc-aa7c-4e64-8adf-dbd43a559c31"&gt;strictly&lt;/a&gt; not an API at the moment, but probably gives us a good indication of what an official .NET API will look like.&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp:nogutter"&gt;&lt;br /&gt;public class MessageArchive&lt;br /&gt;{&lt;br /&gt;    BlobContainer _container;&lt;br /&gt;    public MessageArchive(string containerName)&lt;br /&gt;    {&lt;br /&gt;        StorageAccountInfo account = &lt;br /&gt;          new StorageAccountInfo(new Uri(&amp;quot;http://blob.core.windows.net/&amp;quot;),&lt;br /&gt;                                 null, &lt;br /&gt;                                 &amp;quot;bitsinout&amp;quot;,&lt;br /&gt;                                 &amp;quot;*************************************8&amp;quot;);&lt;br /&gt;&lt;br /&gt;        BlobStorage blobStorage = BlobStorage.Create(account);&lt;br /&gt;        _container = blobStorage.GetBlobContainer(containerName);&lt;br /&gt;        //Create the container if it does not exist.&lt;br /&gt;        if (!_container.DoesContainerExist())&lt;br /&gt;        {&lt;br /&gt;            _container.CreateContainer(null, ContainerAccessControl.Private);&lt;br /&gt;        }&lt;br /&gt;           &lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void StoreMessage(string name, string message)&lt;br /&gt;    {&lt;br /&gt;        _container.CreateBlob(new BlobProperties(name), new BlobContents(Encoding.UTF8.GetBytes(message)), true);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;Note the URI passed to the StorageAccount does not include the sub domain name of your Azure storage solution.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Let's run this process in the dev fabric, using my .NET Services publisher runtime to populate the Queue. The Development Fabric UI shows the worker role logging the periodic checking of the queue for messages:&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_Sc3uxihjOeo/SsNvh_3CZ2I/AAAAAAAAAEc/jxjrmcbs5IE/s1600-h/devfabric.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 189px;" src="http://3.bp.blogspot.com/_Sc3uxihjOeo/SsNvh_3CZ2I/AAAAAAAAAEc/jxjrmcbs5IE/s400/devfabric.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5387272209133889378" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;As I had created a web role along with the worker role I created a quick aspx page to list the contents of the Blob container (first ASP.NET I've done in a few years!):&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Sc3uxihjOeo/SsNvshr0GLI/AAAAAAAAAEk/NEMTG_WIegw/s1600-h/browserview.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 154px;" src="http://4.bp.blogspot.com/_Sc3uxihjOeo/SsNvshr0GLI/AAAAAAAAAEk/NEMTG_WIegw/s400/browserview.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5387272390012311730" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;The final step is to deploy and run the solution to the Azure cloud. As others have noted this is a simple process. Select 'Publish' on the cloud service project in Visual Studio. This will create a package file ([projectname].cspkg) and a config file (ServiceConfiguration.cscfg). Browse to your service on the Windows Azure portal,  click 'deploy', select the two files above and once uploaded you can run your project:&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_Sc3uxihjOeo/SsNzL8pln5I/AAAAAAAAAE0/lzmznTeCAZY/s1600-h/deployed.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 267px;" src="http://2.bp.blogspot.com/_Sc3uxihjOeo/SsNzL8pln5I/AAAAAAAAAE0/lzmznTeCAZY/s400/deployed.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5387276228361559954" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;I used my runtime to publish a few messages to the queue and checked my web page which is now hosted in Azure. I can see the new messages (with a later timestamp) have been stored, proving my worker process is now running happily in the clouds:&lt;/div&gt;.  &lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_Sc3uxihjOeo/SsN0UWC7fCI/AAAAAAAAAE8/_2w1cunj-_k/s1600-h/browserproduction.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 205px;" src="http://2.bp.blogspot.com/_Sc3uxihjOeo/SsN0UWC7fCI/AAAAAAAAAE8/_2w1cunj-_k/s400/browserproduction.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5387277472129317922" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3586668274215233910-2285521790201988101?l=bitsinout.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bitsinout.blogspot.com/2009/09/using-azure-worker-process-to-read-and.html</link><author>noreply@blogger.com (Paul Arundel)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_Sc3uxihjOeo/SsNvM_VHz-I/AAAAAAAAAEU/8YCXCYIL7bc/s72-c/archivediag.JPG" height="72" width="72" /><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3586668274215233910.post-186230529947635518</guid><pubDate>Sun, 13 Sep 2009 10:41:00 +0000</pubDate><atom:updated>2009-09-14T10:58:48.634+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Queues</category><category domain="http://www.blogger.com/atom/ns#">Azure</category><category domain="http://www.blogger.com/atom/ns#">.NET Services</category><title>.NET Services - Queues</title><description>&lt;div&gt;Along with pub/sub routing functionality, the Azure Service Bus provides an additional messaging primitive: Queues. Where a Router will immediately push messages to subscribers, a Queue will hold messages in persistent storage until retrieved by a consumer (as we would expect!). This disconnects our publisher and consumer and allows the consumers to retrieve messages reliably at their own schedule. Queues can be added as subscribers to a Router much like any other endpoint, allowing us to compose the two messaging primitives within the Service Bus.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Continuing the theme from my previous posts, I now wish to add a Queue as a subscriber to my published message. This handles the scenario where the consumer does not wish to immediately receive messages as they are published. I now have three subscribers:&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Sc3uxihjOeo/SqzMdVC4ZOI/AAAAAAAAAD0/9Dqlq6rh3tc/s1600-h/subscribers.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 174px;" src="http://4.bp.blogspot.com/_Sc3uxihjOeo/SqzMdVC4ZOI/AAAAAAAAAD0/9Dqlq6rh3tc/s400/subscribers.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5380900459038401762" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;For the first two subscribers (a WCF endpoint and a simple http endpoint) the Router will immediately forward on any published messages. For our Queue subscriber, the published message will be stored on a Queue and the subscriber/consumer will retrieve the message at their own schedule.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;So how do we add a Queue subscription to a Router? As before the API makes this relatively simple:&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp:nogutter"&gt;&lt;br /&gt;string qServicePath =  string.Format(&amp;quot;/{0}/{1}/&amp;quot;,subscriber.Publisher.Name,subscriber.Name);&lt;br /&gt;Uri qSbURI = ServiceBusEnvironment.CreateServiceUri(&amp;quot;sb&amp;quot;, subscriber.Publisher.Solution.Name,qServicePath);&lt;br /&gt;QueueClient qClient = ServiceBusHelper.GetOrCreateQueue(qSbURI);&lt;br /&gt;qClient.SubscribeToRouter(_routerClient,TimeSpan.FromHours(1));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;First we create an appropriate path for our Queue, in this case sb://bitsinout.servicebus.windows.net/ProductUpdate/QueueSubscriber. We then create a QueueClient by either creating the queue or retrieving a reference to any existing queue at that URL. Finally we use the Queueclient SubscribeToRouter() method, passing in  a reference to our existing RouterClient instance. The GetOrCreateQueue is static helper method and is very similar to the method for creating a Router:&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp:nogutter"&gt;&lt;br /&gt;public static QueueClient GetOrCreateQueue(Uri queueUri)&lt;br /&gt;{&lt;br /&gt;    TransportClientEndpointBehavior serviceBusCredential = GetCredential();&lt;br /&gt;    QueuePolicy policy;&lt;br /&gt;    QueueClient client;&lt;br /&gt;    try&lt;br /&gt;    {&lt;br /&gt;        client = QueueManagementClient.GetQueue(serviceBusCredential, queueUri);&lt;br /&gt;        policy = client.GetPolicy();&lt;br /&gt;    }&lt;br /&gt;    catch (EndpointNotFoundException)&lt;br /&gt;    {&lt;br /&gt;        policy = new QueuePolicy();&lt;br /&gt;        policy.Discoverability = DiscoverabilityPolicy.Managers;&lt;br /&gt;        policy.Authorization = AuthorizationPolicy.NotRequired;&lt;br /&gt;        policy.TransportProtection = TransportProtectionPolicy.None;&lt;br /&gt;        policy.ExpirationInstant = DateTime.UtcNow + TimeSpan.FromHours(1);&lt;br /&gt;        client = QueueManagementClient.CreateQueue(serviceBusCredential, queueUri, policy);&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     return client;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;Alternatively we can create a subscription to the Queue as we have with the other subscriptions rather than using the QueueClient.SubscribeToRouter() method. To do this we need to supply the address of the Queue with the Https protocol when adding the subscription:&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp:nogutter"&gt;&lt;br /&gt;string qServicePath =  string.Format(&amp;quot;/{0}/{1}/&amp;quot;,subscriber.Publisher.Name,subscriber.Name);&lt;br /&gt;Uri qSbURI = ServiceBusEnvironment.CreateServiceUri(&amp;quot;sb&amp;quot;, subscriber.Publisher.Solution.Name,qServicePath);&lt;br /&gt;Uri qHttpsURI = ServiceBusEnvironment.CreateServiceUri(&amp;quot;https&amp;quot;, subscriber.Publisher.Solution.Name, qServicePath);&lt;br /&gt;QueueClient qClient = ServiceBusHelper.GetOrCreateQueue(qSbURI);&lt;br /&gt;RouterSubscriptionClient subscriptionClient = _routerClient.Subscribe(new EndpointAddress(qHttpsUR), TimeSpan.FromHours(1));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;The code for our consumer client is just as simple:&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp:nogutter"&gt;&lt;br /&gt;Uri queueUri = ServiceBusEnvironment.CreateServiceUri(&amp;quot;sb&amp;quot;, &amp;quot;bitsinout&amp;quot;, &amp;quot;/ProductUpdate/QueuePush/&amp;quot;);&lt;br /&gt;QueueClient client = ServiceBusHelper.GetOrCreateQueue(queueUri);&lt;br /&gt;//throws TimeoutException if no message in queue&lt;br /&gt;Message m = client.Retrieve(new TimeSpan(0, 0, 5));&lt;br /&gt;Console.WriteLine(m.GetBody&amp;lt;string&amp;gt;())&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;We get the Queue reference as before and call the Retrieve() method which makes a destructive read on the queue (the message is deleted from the queue when it is read). The method returns a WCF Message instance from which we can retrieve the message content. As an alternative to the Retrieve() method we can use RetrieveMultiple() to get all the messages from the queue:&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp:nogutter"&gt;&lt;br /&gt;var messages = client.RetrieveMultiple(int.MaxValue,new TimeSpan(0,0,10));&lt;br /&gt;foreach(Message m in messages)&lt;br /&gt;{&lt;br /&gt;    Console.WriteLine(m.GetBody&amp;lt;string&amp;gt;());&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;Using the runtime and Quadrant as detailed in my last &lt;a href="http://bitsinout.blogspot.com/2009/08/mixing-it-up-part-ii-editing-data-with.html"&gt;post&lt;/a&gt; I've set up the router subscriptions as shown in the diagram above. I've added a simple field to the model to allow a subscriber to be defined as a queue. The runtime creates a unique URL from the publisher and subscriber names:&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_Sc3uxihjOeo/SqzMmKTweuI/AAAAAAAAAD8/h5nCcAYA5pA/s1600-h/quadrantsubs.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 96px;" src="http://3.bp.blogspot.com/_Sc3uxihjOeo/SqzMmKTweuI/AAAAAAAAAD8/h5nCcAYA5pA/s400/quadrantsubs.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5380900610775218914" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;Executing my runtime with these configuration values defined and the various services running I get the expected results as shown in the confusing screen grab below. The top console window shows the runtime process, creating the router and adding subscriptions. The next console window shows the WCF service receiving the messages and the following folder shows the messages written to file by the simple .aspx service. Finally the last console window shows the client process that retrieves the messages from the Queue at a slightly later time.&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_Sc3uxihjOeo/SqzMuwkhv4I/AAAAAAAAAEE/zgqFtqIEa_0/s1600-h/messages.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 328px;" src="http://3.bp.blogspot.com/_Sc3uxihjOeo/SqzMuwkhv4I/AAAAAAAAAEE/zgqFtqIEa_0/s400/messages.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5380900758485057410" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;The Retrieve method is potentially risky as any failure in our client after the destructive read could result in the loss of the message. However we can add a level of reliability by using the PeekLock method as an alternative to Retrieve. Clemens Vasters &lt;a href="http://vasters.com/clemensv/PermaLink,guid,8e30d2eb-6e2d-4dc5-8aba-5aa410e450de.aspx"&gt;discusses&lt;/a&gt; this in the context of an Audit Service where the reliable storing of the message is more important than the speed of transfer. PeekLock allows us to retrieve and lock the message in the queue. If we successfully complete our operation, we delete the message from the queue, otherwise we release the message in the queue allowing it to be retrieved again. The following code shows this process:&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp:nogutter"&gt;&lt;br /&gt;Message m = client.PeekLock(new TimeSpan(0,0,20));&lt;br /&gt;string mb =  m.GetBody&amp;lt;string&amp;gt;();&lt;br /&gt;Console.WriteLine(string.Format(&amp;quot;{0} - Message retrieved - {1}&amp;quot;, DateTime.Now,mb));&lt;br /&gt;try&lt;br /&gt;{&lt;br /&gt;    File.WriteAllText(args[0], mb);&lt;br /&gt;    client.DeleteLockedMessage(m);&lt;br /&gt;    Console.WriteLine(string.Format(&amp;quot;{0} - Message deleted&amp;quot;, DateTime.Now));&lt;br /&gt;}&lt;br /&gt;catch (Exception e)&lt;br /&gt;{&lt;br /&gt;    Console.WriteLine(string.Format(&amp;quot;{0} - Error - {1}&amp;quot;, DateTime.Now,e.Message));&lt;br /&gt;    client.ReleaseLock(m);&lt;br /&gt;    Console.WriteLine(string.Format(&amp;quot;{0} - Message released&amp;quot;, DateTime.Now));&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;The following screen grab shows this process executed two times, the first with an invalid file path causing an error and the message to be released. If I hadn't called the ReleaseLock method Azure Service Bus takes care of this situation by automatically releasing locked messages after one minute.&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Sc3uxihjOeo/SqzM1FYJSVI/AAAAAAAAAEM/QVo5kE1TP_o/s1600-h/peeklock.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 170px;" src="http://4.bp.blogspot.com/_Sc3uxihjOeo/SqzM1FYJSVI/AAAAAAAAAEM/QVo5kE1TP_o/s400/peeklock.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5380900867149482322" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3586668274215233910-186230529947635518?l=bitsinout.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bitsinout.blogspot.com/2009/09/net-services-queues.html</link><author>noreply@blogger.com (Paul Arundel)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_Sc3uxihjOeo/SqzMdVC4ZOI/AAAAAAAAAD0/9Dqlq6rh3tc/s72-c/subscribers.JPG" height="72" width="72" /><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3586668274215233910.post-346900516787548507</guid><pubDate>Wed, 26 Aug 2009 10:31:00 +0000</pubDate><atom:updated>2009-09-16T11:05:09.639+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Oslo</category><category domain="http://www.blogger.com/atom/ns#">.NET Services</category><category domain="http://www.blogger.com/atom/ns#">WCF</category><category domain="http://www.blogger.com/atom/ns#">Quadrant</category><title>Mixing it up Part II: Editing data with Quadrant and runtime retrieval of data from the Oslo Repository</title><description>&lt;div&gt;In my &lt;a href="http://bitsinout.blogspot.com/2009/08/mixing-it-up-using-oslo-tools-to-define.html"&gt;last post&lt;/a&gt; I hand coded M values as an instance of my model for configuring .NET Services router subscriptions. As I had not yet uploaded the model or the instance data to the repository that would be the next step. Without using the Oslo command line tools the easiest way to do this is to open your model definition m file in Intellipad and select M Mode -&gt; T-SQL Preview. Presuming your model is error free this opens a new panel with various SQL statements defining your model in terms of SQL CREATE TABLE statements and the relationships between them. If you include instance data for your model, appropriate INSERT statements will also be listed. This text can then simply be pasted into a Management Studio query and executed.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Now we can fire up Quadrant and have a look at our newly defined tables and data:&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Sc3uxihjOeo/SpURDr7awQI/AAAAAAAAAC0/C74NHP60_Bk/s1600-h/quadtables.PNG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 393px; height: 210px;" src="http://4.bp.blogspot.com/_Sc3uxihjOeo/SpURDr7awQI/AAAAAAAAAC0/C74NHP60_Bk/s400/quadtables.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5374220485365776642" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;Let's try dragging the selected 'Subscribers' item to a separate window. This displays a list of the data in the Subscribers table which we can edit:&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_Sc3uxihjOeo/SpUTncqapkI/AAAAAAAAADk/zgFJP6-OUtg/s1600-h/quadsubs.PNG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 122px;" src="http://3.bp.blogspot.com/_Sc3uxihjOeo/SpUTncqapkI/AAAAAAAAADk/zgFJP6-OUtg/s400/quadsubs.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5374223298766480962" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;Select the 'insert item' menu option to add a new subscriber to the table:&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Sc3uxihjOeo/SpUUoihHqcI/AAAAAAAAADs/x3FSthq_x_A/s1600-h/quadaddsubfail.PNG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 183px;" src="http://1.bp.blogspot.com/_Sc3uxihjOeo/SpUUoihHqcI/AAAAAAAAADs/x3FSthq_x_A/s400/quadaddsubfail.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5374224417029597634" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;Oh. Quadrant dynamically uses the model relationships to generate the views/editing actions that we can take. In this case, to add a new Subscription we need to know the related Publisher and Quadrant cannot, of course, determine this from a list of the subscriptions table's contents. To get the appropriate context we will need to drill down from the Publisher to create the subscriptions. To make things even clearer, I dragged the Solutions data from the intial folder window and selected the 'Tree Master/Detail' view option:&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Sc3uxihjOeo/SpURjkwyN3I/AAAAAAAAADM/1u9TzQoMFA0/s1600-h/quadsubdefine.PNG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 151px;" src="http://4.bp.blogspot.com/_Sc3uxihjOeo/SpURjkwyN3I/AAAAAAAAADM/1u9TzQoMFA0/s400/quadsubdefine.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5374221033197942642" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;Now the 'Insert Item' option works happily and I can define a new Subscription. Additionally I can't help but notice that the 'Tree Master/Detail' view when selected at the top level of a solution looks very similar to the DSL I had defined initially with MGrammar.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;My runtime uses the Entity Framework to get the repository data. A quick tidy up of pluralization issues and we have an object model to work with:&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_Sc3uxihjOeo/SpURubiSVrI/AAAAAAAAADU/ax-2CUMYXqE/s1600-h/entframemodel.PNG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 248px;" src="http://3.bp.blogspot.com/_Sc3uxihjOeo/SpURubiSVrI/AAAAAAAAADU/ax-2CUMYXqE/s400/entframemodel.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5374221219699775154" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;With this created we can now define a simple method to retrieve the needed subscriptions when a process wishes to publish a message (this presumes publisher names are unique):&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp:nogutter" &gt;&lt;br /&gt;private Publisher GetPublisher(string publisherId)&lt;br /&gt;{&lt;br /&gt;    using (RepositoryEntities context = new RepositoryEntities())&lt;br /&gt;    {&lt;br /&gt;        try&lt;br /&gt;        {&lt;br /&gt;            return context.Publishers.AsPublisherAggregate().Where(x =&amp;gt; x.Name == publisherId).First();&lt;br /&gt;        }&lt;br /&gt;        catch (InvalidOperationException)&lt;br /&gt;        {&lt;br /&gt;            //handle error&lt;br /&gt;            throw new Exception(string.Format(&amp;quot;Publisher '{0}' not defined.&amp;quot;,publisherId));&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;Now we have the publisher data we can create the router and subscriptions with similar code to used in my previous &lt;a href="http://bitsinout.blogspot.com/2009/07/net-services-routers.html"&gt;post&lt;/a&gt; and the SDK samples. This immediately raises a number of question on how you would manage routers and subscriptions when publishing to the service bus. Create and delete them dynamically each time you publish a message? Create them once with a max expiration and periodically update the subscriptions to match data in the repository? For the moment my runtime determines if a router already exists, and if so, retrieves a list of current subscribers and adds any new subscribers to the router. The following method retrieves a list of current subscriber's URIs for a router&lt;/div&gt;&lt;br /&gt;&lt;PRE name="code" class="c-sharp:nogutter"&gt;&lt;br /&gt;private List&amp;lt;Uri&amp;gt; GetCurrentSubscriptions(Uri routerUri)&lt;br /&gt;{&lt;br /&gt;    List&amp;lt;Uri&amp;gt; currentSubscriptions = new List&amp;lt;Uri&amp;gt;();&lt;br /&gt;            &lt;br /&gt;    HttpWebRequest req = HttpWebRequest.Create(new Uri(routerUri,&amp;quot;!(router/subscriptions)&amp;quot;)) as HttpWebRequest;&lt;br /&gt;    req.Method = &amp;quot;GET&amp;quot;;&lt;br /&gt;    req.Headers.Add(&amp;quot;X-MS-Identity-Token&amp;quot;, HttpGetAuthenticationToken());&lt;br /&gt;&lt;br /&gt;    using (var r = req.GetResponse() as HttpWebResponse)&lt;br /&gt;    {&lt;br /&gt;        using (var rs = r.GetResponseStream())&lt;br /&gt;        {&lt;br /&gt;            Atom10FeedFormatter ff = new Atom10FeedFormatter();&lt;br /&gt;            ff.ReadFrom(new XmlTextReader(rs));&lt;br /&gt;            var links = ff.Feed.Items.SelectMany(x =&amp;gt; x.Links).Where(l =&amp;gt; l.RelationshipType == &amp;quot;alternate&amp;quot;);&lt;br /&gt;            links.ToList().ForEach(l=&amp;gt;currentSubscriptions.Add(l.Uri));&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return currentSubscriptions;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;Finally the code for publishing a message. I use fixed values for the messaging format, obviously this could be configurable within the repository on a per publisher basis:&lt;/div&gt;&lt;br /&gt;&lt;PRE name="code" class="c-sharp:nogutter"&gt;&lt;br /&gt;MessageVersion messageVersion = MessageVersion.Soap12WSAddressing10;&lt;br /&gt;Binding binding = new WSHttpBinding(SecurityMode.None);&lt;br /&gt;EndpointAddress epAddress = new EndpointAddress(_routerUriHttp);&lt;br /&gt;Message m = Message.CreateMessage(messageVersion, &amp;quot;&amp;quot;, message);&lt;br /&gt;&lt;br /&gt;ChannelFactory&amp;lt;IOutputChannel&amp;gt; factory =  new ChannelFactory&amp;lt;IOutputChannel&amp;gt;(binding, epAddress)&lt;br /&gt;factory.Endpoint.Behaviors.Add(GetCredential());&lt;br /&gt;IOutputChannel channel = factory.CreateChannel();&lt;br /&gt;channel.Open();&lt;br /&gt;channel.Send(m);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;With this defined lets try publishing a simple string of XML using the runtime. I have two subscribers defined in the Repository and matching services listening on my machine (a WCF host, and an .aspx page that saves any posted data to a file):&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Sc3uxihjOeo/SpUSHdJQ_qI/AAAAAAAAADc/3c7nLSU_Rhc/s1600-h/quadrantmessagereceived.PNG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 247px;" src="http://1.bp.blogspot.com/_Sc3uxihjOeo/SpUSHdJQ_qI/AAAAAAAAADc/3c7nLSU_Rhc/s400/quadrantmessagereceived.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5374221649628429986" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt; My next step is to look at handling a message transform for a particular subscriber and therefore how we can chain routers and subscriptions to provide more of a process flow. I never looked at the workflow capability that was originally part of .NET Services but that may well have been a candidate. As the workflow capability was removed an Azure WCF service that calls back into the service bus may provide a solution.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3586668274215233910-346900516787548507?l=bitsinout.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bitsinout.blogspot.com/2009/08/mixing-it-up-part-ii-editing-data-with.html</link><author>noreply@blogger.com (Paul Arundel)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_Sc3uxihjOeo/SpURDr7awQI/AAAAAAAAAC0/C74NHP60_Bk/s72-c/quadtables.PNG" height="72" width="72" /><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3586668274215233910.post-8608503276390712839</guid><pubDate>Mon, 10 Aug 2009 18:46:00 +0000</pubDate><atom:updated>2009-08-12T10:02:29.382+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Oslo</category><category domain="http://www.blogger.com/atom/ns#">.NET Services</category><title>Mixing it up: Using the Oslo tools to define .NET Services Router Subscriptions</title><description>&lt;div&gt;My projects/blogging have recently focused on the Azure .NET Services platform and the various Oslo tools. So naturally I've arrived at the conclusion that I should attempt to combine these two strands of technology in my next project. When working with the .NET Services Service Bus I thought it may be helpful to define router subscriptions with a DSL using the Oslo tools. A process that needs to publish a message could then hand this responsibility to a runtime/service which would create the correct subscriptions for that publisher from the DSL defined data and send the message.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;As my BizUnit DSL runtime parsed the object graph generated from my DSL, this time I wanted my runtime to retrieve the subscriptions data directly from the repository, the other major part of Oslo (much like Mikael Håkanssons with his &lt;a href="http://blogical.se/blogs/mikael/archive/2009/07/07/how-to-use-the-oslo-repository-to-store-your-service-configuration.aspx"&gt;WCF service configuration&lt;/a&gt;). To do this, as well as defining a DSL, I needed to create a model for my subscriptions with the M modelling language, use the Oslo tools to convert my DSL input file into an M instance of this model and import this into the repository. I could then toy with Quadrant as a way of editing my subscriptions. Should be easy......&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Fairly quickly I had my grammar defined and a simple DSL input file, which is not much more than a list of subscribers:&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Sc3uxihjOeo/SoBr_wrWXfI/AAAAAAAAACM/w3GfHsLIJhg/s1600-h/routerdsl.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 234px;" src="http://4.bp.blogspot.com/_Sc3uxihjOeo/SoBr_wrWXfI/AAAAAAAAACM/w3GfHsLIJhg/s400/routerdsl.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5368409498968284658" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;The DSL simply defines the Service Bus solution name, publishers and the URIs of subscribers. Notice I have a Transform in there also. I intend my runtime to dynamically create subscriptions so that additional steps (such as a message transforming external service) can be performed. The Transform just serves as an example of this.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Next I defined my model using the MSchema modelling language, again super simple to start with:&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_Sc3uxihjOeo/SoBsNoNyPNI/AAAAAAAAACU/cIsfljOPbg0/s1600-h/routermodelrel.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 291px; height: 400px;" src="http://3.bp.blogspot.com/_Sc3uxihjOeo/SoBsNoNyPNI/AAAAAAAAACU/cIsfljOPbg0/s400/routermodelrel.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5368409737214966994" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;Now my next step was to use the Oslo tools to parse my DSL input file and create M values of the input suitable for my model (following Dana Kaufmans &lt;a href="http://blogs.msdn.com/dkaufman/archive/2009/06/05/from-dsls-and-models-to-quadrant-using-oslo-may-ctp-part-ii.aspx"&gt;posts&lt;/a&gt;). After a few errors using the command line tools I decided to hand code some working M values which would give me a better view of how my DSL grammar should project the input file. My hand coded M values could be defined a number of ways, including separate values for each of the collections (e.g. Transforms, Subscribers) related with label names. However the image below shows the values as one statement:&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_Sc3uxihjOeo/SoBsgSvSY3I/AAAAAAAAACc/n_9Lv0cRnA0/s1600-h/routermvalues.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 174px;" src="http://2.bp.blogspot.com/_Sc3uxihjOeo/SoBsgSvSY3I/AAAAAAAAACc/n_9Lv0cRnA0/s400/routermvalues.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5368410057867420530" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;Obviously something was not right, how could I amend the projection of my DSL to look something like the above? Searching the forums I came across a number of posts from a few months ago by Rockford Lhotka discussing this issue (&lt;a href="http://www.lhotka.net/weblog/MCslaNdashCompilingDSLSourceIntoM.aspx"&gt;here&lt;/a&gt; and &lt;a href="http://social.msdn.microsoft.com/Forums/en-US/oslo/thread/4d6d6138-747c-4d57-a55f-9188524a0e9f"&gt;here&lt;/a&gt; and a short &lt;a href="http://www.davidlangworthy.com/2009/04/hierarchical-data-in-m.html"&gt;response&lt;/a&gt; from someone on the Oslo team). My model is defined using relationships between the entities, for example each Subscriber is related to one Publisher. In the generated SQL this becomes a foreign key from the Subscriber (child) to the Publisher table (parent). If we look at my DSL, the structure that is generated by mgx (and the Intelipad preview) is different. The relationship is defined from the parent to the children and is an hierarchical form like an XML document (e.g the relationship is defined from the Publisher (parent) to the subscribers (children)). No amount of amending the projection of my DSL was going to help.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;As Rockford suggests in one of the posts above, one solution is to amend my Mschema model and use a hierarchical MSchema. In this way I would define the relationships from parent to child and hopefully then I could transform my input file into appropriate M values:&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Sc3uxihjOeo/SoBu34ZzR-I/AAAAAAAAACs/iLlUo2XS_wQ/s1600-h/routermodelhier.PNG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 355px; height: 231px;" src="http://1.bp.blogspot.com/_Sc3uxihjOeo/SoBu34ZzR-I/AAAAAAAAACs/iLlUo2XS_wQ/s400/routermodelhier.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5368412662138095586" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;Unfortunately the SQL created from this model does not create the SQL as cleanly as the relational model and includes a join table. The Oslo SDK also notes "&lt;a href="http://msdn.microsoft.com/en-us/library/dd326773(VS.85).aspx"&gt;Do Not Use Collections to Model One-to-Many Relationships&lt;/a&gt;".&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Discarding using hierarchical MSchema I have a number of choices to continue my project. I could write a new runtime to replace mgx for my dsl, traverse the object graph of a parsed DSL input file and create the appropriate M values. This seems a little pointless as I may as well just work directly from the object graph to create my router subscriptions. Alternatively I could stick with my original model and add my required configuration values with Quadrant. My subscriptions runtime could then run from the repository as I had intended. The latter is the sensible approach as this will let me move on to the fun part of my project and hopefully the DSL -&gt; M -&gt; Repository picture will become clearer in the future. However I feel slightly disappointed that I cannot demonstrate directly going from my DSL to the runtime via the repository, as the DSL provides such a simple and clear picture of the process defined.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;This also raises the question of why you would use both a DSL and Quadrant. If you can execute your process from an instance of your DSL why use the repository? And if M/Repository/Quadrant provide a complete way to model and edit your data why use a DSL? As I'm learning a lot from Rockford Lhotka's various posts on this he &lt;a href="http://social.msdn.microsoft.com/Forums/en-US/oslo/thread/4b7b93ce-308d-4863-919e-455fce1f0278"&gt;raised this issue months ago&lt;/a&gt; starting an interesting discussion.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3586668274215233910-8608503276390712839?l=bitsinout.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bitsinout.blogspot.com/2009/08/mixing-it-up-using-oslo-tools-to-define.html</link><author>noreply@blogger.com (Paul Arundel)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_Sc3uxihjOeo/SoBr_wrWXfI/AAAAAAAAACM/w3GfHsLIJhg/s72-c/routerdsl.png" height="72" width="72" /><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3586668274215233910.post-5192152036269636158</guid><pubDate>Tue, 28 Jul 2009 12:07:00 +0000</pubDate><atom:updated>2009-07-28T22:32:11.054+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Azure</category><category domain="http://www.blogger.com/atom/ns#">.NET Services</category><category domain="http://www.blogger.com/atom/ns#">WCF</category><title>.NET Services - Routers - Pushing Messages to Internet Facing Services</title><description>&lt;div&gt;Continuing my look at .NET Services routers, I wanted the Service Bus to push a message to a public HTTP endpoint. Something that is not currently, as far I can see, in the SDK samples.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;To avoid any reliance on the various web service technologies and to some extent to test platform independance I created a very simple endpoint using an .aspx page. This .aspx page simply writes out the message body to a file from a http POST. For what it's worth here's the code in Page_Load:&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp:nogutter"&gt;&lt;br /&gt;StreamReader sr = new StreamReader(Page.Request.InputStream);&lt;br /&gt;File.AppendAllText(@&amp;quot;c:\dev\out\postdata.txt&amp;quot;, sr.ReadToEnd());&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;I also re-configured my hardware router to forward port 80 requests to my server to ensure the service bus could talk to the service.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;I then made a change to my publisher code to add a subscription for this endpoint, as unlike my ealier relay example, this endpoint will not make it's own. The following code was added after the code to create/get the RouterClient:&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp:nogutter"&gt;&lt;br /&gt;client.Subscribe(&lt;br /&gt;    new EndpointAddress(@&amp;quot;http://myipaddress/testep/default.aspx&amp;quot;),&lt;br /&gt;    TimeSpan.MaxValue);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;Unfortunately this failed with an unhelpful 'internal error'. Experimenting I noticed that if I used a https in the subscription, the method call worked and my firewall log indicated an attempted connection on port 443 from the Service Bus, so the router and subscription were working. Failing to spot the obvious my progress was halted until I read this very helpful &lt;a href="http://social.msdn.microsoft.com/Forums/en-US/netservices/thread/c2538c34-af0a-43a7-9e51-82e912681248"&gt;thread&lt;/a&gt;. By default the RouterPolicy.TransportProtection is set to TransportProtectionPolicy.AllPaths, indicating that the Router should use a secure connection when sending messages to subscribers. I therefore changed the policy to the only alternative:&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp:nogutter"&gt;&lt;br /&gt;policy.TransportProtection = TransportProtectionPolicy.None;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;Executing the publisher process again and the service bus successfully called my simple service, writing the request to a file:&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="xml:nogutter"&gt;&lt;br /&gt;&amp;lt;s:Envelope xmlns:s=&amp;quot;http://www.w3.org/2003/05/soap-envelope&amp;quot; xmlns:a=&amp;quot;http://www.w3.org/2005/08/addressing&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;s:Header&amp;gt;&lt;br /&gt;        &amp;lt;a:Action s:mustUnderstand=&amp;quot;1&amp;quot;&amp;gt;http://bitsinout.servicebus.windows.net/IProductServices/ProductUpdate&amp;lt;/a:Action&amp;gt;&lt;br /&gt;        &amp;lt;a:To s:mustUnderstand=&amp;quot;1&amp;quot;&amp;gt;sb://bitsinout.servicebus.windows.net/productrouter/&amp;lt;/a:To&amp;gt;&lt;br /&gt;    &amp;lt;/s:Header&amp;gt;&lt;br /&gt;    &amp;lt;s:Body&amp;gt;&lt;br /&gt;        &amp;lt;ProductUpdate xmlns=&amp;quot;http://bitsinout.servicebus.windows.net&amp;quot;&amp;gt;&lt;br /&gt;            &amp;lt;product xmlns:i=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&amp;gt;&lt;br /&gt;                &amp;lt;Code&amp;gt;12345&amp;lt;/Code&amp;gt;&lt;br /&gt;                &amp;lt;Name&amp;gt;Oxtail Soup&amp;lt;/Name&amp;gt;&lt;br /&gt;                &amp;lt;Price&amp;gt;79&amp;lt;/Price&amp;gt;&lt;br /&gt;            &amp;lt;/product&amp;gt;&lt;br /&gt;        &amp;lt;/ProductUpdate&amp;gt;&lt;br /&gt;    &amp;lt;/s:Body&amp;gt;&lt;br /&gt;&amp;lt;/s:Envelope&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;So we have the SOAP message sent to the service, a good test that the router and subscription mechanism is working. The next step was to add a second subscription this time to a normal WCF service.&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp:nogutter"&gt;&lt;br /&gt;client.Subscribe(&lt;br /&gt;    new EndpointAddress(@&amp;quot;http://myipaddress/ProductService&amp;quot;),&lt;br /&gt;    TimeSpan.MaxValue);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;As our RouterClient appears to give us a SOAP 1.2 message I used a wsHttpBinding for the service:&lt;/div&gt; &lt;br /&gt;&lt;pre name="code" class="xml:nogutter"&gt;&lt;br /&gt;&amp;lt;service name=&amp;quot;Arundel.NetServicesTest.ExternalWCFService.ProductService&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;endpoint address=&amp;quot;sb://bitsinout.servicebus.windows.net/productrouter/&amp;quot;&lt;br /&gt;              listenUri=&amp;quot;http://localhost/ProductService&amp;quot;&lt;br /&gt;              binding=&amp;quot;wsHttpBinding&amp;quot;&lt;br /&gt;              bindingConfiguration=&amp;quot;customWSBindingConfig&amp;quot;&lt;br /&gt;              contract=&amp;quot;Arundel.NetServicesTest.Services.IProductServices&amp;quot; /&amp;gt;&lt;br /&gt;&amp;lt;/service&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;bindings&amp;gt;&lt;br /&gt;    &amp;lt;wsHttpBinding&amp;gt;&lt;br /&gt;        &amp;lt;binding name=&amp;quot;customWSBindingConfig&amp;quot;&amp;gt;&lt;br /&gt;            &amp;lt;security mode=&amp;quot;None&amp;quot;&amp;gt;&lt;br /&gt;                &amp;lt;transport clientCredentialType=&amp;quot;None&amp;quot; /&amp;gt;&lt;br /&gt;            &amp;lt;/security&amp;gt;&lt;br /&gt;        &amp;lt;/binding&amp;gt;&lt;br /&gt;    &amp;lt;/wsHttpBinding&amp;gt;&lt;br /&gt;&amp;lt;/bindings&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;After initial failures, I created a custom binding configuration to remove security and authentication from the process, something to look at later. Once these complications were removed I could see from the WCF traces that I was getting an AddressFilterMismatch error, that the Action:To was the address of the Service Bus router rather than the intended service address. As the process involves an additional hop we need to update the service configuration, setting the logical address to the router address (the endpoint address above) and listentUri to our actual physical address. Once this was in place the message was received (shown with the output from our first subscriber):&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_Sc3uxihjOeo/Sm7rZh4oQzI/AAAAAAAAACE/J9sV3rb5kvQ/s1600-h/routertowcfservice.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 131px;" src="http://3.bp.blogspot.com/_Sc3uxihjOeo/Sm7rZh4oQzI/AAAAAAAAACE/J9sV3rb5kvQ/s400/routertowcfservice.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5363483030069986098" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;To wrap things up I wanted to try sending a non-SOAP message via the router. I updated my router code to just create the router, commenting out the subscription to my WCF endpoint and the push of data to the router. Then using a seperate console application I used a HttpWebRequest to send a simple csv string:&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp:nogutter"&gt;&lt;br /&gt;string token = HttpGetAuthenticationToken(&amp;quot;bitsinout&amp;quot;, &amp;quot;********&amp;quot;);&lt;br /&gt;WebRequest req = HttpWebRequest.Create(&amp;quot;http://bitsinout.servicebus.windows.net/productrouter/&amp;quot;);            &lt;br /&gt;req.Method = &amp;quot;POST&amp;quot;;&lt;br /&gt;req.Headers.Add(&amp;quot;X-MS-Identity-Token&amp;quot;, token);&lt;br /&gt;req.ContentType = &amp;quot;text/csv&amp;quot;;&lt;br /&gt;StreamWriter sw = new StreamWriter(req.GetRequestStream());&lt;br /&gt;sw.Write(&amp;quot;12346,ProductB,350&amp;quot;);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;The string of data was successfully pushed through to my service. The HttpGetAuthenticationToken method is from the SDK samples and allows us to retrieve a temporary security token enabling requests to be authenticated on the Service Bus. &lt;/div&gt;&lt;br /&gt;&lt;div&gt;One thing to note, as the router only fowards messages, we need a separate router per data format required by each push subscriber and therefore the creation of these different formats would be down to the publisher. If a business has made the move to put pub/sub into the cloud, presumably they would also want message transformations there also.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3586668274215233910-5192152036269636158?l=bitsinout.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bitsinout.blogspot.com/2009/07/net-services-routers-pushing-to.html</link><author>noreply@blogger.com (Paul Arundel)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_Sc3uxihjOeo/Sm7rZh4oQzI/AAAAAAAAACE/J9sV3rb5kvQ/s72-c/routertowcfservice.jpg" height="72" width="72" /><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3586668274215233910.post-3766865414330743957</guid><pubDate>Wed, 22 Jul 2009 20:26:00 +0000</pubDate><atom:updated>2009-07-27T15:42:34.628+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Azure</category><category domain="http://www.blogger.com/atom/ns#">.NET Services</category><category domain="http://www.blogger.com/atom/ns#">WCF</category><title>.NET Services - Routers</title><description>&lt;div&gt;In my previous &lt;a href="http://bitsinout.blogspot.com/2009/07/net-services-integration-scenarios.html"&gt;post&lt;/a&gt; I worked through a sample where a business could use the .NET services relay to expose an external service without making any infrastructure changes. For this post I will look at the how we can use the Service Bus Router to push data to external services.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;My scenario is a simple push of product data updates to partners/customers who wish to subscribe to this information. With BizTalk I could create a simple solution where a product update message would be inserted into the BizTalk Message Box and send ports for each subscriber would be tailored to that subscribers message format and transport mechanism needs. Using .NET Services we will fire our product update into the cloud and allow the Service Bus to distribute the message to push subscribers. This offers a distinct advantage other than just moving the pub/sub infrastructure into the cloud. Partners who wish to receive this information can themselves use the .NET Services relay bindings to subscribe directly to messages sent to the router without having to expose a public service to the internet.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;I'm going to look at a number of external partners as examples, each with different requirements in how they want the data pushed to them. In this post I will look at getting a message through to a partner who wants to connect directly to the router from an internal system using the relay bindings. I'll next look at how the router can push messages to a push subscriber web service endpoints that are not using relay bindings (i.e. just normal public web services that do not know messages are coming from the Service Bus). Finally I want to look at a push subscriber that cannot have a constant connection to the Service Bus and will instead use the Service Bus Queue functionality. My example for this last case would be a company that only wants to recieve product updates once a day as part of a batch process. &lt;/div&gt;&lt;br /&gt;&lt;div&gt;First the code for our message publisher. (Most of the code is based on/copied from the &lt;a href="http://msdn.microsoft.com/en-us/library/dd582755.aspx"&gt;SoapRouter&lt;/a&gt; and HttpRouter samples):&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp:nogutter"&gt;&lt;br /&gt;Uri routerUri = ServiceBusEnvironment.CreateServiceUri(&amp;quot;sb&amp;quot;, &amp;quot;bitsinout&amp;quot;, &amp;quot;productupdates&amp;quot;);&lt;br /&gt;TransportClientEndpointBehavior serviceBusCredential = GetCredential();&lt;br /&gt;RouterClient client;&lt;br /&gt;try&lt;br /&gt;{&lt;br /&gt;    client = RouterManagementClient.GetRouter(serviceBusCredential, routerUri);&lt;br /&gt;    policy = client.GetPolicy();&lt;br /&gt;}&lt;br /&gt;catch (EndpointNotFoundException)&lt;br /&gt;{&lt;br /&gt;    policy = new RouterPolicy();&lt;br /&gt;    policy.MessageDistribution = MessageDistributionPolicy.AllSubscribers;&lt;br /&gt;    policy.Discoverability = DiscoverabilityPolicy.Public;&lt;br /&gt;    policy.MaxSubscribers = 10;&lt;br /&gt;    policy.Authorization = AuthorizationPolicy.NotRequired;&lt;br /&gt;    client = RouterManagementClient.CreateRouter(serviceBusCredential, routerUri, policy);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;ChannelFactory&amp;lt;IProductServicesChannel&amp;gt; factory = client.CreateRouterClient&amp;lt;IProductServicesChannel&amp;gt;(EndToEndSecurityMode.None, RelayClientAuthenticationType.RelayAccessToken);&lt;br /&gt;factory.Endpoint.Behaviors.Add(serviceBusCredential);&lt;br /&gt;IProductServicesChannel channel = factory.CreateChannel();&lt;br /&gt;channel.Open();&lt;br /&gt;channel.ProductUpdate(new Product() { Code = &amp;quot;12345&amp;quot;, Name = &amp;quot;Meat Pie with Gravy&amp;quot;, Price = 129 });&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;First we create our router uri, get the credentials allowing us to connect to the service bus and see if the router exists (RouterManagementClient.GetRouter()). If not(EndpointNotFoundException) we create the router using RouterManagementClient.CreateRouter() with an appropriate configuration (RouterPolicy). Once the router is established, we get a client of the router much like we would any other WCF service and call methods on this proxy (in our case channel.ProductUpdate()) to send messages to the router.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;I've chosen the push subscriber relay scenario first as this is very easy to implement. On our subscriber client side we need the following code (this is&lt;br /&gt;from the SoapRouter NetOnewaySubscriber project in the samples):&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp:nogutter"&gt;&lt;br /&gt;Uri routerUri = ServiceBusEnvironment.CreateServiceUri(&amp;quot;sb&amp;quot;, &amp;quot;bitsinout&amp;quot;, &amp;quot;/productrouter/&amp;quot;);&lt;br /&gt;RouterClient client = RouterManagementClient.GetRouter(GetCredential(), routerUri);&lt;br /&gt;ServiceHost host = new ServiceHost(typeof(ProductService));&lt;br /&gt;ServiceEndpoint endpoint = client.AddRouterServiceEndpoint&amp;lt;IProductServices&amp;gt;(host);&lt;br /&gt;host.Open();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;That's it. The AddRouterServiceEndpoint does all the magic, creating a subscription to the router that lasts as long as the client is connected. This worked first time and messages were received by the client.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;However, I was curious to see what happens when I run the publisher process a number of times. That is, what happens when I send a message to the router, close the channel, restart the process, get the router again and send another message, all while the push subscriber endpoint remains connected. This works fine, as you would expect, as the router would not have expired and still exist on the service bus. However, if I call client.DeleteRouter() after sending the first message (simulating an expired router) the subscriber endpoint remains connected, does not error and does not recieve the second message. Going further if I connect/subscribe the destination endpoint to the router before the router is created, it does not error but the publisher process that calls RouterManagementClient.CreateRouter() fails with an unhelpful error. Maybe I'm missing something (and .NET Services is not a finished product) but I suspect subscriber endpoints that connect using the relay bindings will have to be managed very carefully. I see little (or haven't found) much detail on error reporting. How do we know if a particular subscriber did not receive a message?&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Pleased with my progress I've made an attempt to look at my next example, pushing data to external public web services. The SDK samples all use relay bindings for subscriber endpoints, presumably to avoid people trying the samples to worry about exposing a public web service (and tinkering with hardware router rules). Unfortunately in trying to get the Service Bus to push a message to public web service subscriber I've been halted by an error (maybe on my part) which I cannot work around and have sent &lt;a href="https://connect.microsoft.com/netservices/feedback/ViewFeedback.aspx?FeedbackID=476252"&gt;feedback&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3586668274215233910-3766865414330743957?l=bitsinout.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bitsinout.blogspot.com/2009/07/net-services-routers.html</link><author>noreply@blogger.com (Paul Arundel)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3586668274215233910.post-4970989194756247562</guid><pubDate>Tue, 07 Jul 2009 12:06:00 +0000</pubDate><atom:updated>2009-07-27T15:44:35.469+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Azure</category><category domain="http://www.blogger.com/atom/ns#">.NET Services</category><category domain="http://www.blogger.com/atom/ns#">WCF</category><title>.NET Services - Integration Scenarios</title><description>&lt;div&gt;I experimented with the original BizTalk Services last year and created a toy application using the Multicast relay bindings. Now the renamed .NET Services appears to offer more features, particularly Routers and Queues, I would like to investigate further. I want to work through a few common business to business integration scenarios, where we might have used BizTalk or Web Services, and see how .NET Services can help. I don't expect any of this to be new, or even go further than the various SDK samples, but it's always worth working through a scenario to help understanding.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Let's start with a very simple example using the Service Bus as a relay: A company wishes to expose a product data service to the internet so customers can get the latest product pricing information. Normally this may involve infrastructure changes, new hardware and the time of the company network admins (e.g. an internet facing server in the DMZ or allowing specific inbound calls through the firewall). The firewall traversal functionality offered by the .NET Services Service Bus relay can give us this public endpoint without the infrastructure changes. I'm sure the company network admins would still like to have a say in this but lets plough on!&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Before getting to the code it's worth noting Clemens Vasters other &lt;a href="http://vasters.com/clemensv/PermaLink,guid,92d78bee-2cfd-4a29-95ab-c5abb9b905e7.aspx"&gt;reasons&lt;/a&gt; for putting public services on the Service Bus relay: &lt;/div&gt;&lt;br /&gt;&lt;i&gt;&lt;div&gt;In addition to providing NAT and Firewall traversal and discoverability the delegation of the public network endpoint into the Relay provides a service with a number of additional key advantages that are beneficial even if NAT traversal or discoverability are not a problem you need to solve:&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;The Relay functions as a "demilitarized zone" that is isolated from the service's environment and takes on all external network traffic, filtering out unwanted traffic.&lt;/li&gt;&lt;li&gt;The Relay anonymizes the listener and therefore effectively hides all details about the network location of the listener thus reducing the potential attack surface of the listening service to a minimum.&lt;/li&gt;&lt;li&gt;The Relay is integrated with the Access Control Service and can require clients to authenticate and be authorized at the Relay before they can connect through to the listening service. This authorization gate is enabled by default for all connections and can be selectively turned off if the application wants to perform its own authentication and authorization.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/i&gt;&lt;br /&gt;&lt;div&gt;First off I've created a simple WCF service and WCF client, this could represent an already existing internal service at the company:&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp:nogutter"&gt;&lt;br /&gt;//Contract&lt;br /&gt;[ServiceContract]&lt;br /&gt;interface IProductService&lt;br /&gt;{&lt;br /&gt;    [OperationContract]&lt;br /&gt;    Product GetProduct(string code);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;//Service&lt;br /&gt;ServiceHost host = new ServiceHost(typeof(ProductService));&lt;br /&gt;host.Open();&lt;br /&gt;&lt;br /&gt;//Client&lt;br /&gt;ChannelFactory&amp;lt;IProductChannel&amp;gt; factory = new ChannelFactory&amp;lt;IProductChannel&amp;gt;("ProductService");&lt;br /&gt;IProductChannel channel = factory.CreateChannel();&lt;br /&gt;channel.Open();&lt;br /&gt;Product prod = channel.GetProduct("ABC");&lt;br /&gt;channel.Close();&lt;br /&gt;factory.Close();&lt;br /&gt;Console.WriteLine(prod.Name + " " + prod.Price);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;And a couple of very simple configuration files to get things working using the standard basicHttp binding:&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="xml:nogutter"&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;service name=&amp;quot;Arundel.NetServicesTest.Services.ProductService&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;endpoint address=&amp;quot;http://localhost/ProductService&amp;quot;&lt;br /&gt;              binding=&amp;quot;basicHttpBinding&amp;quot;&lt;br /&gt;              contract=&amp;quot;Arundel.NetServicesTest.Services.IProductService&amp;quot; /&amp;gt;&lt;br /&gt;&amp;lt;/service&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;client&amp;gt;&lt;br /&gt;    &amp;lt;endpoint name=&amp;quot;ProductService&amp;quot;&lt;br /&gt;              address=&amp;quot;http://localhost/ProductService&amp;quot; &lt;br /&gt;              binding=&amp;quot;basicHttpBinding&amp;quot;&lt;br /&gt;              contract=&amp;quot;Arundel.NetServicesTest.Services.IProductService&amp;quot; /&amp;gt;&lt;br /&gt;&amp;lt;/client&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;Now to make the changes to create a public endpoint. First I created a solution on my account at the .NET services &lt;a href="https://portal.ex.azure.microsoft.com/View.aspx"&gt;Portal&lt;/a&gt;. All I needed here was a unique name for the relay address: sb://[solution name].servicebus.windows.net. Next I added an endpoint for the relay to my service:&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="xml:nogutter"&gt;&lt;br /&gt;&amp;lt;endpoint address=&amp;quot;http://bitsinout.servicebus.windows.net/productservice&amp;quot;&lt;br /&gt;    binding=&amp;quot;basicHttpRelayBinding&amp;quot;&lt;br /&gt;    contract=&amp;quot;Arundel.NetServicesTest.Services.IProductService&amp;quot;&lt;br /&gt;    behaviorConfiguration=&amp;quot;RelayBehavior&amp;quot;/&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;Three things have changed with this new endpoint. The address is now the public facing uri of the service, hosted on the Service Bus. The binding has been changed to the relay version of the basicHttp binding. Finally a new behavior was needed allowing the service to establish a connection with my service bus solution:&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="xml:nogutter"&gt;&lt;br /&gt;&amp;lt;behavior name=&amp;quot;RelayBehavior&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;transportClientEndpointBehavior credentialType=&amp;quot;UserNamePassword&amp;quot;&amp;gt;&lt;br /&gt;        &amp;lt;clientCredentials&amp;gt;&lt;br /&gt;            &amp;lt;userNamePassword userName=&amp;quot;bitsinout&amp;quot; password=&amp;quot;*********&amp;quot;/&amp;gt;&lt;br /&gt;        &amp;lt;/clientCredentials&amp;gt;&lt;br /&gt;    &amp;lt;/transportClientEndpointBehavior&amp;gt;&lt;br /&gt;&amp;lt;/behavior&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;Ok first test was to update the client configuration to point at the service bus:&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="xml:nogutter"&gt;&lt;br /&gt;&amp;lt;client&amp;gt;&lt;br /&gt;    &amp;lt;endpoint name=&amp;quot;ProductService&amp;quot;&lt;br /&gt;            address=&amp;quot;http://bitsinout.servicebus.windows.net/productservice&amp;quot;&lt;br /&gt;              binding=&amp;quot;basicHttpRelayBinding&amp;quot;&lt;br /&gt;              contract=&amp;quot;Arundel.NetServicesTest.Services.IProductService&amp;quot;&lt;br /&gt;              behaviorConfiguration=&amp;quot;RelayBehavior&amp;quot;/&amp;gt;&lt;br /&gt;&amp;lt;/client&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;Apart from the update of the address and binding you may notice that a behavior for authentication has been added as with the service. This was necessary otherwise a Cardspace window pops up when running the client as the relay bindings require authentication with the Service Bus solution. This was a good test of the relay but obviously consumers of the service will not be required to use a relay WCF binding and I would want my original basicHttp client configuration to stay the same apart from an updated address. I could only get this working by allowing anonymous access to the public endpoint (without delving too deeply into the security configuration options). Anonymous access can be enabled by adding the following to the service configuration:&lt;/div&gt; &lt;br /&gt;&lt;pre name="code" class="xml:nogutter"&gt;&lt;br /&gt;&amp;lt;bindings&amp;gt;&lt;br /&gt;    &amp;lt;basicHttpRelayBinding&amp;gt;&lt;br /&gt;        &amp;lt;binding name=&amp;quot;default&amp;quot;&amp;gt;&lt;br /&gt;            &amp;lt;security mode=&amp;quot;None&amp;quot; relayClientAuthenticationType=&amp;quot;None&amp;quot;/&amp;gt;&lt;br /&gt;        &amp;lt;/binding&amp;gt;&lt;br /&gt;    &amp;lt;/basicHttpRelayBinding&amp;gt;&lt;br /&gt;&amp;lt;/bindings&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;Finally I wanted to test the service from a non WCF client. I therefore added an additional endpoint using the webHttpRelayBinding, first making a few changes to the service code switching from a ServiceHost to a WebServiceHost and added an appropriate WebGet attribute to the operation:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp:nogutter"&gt;&lt;br /&gt;WebServiceHost host = new WebServiceHost(typeof(ProductService));&lt;br /&gt;&lt;br /&gt;[OperationContract]&lt;br /&gt;[WebGet(UriTemplate = "product/{code}")]&lt;br /&gt;Product GetProduct(string code);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;And the additional endpoint:&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="xml:nogutter"&gt;&lt;br /&gt;&amp;lt;endpoint address=&amp;quot;http://bitsinout.servicebus.windows.net/products&amp;quot;&lt;br /&gt;          binding=&amp;quot;webHttpRelayBinding&amp;quot;&lt;br /&gt;          contract=&amp;quot;Arundel.NetServicesTest.Services.IProductService&amp;quot;&lt;br /&gt;          bindingConfiguration=&amp;quot;default&amp;quot;&lt;br /&gt;          behaviorConfiguration=&amp;quot;RelayBehavior&amp;quot;/&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;webHttpRelayBinding&amp;gt;&lt;br /&gt;    &amp;lt;binding name=&amp;quot;default&amp;quot;&amp;gt;&lt;br /&gt;        &amp;lt;security mode=&amp;quot;None&amp;quot; relayClientAuthenticationType=&amp;quot;None&amp;quot;/&amp;gt;&lt;br /&gt;    &amp;lt;/binding&amp;gt;&lt;br /&gt;&amp;lt;/webHttpRelayBinding&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;Finally a simple http GET with a browser:&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_Sc3uxihjOeo/SluTiiEKTqI/AAAAAAAAAB8/nMyIej_BXLM/s1600-h/prodquerybrowser.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 226px;" src="http://2.bp.blogspot.com/_Sc3uxihjOeo/SluTiiEKTqI/AAAAAAAAAB8/nMyIej_BXLM/s400/prodquerybrowser.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5358038403156430498" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;It's astonishing how easily WCF configuration and .NET services allow this to be implemented. However the ease of implementation would only be a small consideration, amongst many others, when a business decides to expose a public service in this way. My thoughts would be that .NET services could be very useful to medium sized organizations when establishing business to business integration processes with their partners/customers. It worth remembering that many business are still integrating by emailing excel spreadsheets to each other or FTPing large daily flat files. Any platform that could help the move away from those types of processes is a good thing.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3586668274215233910-4970989194756247562?l=bitsinout.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bitsinout.blogspot.com/2009/07/net-services-integration-scenarios.html</link><author>noreply@blogger.com (Paul Arundel)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_Sc3uxihjOeo/SluTiiEKTqI/AAAAAAAAAB8/nMyIej_BXLM/s72-c/prodquerybrowser.jpg" height="72" width="72" /><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3586668274215233910.post-6288468639584975458</guid><pubDate>Thu, 18 Jun 2009 11:05:00 +0000</pubDate><atom:updated>2009-07-27T15:41:27.119+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">BizTalk</category><category domain="http://www.blogger.com/atom/ns#">BizUnit</category><category domain="http://www.blogger.com/atom/ns#">Oslo</category><title>Running BizUnit tests in Intellipad</title><description>&lt;div&gt;After a lot of work I've finally managed to get the tests running directly within Intellipad. My aim was to have a syntax highlighted BizUnitMgMode, where a key press would parse the source, start the BizUnit process and display the output in a new Intellipad buffer.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;I initially decided to re-use the CodeDOM compiling part of my code and basically compile the input to a dll and then use a testing framework to run the tests all within the context of Intellipad. This didn't go well.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;I tried MSTest first and thought it would be easy to hook up to the API and run the test programmatically. But there doesn't appear to be an API as most of the classes are internal. Then I thought to write a wrapper around MSTest.exe, but I couldn't see a way to get to the output as the exe presumably redirects the output to the test results files. Disappointing.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;NUnit next. After looking through the NUnit source and learning more about NUnit than I wanted to, I had the test running within the Visual Studio debugger. But no luck running the process from within Intellipad. I gave up and decided to forget the assembly idea and use the BizTalk object model directly. I only needed to write a simple test wrapper around the test runs, count passes and failures and BizUnit does the rest.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;The actual Intellipad mode was simple to set up using the code from the MUrl sample. The mode uses the GetParser() method directly from my compiler allowing Intellipad to recognise valid source files and syntax highlight. I set the Intellipad 'Extension' code attribute to recognize '.bzm' files and sure enough opening a valid .bzm file in Intellipad selects the correct BizUnitMgMode and syntax highlights nicely:&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_Sc3uxihjOeo/SjpkHfXcaPI/AAAAAAAAABk/fGPmD7dM2Ls/s1600-h/bizunitmgmode.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 303px;" src="http://2.bp.blogspot.com/_Sc3uxihjOeo/SjpkHfXcaPI/AAAAAAAAABk/fGPmD7dM2Ls/s400/bizunitmgmode.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5348697587297577202" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;I bound a key press to run the tests and the BizUnit output scrolls by in the output window:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Sc3uxihjOeo/SjpsgkBBQsI/AAAAAAAAAB0/M-rqGk9MzuQ/s1600-h/testwithoutput.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 311px;" src="http://4.bp.blogspot.com/_Sc3uxihjOeo/SjpsgkBBQsI/AAAAAAAAAB0/M-rqGk9MzuQ/s400/testwithoutput.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5348706814135452354" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3586668274215233910-6288468639584975458?l=bitsinout.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bitsinout.blogspot.com/2009/06/running-bizunit-tests-in-intellipad.html</link><author>noreply@blogger.com (Paul Arundel)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_Sc3uxihjOeo/SjpkHfXcaPI/AAAAAAAAABk/fGPmD7dM2Ls/s72-c/bizunitmgmode.jpg" height="72" width="72" /><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3586668274215233910.post-1615731943279817642</guid><pubDate>Wed, 10 Jun 2009 10:09:00 +0000</pubDate><atom:updated>2009-06-11T08:23:39.973+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">BizTalk</category><category domain="http://www.blogger.com/atom/ns#">BizUnit</category><category domain="http://www.blogger.com/atom/ns#">Oslo</category><title>Oslo May CTP Updates</title><description>&lt;div&gt;I've installed the &lt;a href="http://blogs.msdn.com/modelcitizen/archive/2009/05/27/about-the-oslo-may-2009-ctp.aspx"&gt;Oslo May CTP&lt;/a&gt; and updated my prototype Oslo BizUnit language to work with the various changes. I've only looked at the changes that affect my project and have not spent any time with the Repository, Quadrant or 'M'. Although in the latter case 'M' now refers to both the domain modeling language and the language for defining textual DSLs. So I am working with &lt;a href="http://msdn.microsoft.com/en-us/library/dd285282.aspx"&gt;'M'&lt;/a&gt; in the language definition sense. Clear?&lt;/div&gt;&lt;br /&gt;&lt;div&gt;The change in the meaning of 'M' has corresponding updates in the language tools. Project assembly references need to be updated from 'Microsoft.M.Grammar' to 'Microsoft.M'. The APIs have also changed. To compile your grammar and get a DyanamicParser the following changes are needed:&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp:nogutter"&gt;&lt;br /&gt; /*OLD&lt;br /&gt;MGrammarCompiler compiler = new MGrammarCompiler();&lt;br /&gt;compiler.FileNames = new string[] { "../../Mg/BizUnit.mg" };&lt;br /&gt;compiler.Compile(ErrorReporter.Standard);&lt;br /&gt;                &lt;br /&gt;DynamicParser parser = new DynamicParser();&lt;br /&gt;compiler.LoadDynamicParser(parser);&lt;br /&gt;return parser;&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;//NEW&lt;br /&gt;var options = new CompilerOptions() { &lt;br /&gt;    Sources = { new TextItem {&lt;br /&gt;          Name = "../../Mg/BizUnit.mg",&lt;br /&gt;          ContentType = TextItemType.MGrammar, &lt;br /&gt;          Reader = new StreamReader(syntax)}}};&lt;br /&gt;                    &lt;br /&gt;CompilationResults results = Compiler.Compile(options);&lt;br /&gt;return results.ParserFactories["BizUnit.TestLanguage"].Create();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;If you are using the Build task to compile your .mg file, the following change is needed:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp:nogutter"&gt;&lt;br /&gt;//OLD&lt;br /&gt;//return DynamicParser.LoadFromResource("BizUnitMg", "BizUnit.TestLanguage");&lt;br /&gt;&lt;br /&gt;//NEW&lt;br /&gt;return MImage.LoadFromResource(Assembly.GetExecutingAssembly(), "BizUnitMg.mx").&lt;br /&gt;                  ParserFactories["BizUnit.TestLanguage"].Create();&lt;br /&gt;               &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;You also need to update your .csproj file to use 'MCompile' rather than 'MgCompile' and the imported project from Microsoft.M.Grammar.targets to Microsoft.M.Embedded.targets.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;The most significant API change for my project was the deprecation of the GraphBuilder class in favour of a new NodeGraphBuilder. NodeGraphBuilder itself will be removed at some point but represents a temporary bridge to work with until IGraphBuilder is removed.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;NodeGraphBuilder provides a Node class to work with when processing a graph. This is an improvement on GraphBuilder where passing objects to various GraphBuilder methods was the only way to traverse and process the graph. Although NodeGraphBuilder provides a more natural interface, the graph structure has changed considerably. With GraphBuilder the graph of sequences and nodes was relatively easy to pick up, particularly as it closely resembled the graph view displayed by Intelipad. NodeGraphBuilder provides a considerably more complex model to work with, where the Node class is either Atomic (has a single value) or has a number of Edges which point to other nodes. This is described in detail in an article &lt;a href="http://msdn.microsoft.com/en-us/library/dd878360.aspx"&gt;here&lt;/a&gt; by Clemens Szyperski.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;I need to get a better understanding of the material covered in the article, but with a little patience I have managed to update my code to use NodeGraphBuilder. I spent a lot of time initially updating the projection of my syntax to a form that allowed me to make sense of the node graph. I particularly struggled with how my grammar related to the NodeKind concept and the graph patterns discussed in section 1.1.2 of the article. I gained some clarity when following section 1.1.1 of the aritcle and mapped branded nodes to the various tree node classes in the project (e.g. TestCaseNode or CopyFileNode) and used labels for the various atomic values (e.g. SourceFile, TimeToDelay).&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp:nogutter"&gt;&lt;br /&gt;protected TreeNode CreateTreeNode(Node n)&lt;br /&gt;{&lt;br /&gt;    string brand = n.Brand.Text;&lt;br /&gt;    return BizUnitMgCompiler.CreateNode(brand, n);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;protected string GetEdgeValueByLabel(Node n, string label)&lt;br /&gt;{&lt;br /&gt;    var e = n.Edges.Single(x =&gt; x.Label == label);&lt;br /&gt;    if (e.Node.AtomicValue != null)&lt;br /&gt;    {&lt;br /&gt;        return e.Node.AtomicValue.ToString();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return String.Empty;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;The CreateTreeNode helper method now uses the node brand to dynamically create the correct class. The second helper method retrieves a string value from a node's set of edges by label.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;Finally Intelipad appears to run a little quicker, although there are still delays when editing a grammar and the graph view is rebuilt. This delay has improved from over a second to well under a second for me. A restart of Intelipad now and again seems to help.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;Tree preview mode has disappeared. To get the previous input / grammar / graph split panel view you now have to:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Open your .mg file with Intelipad&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Choose 'Split new input and output views' from the DSL menu&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Select the input panel and open your input source file from the File menu.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;In the mode menu of the input panel select '[name of your grammar].mg Mode'&lt;/li&gt;&lt;br /&gt;&lt;li&gt; In the mode menu of the output panel select '[name of your grammar].mg Output Mode'&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Click the top left of your output panel and select the input source file.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Sc3uxihjOeo/Si_J_z6zvPI/AAAAAAAAABc/AMBs2Uae9r0/s1600-h/mayinteli.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 278px;" src="http://4.bp.blogspot.com/_Sc3uxihjOeo/Si_J_z6zvPI/AAAAAAAAABc/AMBs2Uae9r0/s400/mayinteli.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5345713380817878258" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3586668274215233910-1615731943279817642?l=bitsinout.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bitsinout.blogspot.com/2009/06/oslo-may-ctp-updates.html</link><author>noreply@blogger.com (Paul Arundel)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_Sc3uxihjOeo/Si_J_z6zvPI/AAAAAAAAABc/AMBs2Uae9r0/s72-c/mayinteli.jpg" height="72" width="72" /><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3586668274215233910.post-9094191154552085004</guid><pubDate>Sun, 31 May 2009 15:40:00 +0000</pubDate><atom:updated>2009-06-01T22:38:20.121+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">BizTalk</category><category domain="http://www.blogger.com/atom/ns#">BizUnit</category><category domain="http://www.blogger.com/atom/ns#">Oslo</category><title>MGrammar BizUnit DSL - overview of the compiler</title><description>As mentioned in my previous &lt;a href="http://bitsinout.blogspot.com/2009/05/bizunit-mgrammar.html"&gt;post&lt;/a&gt; I wanted the compiler of my DSL for BizUnit to be able to generate different outputs. Initially this will either be an assembly that can be executed by MSTest/NUnit or BizUnit xml files for each of the tests. Once I have the compiler tidied up I want to look at directly executing the test scripts within Intellipad with an interactive mode like &lt;a href="http://www.douglaspurdy.com/2009/03/20/murl-a-dsl-for-restful-clients/"&gt;MUrl&lt;/a&gt;.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;My compiler needs to be able to traverse the graph of the input file generated by the Oslo tools and create one of the two types of output. Taking the lead from Roger Alsing's &lt;a href="http://rogeralsing.com/2008/11/22/linqing-mgrammar-to-cil/"&gt;excellent example post&lt;/a&gt; and dusting off my copy of the Design Patterns book, the &lt;a href="http://en.wikipedia.org/wiki/Visitor_pattern"&gt;Visitor&lt;/a&gt; pattern seems a good fit for the general design. This allows separation of the process to traverse our node graph from the actual operations we want to perform on each node. The operations being those that actually create output. Additionally each visitor is a separate class and can therefore build up appropriate state while each node is visited. The image below shows the base TreeNode class and a few of the classes for BizUnit steps:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Sc3uxihjOeo/SiK2ykCapzI/AAAAAAAAAAs/088PDgJ-qjI/s1600-h/nodes.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 228px;" src="http://1.bp.blogspot.com/_Sc3uxihjOeo/SiK2ykCapzI/AAAAAAAAAAs/088PDgJ-qjI/s400/nodes.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5342033087798355762" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Each node implements the Accept() method inherited from the abstract base class taking an instance of a visitor and calling the appropriate visitor method for the node type. Additionally each node class stores properties relevant to the BizUnit step it represents (e.g. The length of time to delay for the DelayStep) as the visitor will need access to these for the operations it will perform. Below is the code for a SequenceNode in the graph:&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp:nogutter"&gt;&lt;br /&gt;public class SequenceNode : TreeNode&lt;br /&gt;{&lt;br /&gt;    public SequenceNode(object node) : base(node) { }&lt;br /&gt;&lt;br /&gt;    public override void Accept(IVisitor visitor)&lt;br /&gt;    {&lt;br /&gt;        foreach (object n in Builder.GetSequenceElements(Node))&lt;br /&gt;        {&lt;br /&gt;            TreeNode gn = CreateTreeNode(n);&lt;br /&gt;            gn.Accept(visitor);&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;        visitor.Visit(this);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;For the case of a SequenceNode, a System.DataFlow.GraphBuilder is used to retrieve all the elements in the sequence. The method CreateTreeNode() dynamically creates an instance of the appropriate node (by matching name to a node type) and calls Accept() on each node. An instance of the following class is created for a CopyFile:  &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp:nogutter"&gt;&lt;br /&gt;public class CopyFileNode : TreeNode&lt;br /&gt;{&lt;br /&gt;    public string SourcePath { get; set; }&lt;br /&gt;    public string CreationPath { get; set; }&lt;br /&gt;&lt;br /&gt;    public CopyFileNode(object node)&lt;br /&gt;        : base(node)&lt;br /&gt;    {&lt;br /&gt;        SourcePath = GetValue(node, "From");&lt;br /&gt;        CreationPath = GetValue(node, "To");&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public override void Accept(IVisitor visitor)&lt;br /&gt;    {&lt;br /&gt;        visitor.Visit(this);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;The GetValue() method is a helper method that uses a GraphBuilder to retrieve descendant nodes by label. In this case the CopyFile node will have descendant nodes named 'From' and 'To'. As there is no node processing needed the Accept() method simply calls the Visit() method on the visitor instance which can then perform the appropriate operations for a CopyFile. &lt;/div&gt;&lt;br /&gt;&lt;div&gt;I've created two implementations of the visitor interface to generate the two output types. The first uses the various classes in the System.Xml.Linq namespace to generate BizUnit xml files. The second the CodeDOM to generate a test assembly:&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_Sc3uxihjOeo/SiLo4I-SlLI/AAAAAAAAABU/o1Ite5vhYUA/s1600-h/visitor.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 193px;" src="http://3.bp.blogspot.com/_Sc3uxihjOeo/SiLo4I-SlLI/AAAAAAAAABU/o1Ite5vhYUA/s400/visitor.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5342088159193896114" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;The visitor interface looks as follows (with a small number of BizUnit steps):&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp:nogutter"&gt;&lt;br /&gt;public interface IVisitor&lt;br /&gt;{&lt;br /&gt;    void Visit(BizUnitTestFixtureNode node);&lt;br /&gt;    void Visit(TestCaseNode node);&lt;br /&gt;    void Visit(VarNode node);&lt;br /&gt;    void Visit(SequenceNode node);&lt;br /&gt;    void Visit(BizUnitStepNode node);&lt;br /&gt;    void Visit(CopyFileNode node);&lt;br /&gt;    void Visit(DelayNode node);&lt;br /&gt;    void Visit(ValidateFileNode node);&lt;br /&gt;    void Visit(DBNonQueryNode node);&lt;br /&gt;    void Visit(CleanUpNode node);&lt;br /&gt;    void Visit(HttpPostNode node);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;The following code illustrates how the visitor processes a DBNonQuery node and creates an xml element for the BizUnit step. The '_testDocs' variable is just a collection used to build up the various xml elements created as the process moves through the node tree.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="c-sharp:nogutter"&gt;&lt;br /&gt;public void Visit(DBNonQueryNode node)&lt;br /&gt;{&lt;br /&gt;    CreateTestStep(node, "BizUnit.DBExecuteNonQueryStep",&lt;br /&gt;        new XElement("DelayBeforeExecution", 0),&lt;br /&gt;        new XElement("ConnectionString", node.ConnectionStr),&lt;br /&gt;        new XElement("NumberOfRowsAffected", node.NumberOfRowsAffected),&lt;br /&gt;        new XElement("SQLQuery", new XElement("RawSQLQuery", node.Query)));&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;private void CreateTestStep(object node, string assemblyName, string typeName, params XElement[] xel)&lt;br /&gt;{&lt;br /&gt;    _testDocs.Last().Value.Descendants(_testStage).&lt;br /&gt;        First().Add(CreateStepXElement("TestStep", assemblyName,typeName,xel));&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private XElement CreateStepXElement(string name, string assemblyName, string typeName, params XElement[] xel)&lt;br /&gt;{&lt;br /&gt;    return new XElement(name, new XAttribute("assemblyPath", assemblyName), new XAttribute("typeName", typeName), xel);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt; &lt;br /&gt;&lt;div&gt;As the visitor processes each node it adds a new XML element to the correct test stage of the current XDocument being worked on. Once all the nodes have been processed the XDocuments are saved to the file system. The CodeDOM visitor is very similar in process but obviously builds up the various code methods, attributes and expressions before saving as a .NET assembly. &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3586668274215233910-9094191154552085004?l=bitsinout.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bitsinout.blogspot.com/2009/05/mgrammar-bizunit-dsl-design-of-compiler.html</link><author>noreply@blogger.com (Paul Arundel)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_Sc3uxihjOeo/SiK2ykCapzI/AAAAAAAAAAs/088PDgJ-qjI/s72-c/nodes.jpg" height="72" width="72" /><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3586668274215233910.post-5614207079603311801</guid><pubDate>Tue, 26 May 2009 20:34:00 +0000</pubDate><atom:updated>2009-06-01T15:09:28.158+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">BizTalk</category><category domain="http://www.blogger.com/atom/ns#">BizUnit</category><category domain="http://www.blogger.com/atom/ns#">Oslo</category><title>Prototype of an MGrammar DSL for BizUnit</title><description>&lt;div&gt;Inspired by &lt;a href="http://www.sabratech.co.uk/blogs/yossidahan/2009/05/oslo-based-solution-for-deploying.html"&gt;Yossi's&lt;/a&gt; Oslo based BizTalk deployment solution, I scanned around for a similar project to get experience of using the Oslo tools. I decided to try implementing a small language to write &lt;a href="http://www.codeplex.com/bizunit"&gt;BizUnit&lt;/a&gt; tests.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;While the declarative programming model used by BizUnit provides a lot of flexibility, the resulting XML test files are not the easiest to read, understand and maintain. I imagine the original intention was for the XML to be auto generated, but in my experience, most BizTalk devs are hand coding the xml test files. This makes it difficult to understand the test coverage of a solution's test scripts when presented with pages and pages of angle brackets.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So my aim is to write a simple DSL that will compile down to calling the various steps of the BizUnit framework and allow developers (and maybe non-technical testers) to easily write and understand tests for common integration scenarios. The language will use the same step approach as BizUnit but with a minimal syntax. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For example to copy a file in BizUnit you use the following XML:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;pre&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;&amp;lt;TestStep assemblyPath="" typeName="BizUnit.FileCreateStep"&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;  &amp;lt;SourcePath&amp;gt;.\TestData\InDoc1.xml&amp;lt;/SourcePath&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;  &amp;lt;CreationPath&amp;gt;.\Rec_01\InDoc1.xml&amp;lt;/CreationPath&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;&amp;lt;/TestStep&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt;With the DSL we could simply write something like:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;CopyFile&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt; ".\TestData\InDoc1.xml" &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;To&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt; ".\Rec_01\InDoc1.xml"&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This doesn't look a great deal, but a few lines of this language are much easier to understand than a few pages of the XML. Where possible I also think it makes sense to use sensible defaults for BizUnit step properties e.g.:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;pre&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;&amp;lt;TestStep assemblyPath="" typeName="BizUnit.FileValidateStep"&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;  &amp;lt;Timeout&amp;gt;2000&amp;lt;/Timeout&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;  &amp;lt;Directory&amp;gt;C:\Recv2\&amp;lt;/Directory&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;  &amp;lt;SearchPattern&amp;gt;TransactionId_*.xml&amp;lt;/SearchPattern&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;  &amp;lt;DeleteFile&amp;gt;true&amp;lt;/DeleteFile&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;&amp;lt;ValidationStep assemblyPath="&amp;amp;quot typeName="BizUnit.BinaryValidationStep"&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;      &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;&amp;lt;ComparisonDataPath&amp;gt;.\TestData\ResultDoc1.xml&amp;lt;/ComparisonDataPath&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;&amp;lt;CompareAsUTF8&amp;gt;true&amp;lt;/CompareAsUTF8&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;&amp;lt;/ValidationStep&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;&amp;lt;/TestStep&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Using common defaults this can be reduced to:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;ValidateFile&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt; "C:\Recv2\TransactionId_*.xml" &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;With&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span" style="font-style: normal;"&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt; ".\TestData\ResultDoc1.&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;xm&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;l"&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Obviously the language can be extended to set the other properties, but my aim is to make the tests scripts as clean as possible.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To get started defining a language with Intellipad you create a blank .mg file for your MGrammar and a blank file for your input language, open the .mg file in Intellipad, select Tree Preview mode, select your blank input file and off you go. Once you get the basic idea of declaring tokens and syntax rules, Intellipad works its magic and starts syntax highlighting your input language on the left and displaying the resulting graph on the right.  I've no real experience of creating DSLs, or compilers for that matter* but the few samples that come with Intellipad get you started surprisingly quickly.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;After a few hours I had a working version of my language. The overall structure is similar to writing normal c# unit tests targeting MSTest or NUnit, but with each test case allowing a number of BizUnit steps and a cleanup step if needed. The screenshot below shows a couple of tests defined with Intellipad syntax highlighting:&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_Sc3uxihjOeo/ShxTH1jQRTI/AAAAAAAAAAc/2zgU7QY6wtQ/s1600-h/bzm.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 271px;" src="http://2.bp.blogspot.com/_Sc3uxihjOeo/ShxTH1jQRTI/AAAAAAAAAAc/2zgU7QY6wtQ/s400/bzm.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5340234652253701426" /&gt;&lt;/a&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've allowed the use of variable definitions in the language. From my experience the paths to files or URLs are used repeatedly throughout BizUnit tests and variables allow these to be declared once.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now I have the basic syntax of my language defined as an .mg file the Oslo tools allow me to create a compiled version of this syntax, an .mgx file. This in turn can be used to process any input files written in the language and produce an MGraph, a tree structure we can then parse to create the output we require. Intellipad dynamically shows a similar graph as you work on your DSL:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_Sc3uxihjOeo/ShxTm1HhJRI/AAAAAAAAAAk/SBrsxOekuro/s1600-h/graph.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 292px;" src="http://3.bp.blogspot.com/_Sc3uxihjOeo/ShxTm1HhJRI/AAAAAAAAAAk/SBrsxOekuro/s400/graph.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5340235184713311506" /&gt;&lt;/a&gt; &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt;I will discuss my compiler as it stands in my next post. It is successfully compiling the syntax as defined and can output either a dll that can be executed directly (with NUnit/MSTest) or can generate matching BizUnit XML files. I think this latter option is important as any investment in time with this language will at least allow you to create standard BizUnit XML files should you decide not to use it fully. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Overall I'm not sure whether this adds a great deal to BizUnit. The syntax is much clearer, but it is another syntax to learn. You could also potentially write a few helper classes that wrap the BizUnitOM classes and allow you to write similar tests directly in c# avoiding this DSL malarkey completely.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The major issue though, is in limiting yourself to this easy syntax you're potentially losing BizUnit's major strengths, its flexibility and extensibility. Every BizTalk solution I have worked on has required custom BizUnit steps of some form. The language will need a way of expressing these custom steps cleanly.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;* Apart from the obligatory BrainF*** to CIL compiler of course.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3586668274215233910-5614207079603311801?l=bitsinout.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bitsinout.blogspot.com/2009/05/bizunit-mgrammar.html</link><author>noreply@blogger.com (Paul Arundel)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_Sc3uxihjOeo/ShxTH1jQRTI/AAAAAAAAAAc/2zgU7QY6wtQ/s72-c/bzm.jpg" height="72" width="72" /><thr:total>0</thr:total></item></channel></rss>

