<?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:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>GauravMantri.com</title>
	
	<link>http://gauravmantri.com</link>
	<description>Gaurav Mantri's Personal Blog</description>
	<lastBuildDate>Sat, 18 May 2013 07:54:31 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.4.2</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/gmantri" /><feedburner:info uri="gmantri" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>gmantri</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item>
		<title>Windows Azure Blob Storage – Dealing With “The specified blob or block content is invalid” Error</title>
		<link>http://feedproxy.google.com/~r/gmantri/~3/UKbZOkEZGmU/</link>
		<comments>http://gauravmantri.com/2013/05/18/windows-azure-blob-storage-dealing-with-the-specified-blob-or-block-content-is-invalid-error/#comments</comments>
		<pubDate>Sat, 18 May 2013 07:42:33 +0000</pubDate>
		<dc:creator>Gaurav</dc:creator>
				<category><![CDATA[Windows Azure]]></category>
		<category><![CDATA[Windows Azure Blob Storage]]></category>

		<guid isPermaLink="false">http://gauravmantri.com/?p=1282</guid>
		<description><![CDATA[If you’re uploading blobs by splitting blobs into blocks and you get the error &#8211; The specified blob or block content is invalid, then this post is for you. Short Version If you’re uploading blobs by splitting blobs into blocks and you get the above mentioned error, ensure that your block ids of your blocks [...]]]></description>
			<content:encoded><![CDATA[<p>
If you’re uploading blobs by splitting blobs into blocks and you get the error &#8211; <b><i>The specified blob or block content is invalid</i></b>, then this post is for you.
</p>
<h2>Short Version</h2>
<p>
If you’re uploading blobs by splitting blobs into blocks and you get the above mentioned error, <b>ensure that your block ids of your blocks are of same length</b>. If the block ids of your blocks are of different length, you’ll get this error.
</p>
<h2>Long Version</h2>
<p>
Now for the longer version of this post <img class="wlEmoticon wlEmoticon-smile" style="border-top-style: none; border-left-style: none; border-bottom-style: none; border-right-style: none" alt="Smile" src="http://gauravmantri.com/wp-content/uploads/2013/05/wlEmoticon-smile2.png" />. A few days back I was working with storage client library especially around uploading blobs in chunks and with one particular blob I was constantly getting the error &#8211; <b><i>The specified blob or block content is invalid</i></b>. I tried numerous combinations even resorting to REST API directly but to no avail. It only happened with just one blob. Furthermore if I uploaded the same blob without splitting it into blocks, all was well. I was at my wits&#8217; end. Tried searching the Internet for this error but could not find a conclusive answer to my problem.
</p>
<p>
After much trial and error, I was able to simulate the same problem on other blobs as well. Here’s how you can recreate it:
</p>
<ol>
<li>Start uploading the blob by splitting it into blocks. For block id, let’s do a 7 character long string e.g. <font face="Consolas">intValue.ToString(“d7”)</font>. This will ensure that my block ids would be “0000001”, “0000002”, …, ”0000010” ….. </li>
<li>After one or two blocks are uploaded, cancel the operation. </li>
<li>Now re-upload the blob by splitting it into blocks. However this time for block id, let’s do a 6 character long string e.g. <font face="Consolas">intValue.ToString(“d6”)</font>. </li>
<li>You’ll get the error as soon as you try to upload the 1<sup>st</sup> block. </li>
</ol>
<h2>Possible Solutions</h2>
<p>
Now that we know the root cause of this problem, let’s look at some of the possible solutions to solve this problem.
</p>
<h3>Wait out</h3>
<p>
One possible solution is to wait out. I know its lame but still a possible solution. We know that Windows Azure Blob Storage Service keeps all uncommitted blocks for a duration of 7 days and if within 7 days those uncommitted blocks are not committed, the storage service purges them.
</p>
<p>
I wish storage service provided some mechanism to purge uncommitted blocks programmatically.
</p>
<h3>Commit uncommitted blocks</h3>
<p>
You could possibly commit the blocks which are in uncommitted state so that at least you get a blob (which would not be the blob we wanted to upload in the first place). You can then delete that blob and re-upload the blob by specifying block ids which are of same length. To fetch the list of uncommitted blocks, if you’re using REST API directly you can perform “<a href="http://msdn.microsoft.com/en-us/library/windowsazure/dd179400.aspx" target="_blank">Get Block List</a>” operation and pass “<font face="Consolas">blocklisttype=uncommitted</font>” as one of the query string parameters. If you’re using storage client library (assuming you’re using the version 2.x of .Net storage client library), you can do something like the code below:
</p>
<p><pre class="brush: plain; title: ; notranslate">
        private static List&lt;string&gt; GetUncommittedBlockIds(CloudBlockBlob blob)
        {
            var sasUri = blob.GetSharedAccessSignature(new SharedAccessBlobPolicy()
            {
                SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(5),
                Permissions = SharedAccessBlobPermissions.Read,
            });
            var blobUri = new Uri(string.Format(&quot;{0}{1}&quot;, blob.Uri, sasUri));
            List&lt;string&gt; uncommittedBlockIds = new List&lt;string&gt;();
            var request = BlobHttpWebRequestFactory.GetBlockList(blobUri, null, null, BlockListingFilter.Uncommitted, null, null);
            //request.Headers.Add(&quot;Authorization&quot;, 
            using (var resp = (HttpWebResponse)request.GetResponse())
            {
                using (var stream = resp.GetResponseStream())
                {
                    var getBlockListResponse = new GetBlockListResponse(stream);
                    var blocks = getBlockListResponse.Blocks;
                    foreach (var block in blocks.Where(b =&gt; !b.Committed))
                    {
                        uncommittedBlockIds.Add(Encoding.UTF8.GetString(Convert.FromBase64String(block.Name)));
                    }
                }
            }
            return uncommittedBlockIds;
        }
</pre>
</p>
<p>
A few things to keep in mind here:
</p>
<ul>
<li><a href="http://msdn.microsoft.com/en-us/library/windowsazure/microsoft.windowsazure.storage.blob.aspx" target="_blank">Microsoft.WindowsAzure.Storage.Blob</a> namespace does not have the capability to get the list of uncommitted blocks. You would need to make use of <a href="http://msdn.microsoft.com/en-us/library/windowsazure/microsoft.windowsazure.storage.blob.protocol.aspx" target="_blank">Microsoft.WindowsAzure.Storage.Blob.Protocol</a> namespace. </li>
<li>Because we’re kind of invoking the REST API by executing an HttpWebRequest, I created a shared access signature on the blob so that I don’t have to create “Authorization” header. </li>
</ul>
<h3>Fetch uncommitted blocks to see block id length</h3>
<p>
You could fetch the list of uncommitted blocks just to find out the length of the block id used. You could then use that block id length for your new upload session and do the upload. Please see the code snippet above to find this information.
</p>
<h3>Upload another blob with same name without splitting it into blocks</h3>
<p>
You could also upload another blob with the same name without splitting it into blocks. It could very well be a zero byte blob. That way your uncommitted block list will be wiped clean. Then you could delete that dummy blob and re-upload the actual blob.
</p>
<h2>A Few Words About Blocks</h2>
<p>
Since we’re talking about blocks, I thought it might be useful to mention a few points about them:
</p>
<ul>
<li><b>Blocks and block related operations are only applicable for “Block Blobs”</b>. Duh!! You’ll get an error if you’re trying to do these operations on a “Page Blob”. </li>
<li><b>For uploading large blobs, it is recommended that you split your blob into blocks</b>. In fact if your blob size is more than 64 MB, then you have to split it into blocks. </li>
<li><b>Minimum size of a block is 1 Byte and the maximum size of a block is 4 MB</b>. It is recommended that you choose a block size based on your internet connectivity and number of parallel threads you want use to upload these blocks. </li>
<li><b>A blob can be split into a maximum of 50000 blocks</b>. It’s important to remember this limitation because you are reminded of this limit when you’re trying to upload 50001<sup>st</sup> block. </li>
<li><b>The length of all the block ids must be same</b>. So if you’re using an integer value to denote block id, you make sure that you pad that integer value with “0” so that you get same length. So you could do something like <font face="Consolas">int.ToString(“d6”)</font>. </li>
<li><b>When passing the block id as a parameter, it must be Base64 encoded</b>. </li>
<li><b>While the order in which the blocks are uploaded is not important, the order is important when you commit the block list</b> because that’s when the blob is constructed by the service. For example, let’s say you’re uploading a blob by splitting it into 5 blocks (with ids “000001”, “000002”, “000003”, “000004”, and “000005”). You could upload these blocks in any order – 000004, 000001, 000003, 000005, 000002 however when you commit the block list, ensure that the block ids are passed in proper order i.e. 000001, 000002, 000003, 000004, 000005. </li>
</ul>
<h2>Summary</h2>
<p>
That’s it for this post. I hope you’ve found this information useful. I spent considerable amount of time trying to fix this problem so I hope it will help some folks out. As always, if you find any issues with the post please let me know and I’ll fix it ASAP.
</p>
<p>
Happy Coding!</p>
<img src="http://feeds.feedburner.com/~r/gmantri/~4/UKbZOkEZGmU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://gauravmantri.com/2013/05/18/windows-azure-blob-storage-dealing-with-the-specified-blob-or-block-content-is-invalid-error/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://gauravmantri.com/2013/05/18/windows-azure-blob-storage-dealing-with-the-specified-blob-or-block-content-is-invalid-error/</feedburner:origLink></item>
		<item>
		<title>Windows Azure SDK 2.0 For .Net – Taking A Second Look At Windows Azure Diagnostics</title>
		<link>http://feedproxy.google.com/~r/gmantri/~3/dO_393t2KAA/</link>
		<comments>http://gauravmantri.com/2013/05/12/windows-azure-sdk-2-0-for-net-taking-a-second-look-at-windows-azure-diagnostics/#comments</comments>
		<pubDate>Sun, 12 May 2013 15:43:33 +0000</pubDate>
		<dc:creator>Gaurav</dc:creator>
				<category><![CDATA[Windows Azure]]></category>
		<category><![CDATA[Windows Azure Diagnostics]]></category>
		<category><![CDATA[Windows Azure SDK]]></category>
		<category><![CDATA[Windows Azure Service Management API]]></category>
		<category><![CDATA[Cloud Service Extensions]]></category>
		<category><![CDATA[Windows Azure Cloud Service]]></category>

		<guid isPermaLink="false">http://gauravmantri.com/?p=1274</guid>
		<description><![CDATA[A few days ago I wrote a post about newly released Windows Azure SDK 2.0 for .Net. You can read that post here: http://gauravmantri.com/2013/04/30/introducing-windows-azure-sdk-2-0-for-net/. In that post I briefly talked about the improvements in the latest SDK with regards to Windows Azure Diagnostics (WAD). In this post, we’ll talk about WAD in more details. We’ll [...]]]></description>
			<content:encoded><![CDATA[<p>
A few days ago I wrote a post about newly released Windows Azure SDK 2.0 for .Net. You can read that post here: <a href="http://gauravmantri.com/2013/04/30/introducing-windows-azure-sdk-2-0-for-net/" target="_blank">http://gauravmantri.com/2013/04/30/introducing-windows-azure-sdk-2-0-for-net/</a>. In that post I briefly talked about the improvements in the latest SDK with regards to Windows Azure Diagnostics (WAD). In this post, we’ll talk about WAD in more details. We’ll talk about improvements in SDK as well as changes in the Service Management API to facilitate these changes.
</p>
<p>
So let’s start.
</p>
<h2>Changes to Windows Azure Diagnostics</h2>
<p>
First let’s talk about changes done to Windows Azure Diagnostics.
</p>
<h3>Windows Azure Diagnostics is now an Extension</h3>
<p>
Windows Azure Diagnostics (WAD) module is now an <b>extension to your cloud service</b>. I wrote a blog post on extensions which you can read here: <a href="http://gauravmantri.com/2013/05/06/windows-azure-cloud-services-extensions-and-service-management-api-fun-with-remote-desktop/" target="_blank">http://gauravmantri.com/2013/05/06/windows-azure-cloud-services-extensions-and-service-management-api-fun-with-remote-desktop/</a>. What that means is that you can enable / disable diagnostics functionality on the fly. If you’ve been working with cloud services, I think you’ll greatly appreciate this enhancement. In the cloud services which used previous version (say 1.8) of the SDK, enabling diagnostics was a pain. One would need to remember a lot of things to get the diagnostics working and if one forgets to do those things, the only option to make diagnostics working was to go back to your code and make the changes and redeploy your application. NOT ANYMORE! Even if you forget to enable diagnostics when you first deploy your cloud service, you can enable the diagnostics on the fly using the extensions mechanism. Furthermore, you don’t really need to write any code in your role’s OnStart() method to enable the diagnostics.
</p>
<p>
We’ll see an example of how you can do this later in this post.
</p>
<h3>Configuring Windows Azure Diagnostics has never been easier</h3>
<p>
With the latest SDK, it’s extremely easy to configure Windows Azure Diagnostics (WAD). Visual Studio provides you with an easy to use user interface to configure the diagnostics. To configure WAD, open up your cloud service configuration by double clicking on the role’s name and go to “Configuration” tab. Under the “Diagnostics” section, you’ll see various configuration options as shown in the screenshot below:
</p>
<p>
<a href="http://gauravmantri.com/wp-content/uploads/2013/05/clip_image002.jpg"><img title="clip_image002" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="clip_image002" src="http://gauravmantri.com/wp-content/uploads/2013/05/clip_image002_thumb.jpg" width="810" height="501" /></a>
</p>
<p>
If you’ve been using previous versions of SDK, you’re used to seeing this kind of screen:
</p>
<p>
<a href="http://gauravmantri.com/wp-content/uploads/2013/05/clip_image004.jpg"><img title="clip_image004" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="clip_image004" src="http://gauravmantri.com/wp-content/uploads/2013/05/clip_image004_thumb.jpg" width="810" height="465" /></a>
</p>
<p>
As you can see from the screenshots, not only you get to choose whether the diagnostics should be enabled or disabled you also get a simple to use user interface to configure the diagnostics. Let’s talk about these options.
</p>
<h4>Errors only</h4>
<p>
When you choose “Errors Only” option, WAD extension transfers only the log entries with log level type “error” and “critical” to storage. A few things to keep in mind:
</p>
<ul>
<li>This option will only enable following log types – trace and event logs. </li>
<li>This option will not do anything with the performance counters. So no performance counters data will be transferred to storage. </li>
<li>As said earlier, only “error” and “critical” log entries will be transferred to storage. </li>
<li>By default the logs will be transferred to storage every minute or in other words the scheduled transfer period is one minute. </li>
</ul>
<p>
Following code segment shows what kind of trace log entries will be transferred if this option is chosen:
</p>
<p><pre class="brush: plain; title: ; notranslate">
            Trace.WriteLine(&quot;This is verbose trace entry&quot;, &quot;Verbose&quot;);//Will NOT be transferred.
            Trace.WriteLine(&quot;This is information trace entry&quot;, &quot;Information&quot;);//Will NOT be transferred.
            Trace.WriteLine(&quot;This is warning trace entry&quot;, &quot;Warning&quot;);//Will NOT be transferred.
            Trace.WriteLine(&quot;This is error trace entry&quot;, &quot;Error&quot;);//Will BE transferred.
            Trace.WriteLine(&quot;This is critical trace entry&quot;, &quot;Critical&quot;);//Will BE transferred.
</pre>
</p>
<h4>All information</h4>
<p>
When you choose “All information” option, WAD extension transfers all log entries to storage. A few things to keep in mind:
</p>
<ul>
<li>This option will only enable following log types – trace and event logs. </li>
<li>This option will not do anything with the performance counters. So no performance counters data will be transferred to storage. </li>
<li>As said earlier, all log entries will be transferred to storage. This would include the following log level types: Verbose, Information, Warning, Error and Critical. </li>
<li>By default the logs will be transferred to storage every minute or in other words the scheduled transfer period is one minute.</li>
</ul>
<p>
Following code segment shows what kind of trace log entries will be transferred if this option is chosen:
</p>
<p><pre class="brush: plain; title: ; notranslate">
            Trace.WriteLine(&quot;This is verbose trace entry&quot;, &quot;Verbose&quot;);// Will BE transferred.
            Trace.WriteLine(&quot;This is information trace entry&quot;, &quot;Information&quot;);// Will BE transferred.
            Trace.WriteLine(&quot;This is warning trace entry&quot;, &quot;Warning&quot;);// Will BE transferred.
            Trace.WriteLine(&quot;This is error trace entry&quot;, &quot;Error&quot;);//Will BE transferred.
            Trace.WriteLine(&quot;This is critical trace entry&quot;, &quot;Critical&quot;);//Will BE transferred.
</pre>
</p>
<h4>Custom plan</h4>
<p>
Custom plan is where things get interesting. Here you get full flexibility for configuring WAD. This is where you’re in complete control of what is captured and what gets transferred to storage. Here’re a few screenshots of the window where you can customize the diagnostics:
</p>
<p>
<b>Trace Logs</b><br />
<a href="http://gauravmantri.com/wp-content/uploads/2013/05/clip_image0025.jpg"><img title="clip_image002[5]" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="clip_image002[5]" src="http://gauravmantri.com/wp-content/uploads/2013/05/clip_image0025_thumb.jpg" width="810" height="551" /></a>
</p>
<p>
<b>Event Logs</b><br />
<a href="http://gauravmantri.com/wp-content/uploads/2013/05/clip_image0045.jpg"><img title="clip_image004[5]" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="clip_image004[5]" src="http://gauravmantri.com/wp-content/uploads/2013/05/clip_image0045_thumb.jpg" width="810" height="551" /></a>
</p>
<p>
<b>Performance Counters</b><br />
<a href="http://gauravmantri.com/wp-content/uploads/2013/05/clip_image006.jpg"><img title="clip_image006" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="clip_image006" src="http://gauravmantri.com/wp-content/uploads/2013/05/clip_image006_thumb.jpg" width="810" height="551" /></a>
</p>
<p>
My guess is that most of the time developers would use these screens to configure diagnostics.
</p>
<h4>Diagnostics.wadcfg file</h4>
<p>
If you look closely in your solution explorer, you’ll notice a diagnostics.wadcfg file beneath your role name. You can read more about this file here: <a href="http://msdn.microsoft.com/en-us/library/windowsazure/hh411551.aspx" target="_blank">http://msdn.microsoft.com/en-us/library/windowsazure/hh411551.aspx</a>.
</p>
<p>
<a href="http://gauravmantri.com/wp-content/uploads/2013/05/clip_image0027.jpg"><img title="clip_image002[7]" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="clip_image002[7]" src="http://gauravmantri.com/wp-content/uploads/2013/05/clip_image0027_thumb.jpg" width="452" height="417" /></a>
</p>
<p>
Essentially when you configure diagnostics using one of the options above, Visual Studio automatically updates this file. This is not a new concept and has been around for quite some time. What’s new is that now Visual Studio creates this file for you. So if you want to tweak some settings after Visual Studio has updated the file, just modify the XML file manually and you should be good to go.
</p>
<h3>Good Bye Old Storage Client Library</h3>
<p>
SDK 1.8 came with a new version of storage client library (2.0.0.0) however Windows Azure Diagnostics (WAD) was not updated to make use of this library. It was still using older version of storage client library. Needless to say, it was a big mess. Not only you would need to remember to add reference to both versions of the library but also take into consideration the different namespaces of older and newer versions of storage client library. With the release of SDK 2.0, WAD library is updated to make use of the latest version of storage client library which is 2.0.5.1 at the time SDK 2.0 was made live.
</p>
<h2>Diagnostics Extension</h2>
<p>
In this section we’ll talk about diagnostics extension and how it can be used to enable/disable or change diagnostics on the fly. I would recommend going through my blog post on extensions first because we’ll make use of code from that post. You can read that post here: <a href="http://gauravmantri.com/2013/05/06/windows-azure-cloud-services-extensions-and-service-management-api-fun-with-remote-desktop/" target="_blank">http://gauravmantri.com/2013/05/06/windows-azure-cloud-services-extensions-and-service-management-api-fun-with-remote-desktop/</a>.
</p>
<p>
For fun sake, we’ll create a cloud service (a simple worker role will do) and choose not to enable diagnostics. When we do that, out diagnostics.wadcfg file looks something like this:
</p>
<p><pre class="brush: plain; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;DiagnosticMonitorConfiguration configurationChangePollInterval=&quot;PT1M&quot; 
                                overallQuotaInMB=&quot;4096&quot; 
                                xmlns=&quot;http://schemas.microsoft.com/ServiceHosting/2010/10/DiagnosticsConfiguration&quot;&gt;
  &lt;DiagnosticInfrastructureLogs /&gt;
  &lt;Directories&gt;
    &lt;IISLogs container=&quot;wad-iis-logfiles&quot; /&gt;
    &lt;CrashDumps container=&quot;wad-crash-dumps&quot; /&gt;
  &lt;/Directories&gt;
  &lt;Logs bufferQuotaInMB=&quot;1024&quot; scheduledTransferPeriod=&quot;PT0M&quot; scheduledTransferLogLevelFilter=&quot;Error&quot; /&gt;
  &lt;WindowsEventLog bufferQuotaInMB=&quot;1024&quot; scheduledTransferPeriod=&quot;PT0M&quot; scheduledTransferLogLevelFilter=&quot;Error&quot;&gt;
    &lt;DataSource name=&quot;Application!*&quot; /&gt;
  &lt;/WindowsEventLog&gt;
&lt;/DiagnosticMonitorConfiguration&gt;
</pre>
</p>
<p>
This is how my worker role’s code looks like:
</p>
<p><pre class="brush: plain; title: ; notranslate">
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Threading;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.Diagnostics;
using Microsoft.WindowsAzure.ServiceRuntime;
using Microsoft.WindowsAzure.Storage;

namespace WorkerRole1
{
    public class WorkerRole : RoleEntryPoint
    {
        public override void Run()
        {
            // This is a sample worker implementation. Replace with your logic.
            Trace.TraceInformation(&quot;WorkerRole1 entry point called&quot;, &quot;Information&quot;);

            while (true)
            {
                Thread.Sleep(10000);
                Trace.WriteLine(&quot;This is verbose trace entry&quot;, &quot;Verbose&quot;);//Will NOT be transferred.
                Trace.WriteLine(&quot;This is information trace entry&quot;, &quot;Information&quot;);//Will NOT be transferred.
                Trace.WriteLine(&quot;This is warning trace entry&quot;, &quot;Warning&quot;);//Will BE transferred.
                Trace.WriteLine(&quot;This is error trace entry&quot;, &quot;Error&quot;);//Will BE transferred.
                Trace.WriteLine(&quot;This is critical trace entry&quot;, &quot;Critical&quot;);//Will BE transferred.
            }
        }

        public override bool OnStart()
        {
            // Set the maximum number of concurrent connections 
            ServicePointManager.DefaultConnectionLimit = 12;

            // For information on handling configuration changes
            // see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.

            return base.OnStart();
        }
    }
}
</pre>
</p>
<p>
Nothing special really. One thing you’ll notice in the OnStart() method is that I’ve not included initialization code for diagnostics. In prior versions of the SDK, I would need to add the following 2 lines of code for diagnostics to work:
</p>
<p><pre class="brush: plain; title: ; notranslate">
            DiagnosticMonitorConfiguration config = DiagnosticMonitor.GetDefaultInitialConfiguration();
            DiagnosticMonitor.Start(&quot;Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString&quot;, config); 
</pre>
</p>
<p>
And this is how my configuration file looks like. If you notice, there’s no diagnostics connection string there.
</p>
<p><pre class="brush: plain; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;ServiceConfiguration serviceName=&quot;WindowsAzure6&quot; 
                      xmlns=&quot;http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration&quot; 
                      osFamily=&quot;3&quot; osVersion=&quot;*&quot; schemaVersion=&quot;2013-03.2.0&quot;&gt;
  &lt;Role name=&quot;WorkerRole1&quot;&gt;
    &lt;Instances count=&quot;1&quot; /&gt;
    &lt;ConfigurationSettings&gt;
    &lt;/ConfigurationSettings&gt;
  &lt;/Role&gt;
&lt;/ServiceConfiguration&gt;
</pre>
</p>
<p>
Let’s publish this cloud service. To ensure Visual Studio is not doing anything “funky”, we’ll just package the file and upload it using <a href="http://www.cerebrata.com/" target="_blank">Azure Management Studio</a>. If you want, you can upload it through the portal as well.
</p>
<p>
Now it’s time to get a bit dramatic <img class="wlEmoticon wlEmoticon-smile" style="border-top-style: none; border-left-style: none; border-bottom-style: none; border-right-style: none" alt="Smile" src="http://gauravmantri.com/wp-content/uploads/2013/05/wlEmoticon-smile1.png" />. For the sake of adding drama to the whole equation, let’s assume that you’re working with a remote team with significant time difference so that you don’t really talk with your remote team in real time but using emails and stuff. The remote team is responsible for the code and deployment and in all their wisdom, they just deployed the service with code as above i.e. with no diagnostics enabled but you don’t know that. Suddenly you start getting calls from your users that the application is running slow and they are not able to do anything there. On top of that, your boss is breathing down your neck to find the problem. Your first reaction is to fire your favorite tools to see diagnostics data to figure out what’s going on but then you realize that your “smart ass remote team <img class="wlEmoticon wlEmoticon-smile" style="border-top-style: none; border-left-style: none; border-bottom-style: none; border-right-style: none" alt="Smile" src="http://gauravmantri.com/wp-content/uploads/2013/05/wlEmoticon-smile1.png" />” forgot to enable diagnostics. Following sections will help you get out of the murky water and make you an office superhero!!! Let’s begin.
</p>
<h3>Step 1: Get the details of diagnostics extension</h3>
<p>
Using the code from my previous <a href="http://gauravmantri.com/2013/05/06/windows-azure-cloud-services-extensions-and-service-management-api-fun-with-remote-desktop/" target="_blank">post</a>, you get the details of diagnostics extension so that you can fetch public and private configuration schema for diagnostics:
</p>
<p><pre class="brush: plain; title: ; notranslate">
            var allExtensions = ListAvailableExtensions(subscriptionId, cert);
            var diagnostics = allExtensions.FirstOrDefault(e =&gt; e.Type == &quot;Diagnostics&quot;);
</pre>
</p>
<p>
<b>Public Configuration Schema:</b>
</p>
<p><pre class="brush: plain; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;xs:schema id=&quot;DiagnosticsConfigSchema&quot;    targetNamespace=&quot;http://schemas.microsoft.com/ServiceHosting/2010/10/DiagnosticsConfiguration&quot;    elementFormDefault=&quot;qualified&quot;    xmlns=&quot;http://schemas.microsoft.com/ServiceHosting/2010/10/DiagnosticsConfiguration&quot;    xmlns:mstns=&quot;http://tempuri.org/XMLSchema.xsd&quot;    xmlns:xs=&quot;http://www.w3.org/2001/XMLSchema&quot;&gt;
  &lt;xs:simpleType name=&quot;PositiveDuration&quot;&gt;
    &lt;xs:restriction base=&quot;xs:duration&quot;&gt;
      &lt;xs:minInclusive value=&quot;PT0S&quot; /&gt;
    &lt;/xs:restriction&gt;
  &lt;/xs:simpleType&gt;
  &lt;xs:simpleType name=&quot;LogLevel&quot;&gt;
    &lt;xs:restriction base=&quot;xs:string&quot;&gt;
      &lt;xs:enumeration value=&quot;Undefined&quot; /&gt;
      &lt;xs:enumeration value=&quot;Verbose&quot; /&gt;
      &lt;xs:enumeration value=&quot;Information&quot; /&gt;
      &lt;xs:enumeration value=&quot;Warning&quot; /&gt;
      &lt;xs:enumeration value=&quot;Error&quot; /&gt;
      &lt;xs:enumeration value=&quot;Critical&quot; /&gt;
    &lt;/xs:restriction&gt;
  &lt;/xs:simpleType&gt;
  &lt;xs:simpleType name=&quot;ContainerName&quot;&gt;
    &lt;xs:restriction base=&quot;xs:string&quot;&gt;
      &lt;xs:pattern value=&quot;[a-z0-9][a-z0-9\-]{1,61}[a-z0-9]&quot; /&gt;
    &lt;/xs:restriction&gt;
  &lt;/xs:simpleType&gt;
  &lt;xs:simpleType name=&quot;AbsolutePathWithEnvironmentExpansion&quot;&gt;
    &lt;xs:restriction base=&quot;xs:string&quot;&gt;
      &lt;xs:pattern value=&quot;([a-zA-Z]:\\)?([^&amp;lt;&amp;gt;:&amp;quot;/|?*]+)*(\\)?&quot; /&gt;
    &lt;/xs:restriction&gt;
  &lt;/xs:simpleType&gt;
  &lt;xs:simpleType name=&quot;RelativePathWithEnvironmentExpansion&quot;&gt;
    &lt;xs:restriction base=&quot;xs:string&quot;&gt;
      &lt;xs:pattern value=&quot;([^&amp;lt;&amp;gt;:&amp;quot;/\\|?*]+)(\\([^&amp;lt;&amp;gt;:&amp;quot;/\\|?*]+))*(\\)?&quot; /&gt;
    &lt;/xs:restriction&gt;
  &lt;/xs:simpleType&gt;
  &lt;xs:simpleType name=&quot;PerformanceCounterPath&quot;&gt;
    &lt;xs:restriction base=&quot;xs:string&quot;&gt;
      &lt;xs:pattern value=&quot;\\[^\\()/#*]+(\(([^\\()#*]+|[^\\()#*]+/[^\\()#*]+|[^\\()#*]+#[^\\()#*]+|[^\\()#*]+/[^\\()#*]+#[^\\()#*]+|\*)\))?\\[^\\()*]+&quot; /&gt;
    &lt;/xs:restriction&gt;
  &lt;/xs:simpleType&gt;
  &lt;xs:simpleType name=&quot;NamedElementNameString&quot;&gt;
    &lt;xs:restriction base=&quot;xs:string&quot;&gt;
      &lt;xs:pattern value=&quot;^[a-zA-Z_][^\\\/\:\*\?\&amp;quot;\&amp;lt;\&amp;gt;\|]*(?&amp;lt;![\.\s])$&quot; /&gt;
    &lt;/xs:restriction&gt;
  &lt;/xs:simpleType&gt;
  &lt;xs:attributeGroup name=&quot;BasicConfiguration&quot;&gt;
    &lt;xs:attribute name=&quot;bufferQuotaInMB&quot; type=&quot;xs:unsignedInt&quot; use=&quot;optional&quot; default=&quot;0&quot;&gt;
      &lt;xs:annotation&gt;
        &lt;xs:documentation&gt;          The maximum amount of file system storage allocated for the specified data.        &lt;/xs:documentation&gt;
      &lt;/xs:annotation&gt;
    &lt;/xs:attribute&gt;
    &lt;xs:attribute name=&quot;scheduledTransferPeriod&quot; type=&quot;PositiveDuration&quot; use=&quot;optional&quot; default=&quot;PT0S&quot;&gt;
      &lt;xs:annotation&gt;
        &lt;xs:documentation&gt;          The interval between scheduled transfers for this data, rounded up to the nearest minute.        &lt;/xs:documentation&gt;
      &lt;/xs:annotation&gt;
    &lt;/xs:attribute&gt;
  &lt;/xs:attributeGroup&gt;
  &lt;xs:attributeGroup name=&quot;LogLevel&quot;&gt;
    &lt;xs:attribute name=&quot;scheduledTransferLogLevelFilter&quot; type=&quot;LogLevel&quot; use=&quot;optional&quot; default=&quot;Undefined&quot;&gt;
      &lt;xs:annotation&gt;
        &lt;xs:documentation&gt;          The minimum log severity to transfer.        &lt;/xs:documentation&gt;
      &lt;/xs:annotation&gt;
    &lt;/xs:attribute&gt;
  &lt;/xs:attributeGroup&gt;
  &lt;xs:attributeGroup name=&quot;DirectoryAttributes&quot;&gt;
    &lt;xs:attribute name=&quot;container&quot; type=&quot;ContainerName&quot; use=&quot;required&quot;&gt;
      &lt;xs:annotation&gt;
        &lt;xs:documentation&gt;          The name of the container where the content of the directory is to be transferred.        &lt;/xs:documentation&gt;
      &lt;/xs:annotation&gt;
    &lt;/xs:attribute&gt;
    &lt;xs:attribute name=&quot;directoryQuotaInMB&quot; type=&quot;xs:unsignedInt&quot; use=&quot;optional&quot; default=&quot;0&quot;&gt;
      &lt;xs:annotation&gt;
        &lt;xs:documentation&gt;          The maximum size of the directory in megabytes.        &lt;/xs:documentation&gt;
      &lt;/xs:annotation&gt;
    &lt;/xs:attribute&gt;
  &lt;/xs:attributeGroup&gt;
  &lt;xs:complexType name=&quot;LogsBase&quot;&gt;
    &lt;xs:attributeGroup ref=&quot;BasicConfiguration&quot; /&gt;
  &lt;/xs:complexType&gt;
  &lt;xs:complexType name=&quot;DiagnosticInfrastructureLogs&quot;&gt;
    &lt;xs:complexContent&gt;
      &lt;xs:extension base=&quot;LogsBase&quot;&gt;
        &lt;xs:attributeGroup ref=&quot;LogLevel&quot; /&gt;
      &lt;/xs:extension&gt;
    &lt;/xs:complexContent&gt;
  &lt;/xs:complexType&gt;
  &lt;xs:complexType name=&quot;DirectoryBase&quot; /&gt;
  &lt;xs:complexType name=&quot;DirectoryAbsolute&quot;&gt;
    &lt;xs:complexContent&gt;
      &lt;xs:extension base=&quot;DirectoryBase&quot;&gt;
        &lt;xs:attribute name=&quot;path&quot; type=&quot;AbsolutePathWithEnvironmentExpansion&quot; use=&quot;required&quot;&gt;
          &lt;xs:annotation&gt;
            &lt;xs:documentation&gt;              The absolute path to the directory to monitor.            &lt;/xs:documentation&gt;
          &lt;/xs:annotation&gt;
        &lt;/xs:attribute&gt;
        &lt;xs:attribute name=&quot;expandEnvironment&quot; type=&quot;xs:boolean&quot; use=&quot;required&quot;&gt;
          &lt;xs:annotation&gt;
            &lt;xs:documentation&gt;              If true, then environment variables in the path will be expanded.            &lt;/xs:documentation&gt;
          &lt;/xs:annotation&gt;
        &lt;/xs:attribute&gt;
      &lt;/xs:extension&gt;
    &lt;/xs:complexContent&gt;
  &lt;/xs:complexType&gt;
  &lt;xs:complexType name=&quot;DirectoryLocalResource&quot;&gt;
    &lt;xs:complexContent&gt;
      &lt;xs:extension base=&quot;DirectoryBase&quot;&gt;
        &lt;xs:attribute name=&quot;relativePath&quot; type=&quot;RelativePathWithEnvironmentExpansion&quot; use=&quot;required&quot;&gt;
          &lt;xs:annotation&gt;
            &lt;xs:documentation&gt;              The path relative to the local resource to monitor.            &lt;/xs:documentation&gt;
          &lt;/xs:annotation&gt;
        &lt;/xs:attribute&gt;
        &lt;xs:attribute name=&quot;name&quot; type=&quot;NamedElementNameString&quot; use=&quot;required&quot;&gt;
          &lt;xs:annotation&gt;
            &lt;xs:documentation&gt;              The local resource that contains the directory to monitor.            &lt;/xs:documentation&gt;
          &lt;/xs:annotation&gt;
        &lt;/xs:attribute&gt;
      &lt;/xs:extension&gt;
    &lt;/xs:complexContent&gt;
  &lt;/xs:complexType&gt;
  &lt;xs:complexType name=&quot;DirectoryConfiguration&quot;&gt;
    &lt;xs:choice&gt;
      &lt;xs:element name=&quot;Absolute&quot; type=&quot;DirectoryAbsolute&quot;&gt;
        &lt;xs:annotation&gt;
          &lt;xs:documentation&gt;            The absolute path to the directory to monitor.          &lt;/xs:documentation&gt;
        &lt;/xs:annotation&gt;
      &lt;/xs:element&gt;
      &lt;xs:element name=&quot;LocalResource&quot; type=&quot;DirectoryLocalResource&quot;&gt;
        &lt;xs:annotation&gt;
          &lt;xs:documentation&gt;            The path relative to a local resource to monitor.          &lt;/xs:documentation&gt;
        &lt;/xs:annotation&gt;
      &lt;/xs:element&gt;
    &lt;/xs:choice&gt;
    &lt;xs:attributeGroup ref=&quot;DirectoryAttributes&quot; /&gt;
  &lt;/xs:complexType&gt;
  &lt;xs:complexType name=&quot;SpecialLogDirectory&quot;&gt;
    &lt;xs:attributeGroup ref=&quot;DirectoryAttributes&quot; /&gt;
  &lt;/xs:complexType&gt;
  &lt;xs:complexType name=&quot;DataSources&quot;&gt;
    &lt;xs:sequence maxOccurs=&quot;unbounded&quot;&gt;
      &lt;xs:element name=&quot;DirectoryConfiguration&quot; type=&quot;DirectoryConfiguration&quot; maxOccurs=&quot;unbounded&quot;&gt;
        &lt;xs:annotation&gt;
          &lt;xs:documentation&gt;            The directory of log files to monitor.          &lt;/xs:documentation&gt;
        &lt;/xs:annotation&gt;
      &lt;/xs:element&gt;
    &lt;/xs:sequence&gt;
  &lt;/xs:complexType&gt;
  &lt;xs:complexType name=&quot;Directories&quot;&gt;
    &lt;xs:complexContent&gt;
      &lt;xs:extension base=&quot;LogsBase&quot;&gt;
        &lt;xs:all&gt;
          &lt;xs:element name=&quot;IISLogs&quot; type=&quot;SpecialLogDirectory&quot; minOccurs=&quot;0&quot;&gt;
            &lt;xs:annotation&gt;
              &lt;xs:documentation&gt;                The IIS log directory.              &lt;/xs:documentation&gt;
            &lt;/xs:annotation&gt;
          &lt;/xs:element&gt;
          &lt;xs:element name=&quot;FailedRequestLogs&quot; type=&quot;SpecialLogDirectory&quot; minOccurs=&quot;0&quot;&gt;
            &lt;xs:annotation&gt;
              &lt;xs:documentation&gt;                The failed request log directory.              &lt;/xs:documentation&gt;
            &lt;/xs:annotation&gt;
          &lt;/xs:element&gt;
          &lt;xs:element name=&quot;CrashDumps&quot; type=&quot;SpecialLogDirectory&quot; minOccurs=&quot;0&quot;&gt;
            &lt;xs:annotation&gt;
              &lt;xs:documentation&gt;                The crash dump directory.              &lt;/xs:documentation&gt;
            &lt;/xs:annotation&gt;
          &lt;/xs:element&gt;
          &lt;xs:element name=&quot;DataSources&quot; type=&quot;DataSources&quot; minOccurs=&quot;0&quot;&gt;
            &lt;xs:annotation&gt;
              &lt;xs:documentation&gt;                Additional log directories.              &lt;/xs:documentation&gt;
            &lt;/xs:annotation&gt;
          &lt;/xs:element&gt;
        &lt;/xs:all&gt;
      &lt;/xs:extension&gt;
    &lt;/xs:complexContent&gt;
  &lt;/xs:complexType&gt;
  &lt;xs:complexType name=&quot;Logs&quot;&gt;
    &lt;xs:complexContent&gt;
      &lt;xs:extension base=&quot;LogsBase&quot;&gt;
        &lt;xs:attributeGroup ref=&quot;LogLevel&quot; /&gt;
      &lt;/xs:extension&gt;
    &lt;/xs:complexContent&gt;
  &lt;/xs:complexType&gt;
  &lt;xs:complexType name=&quot;PerformanceCounterConfiguration&quot;&gt;
    &lt;xs:attribute name=&quot;counterSpecifier&quot; type=&quot;PerformanceCounterPath&quot; use=&quot;required&quot;&gt;
      &lt;xs:annotation&gt;
        &lt;xs:documentation&gt;          The path to the performance counter to collect.        &lt;/xs:documentation&gt;
      &lt;/xs:annotation&gt;
    &lt;/xs:attribute&gt;
    &lt;xs:attribute name=&quot;sampleRate&quot; type=&quot;PositiveDuration&quot; use=&quot;required&quot;&gt;
      &lt;xs:annotation&gt;
        &lt;xs:documentation&gt;          The rate at which the performance counter should be sampled.        &lt;/xs:documentation&gt;
      &lt;/xs:annotation&gt;
    &lt;/xs:attribute&gt;
  &lt;/xs:complexType&gt;
  &lt;xs:complexType name=&quot;PerformanceCounters&quot;&gt;
    &lt;xs:complexContent&gt;
      &lt;xs:extension base=&quot;LogsBase&quot;&gt;
        &lt;xs:sequence maxOccurs=&quot;unbounded&quot;&gt;
          &lt;xs:element name=&quot;PerformanceCounterConfiguration&quot; type=&quot;PerformanceCounterConfiguration&quot;&gt;
            &lt;xs:annotation&gt;
              &lt;xs:documentation&gt;                The performance counter to collect.              &lt;/xs:documentation&gt;
            &lt;/xs:annotation&gt;
          &lt;/xs:element&gt;
        &lt;/xs:sequence&gt;
      &lt;/xs:extension&gt;
    &lt;/xs:complexContent&gt;
  &lt;/xs:complexType&gt;
  &lt;xs:complexType name=&quot;DataSource&quot;&gt;
    &lt;xs:attribute name=&quot;name&quot; type=&quot;xs:string&quot; use=&quot;required&quot;&gt;
      &lt;xs:annotation&gt;
        &lt;xs:documentation&gt;          An XPath expression specifying the logs to collect.        &lt;/xs:documentation&gt;
      &lt;/xs:annotation&gt;
    &lt;/xs:attribute&gt;
  &lt;/xs:complexType&gt;
  &lt;xs:complexType name=&quot;WindowsEventLog&quot;&gt;
    &lt;xs:complexContent&gt;
      &lt;xs:extension base=&quot;LogsBase&quot;&gt;
        &lt;xs:sequence maxOccurs=&quot;unbounded&quot;&gt;
          &lt;xs:element name=&quot;DataSource&quot; type=&quot;DataSource&quot;&gt;
            &lt;xs:annotation&gt;
              &lt;xs:documentation&gt;                The event log to monitor.              &lt;/xs:documentation&gt;
            &lt;/xs:annotation&gt;
          &lt;/xs:element&gt;
        &lt;/xs:sequence&gt;
        &lt;xs:attributeGroup ref=&quot;LogLevel&quot; /&gt;
      &lt;/xs:extension&gt;
    &lt;/xs:complexContent&gt;
  &lt;/xs:complexType&gt;
  &lt;xs:complexType name=&quot;DiagnosticMonitorConfiguration&quot;&gt;
    &lt;xs:all&gt;
      &lt;xs:element name=&quot;DiagnosticInfrastructureLogs&quot; type=&quot;DiagnosticInfrastructureLogs&quot; minOccurs=&quot;0&quot;&gt;
        &lt;xs:annotation&gt;
          &lt;xs:documentation&gt;            Configures the logs generated by the underlying diagnostics infrastructure. The diagnostic infrastructure logs are useful for troubleshooting the diagnostics system itself.          &lt;/xs:documentation&gt;
        &lt;/xs:annotation&gt;
      &lt;/xs:element&gt;
      &lt;xs:element name=&quot;Directories&quot; type=&quot;Directories&quot; minOccurs=&quot;0&quot;&gt;
        &lt;xs:annotation&gt;
          &lt;xs:documentation&gt;            Describes the configuration of a directory to which file-based logs are written.          &lt;/xs:documentation&gt;
        &lt;/xs:annotation&gt;
      &lt;/xs:element&gt;
      &lt;xs:element name=&quot;Logs&quot; type=&quot;Logs&quot; minOccurs=&quot;0&quot;&gt;
        &lt;xs:annotation&gt;
          &lt;xs:documentation&gt;            Configures basic Windows Azure logs.          &lt;/xs:documentation&gt;
        &lt;/xs:annotation&gt;
      &lt;/xs:element&gt;
      &lt;xs:element name=&quot;PerformanceCounters&quot; type=&quot;PerformanceCounters&quot; minOccurs=&quot;0&quot;&gt;
        &lt;xs:annotation&gt;
          &lt;xs:documentation&gt;            Configures performance counter collection.          &lt;/xs:documentation&gt;
        &lt;/xs:annotation&gt;
      &lt;/xs:element&gt;
      &lt;xs:element name=&quot;WindowsEventLog&quot; type=&quot;WindowsEventLog&quot; minOccurs=&quot;0&quot;&gt;
        &lt;xs:annotation&gt;
          &lt;xs:documentation&gt;            Configures Windows event log collection.          &lt;/xs:documentation&gt;
        &lt;/xs:annotation&gt;
      &lt;/xs:element&gt;
    &lt;/xs:all&gt;
    &lt;xs:attribute name=&quot;configurationChangePollInterval&quot; type=&quot;PositiveDuration&quot; use=&quot;optional&quot; default=&quot;PT1M&quot;&gt;
      &lt;xs:annotation&gt;
        &lt;xs:documentation&gt;          The interval at which the diagnostic monitor polls for configuration changes.        &lt;/xs:documentation&gt;
      &lt;/xs:annotation&gt;
    &lt;/xs:attribute&gt;
    &lt;xs:attribute name=&quot;overallQuotaInMB&quot; type=&quot;xs:unsignedInt&quot; use=&quot;optional&quot; default=&quot;4000&quot;&gt;
      &lt;xs:annotation&gt;
        &lt;xs:documentation&gt;          The total amount of file system storage allocated for all logging buffers.        &lt;/xs:documentation&gt;
      &lt;/xs:annotation&gt;
    &lt;/xs:attribute&gt;
  &lt;/xs:complexType&gt;
  &lt;xs:complexType name=&quot;StorageAccount&quot;&gt;
    &lt;xs:all&gt;
      &lt;xs:element name=&quot;Name&quot; type=&quot;xs:string&quot; minOccurs=&quot;0&quot; maxOccurs=&quot;1&quot; /&gt;
      &lt;xs:element name=&quot;DefaultEndpointsProtocol&quot; type=&quot;xs:string&quot; minOccurs=&quot;0&quot; maxOccurs=&quot;1&quot; default=&quot;https&quot; /&gt;
      &lt;xs:element name=&quot;ConnectionQualifiers&quot; type=&quot;xs:string&quot; minOccurs=&quot;0&quot; maxOccurs=&quot;1&quot; /&gt;
    &lt;/xs:all&gt;
  &lt;/xs:complexType&gt;
  &lt;xs:element name=&quot;PublicConfig&quot;&gt;
    &lt;xs:complexType&gt;
      &lt;xs:all&gt;
        &lt;xs:element name=&quot;WadCfg&quot;&gt;
          &lt;xs:complexType&gt;
            &lt;xs:sequence&gt;
              &lt;xs:element name=&quot;DiagnosticMonitorConfiguration&quot; type=&quot;DiagnosticMonitorConfiguration&quot; minOccurs=&quot;0&quot; maxOccurs=&quot;1&quot;/&gt;
            &lt;/xs:sequence&gt;
          &lt;/xs:complexType&gt;
        &lt;/xs:element&gt;
        &lt;xs:element name=&quot;StorageAccount&quot; type=&quot;StorageAccount&quot; minOccurs=&quot;1&quot; /&gt;
      &lt;/xs:all&gt;
    &lt;/xs:complexType&gt;
  &lt;/xs:element&gt;
&lt;/xs:schema&gt;
</pre>
</p>
<p>
<b>Private Configuration Schema:</b>
</p>
<p><pre class="brush: plain; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;xs:schema attributeFormDefault=&quot;unqualified&quot; elementFormDefault=&quot;qualified&quot; xmlns:xs=&quot;http://www.w3.org/2001/XMLSchema&quot;&gt;
  &lt;xs:element name=&quot;PrivateConfig&quot;&gt;
    &lt;xs:complexType&gt;
      &lt;xs:sequence&gt;
        &lt;xs:element name=&quot;StorageKey&quot; type=&quot;xs:string&quot; /&gt;
      &lt;/xs:sequence&gt;
    &lt;/xs:complexType&gt;
  &lt;/xs:element&gt;
&lt;/xs:schema&gt;
</pre>
</p>
<p>
Based on these, you can generate XML template for public and private configurations.
</p>
<p>
<b>Public Configuration XML Template:</b>
</p>
<p><pre class="brush: plain; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;PublicConfig xmlns=&quot;http://schemas.microsoft.com/ServiceHosting/2010/10/DiagnosticsConfiguration&quot;&gt;
  &lt;StorageAccount&gt;
    &lt;ConnectionQualifiers&gt;ConnectionQualifiers1&lt;/ConnectionQualifiers&gt;
    &lt;DefaultEndpointsProtocol&gt;https&lt;/DefaultEndpointsProtocol&gt;
    &lt;Name&gt;Name1&lt;/Name&gt;
  &lt;/StorageAccount&gt;
  &lt;WadCfg&gt;
    &lt;DiagnosticMonitorConfiguration configurationChangePollInterval=&quot;PT1M&quot; overallQuotaInMB=&quot;4000&quot;&gt;
      &lt;WindowsEventLog scheduledTransferLogLevelFilter=&quot;Undefined&quot; bufferQuotaInMB=&quot;0&quot; scheduledTransferPeriod=&quot;PT0S&quot;&gt;
        &lt;DataSource name=&quot;name1&quot; /&gt;
        &lt;DataSource name=&quot;name2&quot; /&gt;
        &lt;DataSource name=&quot;name3&quot; /&gt;
      &lt;/WindowsEventLog&gt;
      &lt;PerformanceCounters bufferQuotaInMB=&quot;0&quot; scheduledTransferPeriod=&quot;PT0S&quot;&gt;
        &lt;PerformanceCounterConfiguration counterSpecifier=&quot;counterSpecifier1&quot; sampleRate=&quot;PT0S&quot; /&gt;
        &lt;PerformanceCounterConfiguration counterSpecifier=&quot;counterSpecifier2&quot; sampleRate=&quot;P10675199DT2H48M5.477S&quot; /&gt;
        &lt;PerformanceCounterConfiguration counterSpecifier=&quot;counterSpecifier3&quot; sampleRate=&quot;P365D&quot; /&gt;
      &lt;/PerformanceCounters&gt;
      &lt;Logs scheduledTransferLogLevelFilter=&quot;Undefined&quot; bufferQuotaInMB=&quot;0&quot; scheduledTransferPeriod=&quot;PT0S&quot; /&gt;
      &lt;Directories bufferQuotaInMB=&quot;0&quot; scheduledTransferPeriod=&quot;PT0S&quot;&gt;
        &lt;DataSources&gt;
          &lt;DirectoryConfiguration container=&quot;container1&quot; directoryQuotaInMB=&quot;0&quot;&gt;
            &lt;Absolute path=&quot;path1&quot; expandEnvironment=&quot;true&quot; /&gt;
          &lt;/DirectoryConfiguration&gt;
          &lt;DirectoryConfiguration container=&quot;container2&quot; directoryQuotaInMB=&quot;0&quot;&gt;
            &lt;Absolute path=&quot;path2&quot; expandEnvironment=&quot;false&quot; /&gt;
          &lt;/DirectoryConfiguration&gt;
          &lt;DirectoryConfiguration container=&quot;container3&quot; directoryQuotaInMB=&quot;4294967295&quot;&gt;
            &lt;Absolute path=&quot;path3&quot; expandEnvironment=&quot;true&quot; /&gt;
          &lt;/DirectoryConfiguration&gt;
          &lt;DirectoryConfiguration container=&quot;container4&quot; directoryQuotaInMB=&quot;1&quot;&gt;
            &lt;Absolute path=&quot;path4&quot; expandEnvironment=&quot;false&quot; /&gt;
          &lt;/DirectoryConfiguration&gt;
          &lt;DirectoryConfiguration container=&quot;container5&quot; directoryQuotaInMB=&quot;4294967294&quot;&gt;
            &lt;Absolute path=&quot;path5&quot; expandEnvironment=&quot;true&quot; /&gt;
          &lt;/DirectoryConfiguration&gt;
          &lt;DirectoryConfiguration container=&quot;container6&quot; directoryQuotaInMB=&quot;2&quot;&gt;
            &lt;Absolute path=&quot;path6&quot; expandEnvironment=&quot;false&quot; /&gt;
          &lt;/DirectoryConfiguration&gt;
          &lt;DirectoryConfiguration container=&quot;container7&quot; directoryQuotaInMB=&quot;4294967293&quot;&gt;
            &lt;Absolute path=&quot;path7&quot; expandEnvironment=&quot;true&quot; /&gt;
          &lt;/DirectoryConfiguration&gt;
          &lt;DirectoryConfiguration container=&quot;container8&quot; directoryQuotaInMB=&quot;3&quot;&gt;
            &lt;Absolute path=&quot;path8&quot; expandEnvironment=&quot;false&quot; /&gt;
          &lt;/DirectoryConfiguration&gt;
          &lt;DirectoryConfiguration container=&quot;container9&quot; directoryQuotaInMB=&quot;4294967292&quot;&gt;
            &lt;Absolute path=&quot;path9&quot; expandEnvironment=&quot;true&quot; /&gt;
          &lt;/DirectoryConfiguration&gt;
        &lt;/DataSources&gt;
        &lt;CrashDumps container=&quot;container1&quot; directoryQuotaInMB=&quot;0&quot; /&gt;
        &lt;FailedRequestLogs container=&quot;container1&quot; directoryQuotaInMB=&quot;0&quot; /&gt;
        &lt;IISLogs container=&quot;container1&quot; directoryQuotaInMB=&quot;0&quot; /&gt;
      &lt;/Directories&gt;
      &lt;DiagnosticInfrastructureLogs scheduledTransferLogLevelFilter=&quot;Undefined&quot; bufferQuotaInMB=&quot;0&quot; scheduledTransferPeriod=&quot;PT0S&quot; /&gt;
    &lt;/DiagnosticMonitorConfiguration&gt;
  &lt;/WadCfg&gt;
&lt;/PublicConfig&gt;
</pre>
</p>
<p>
<b>Private Configuration XML Template:</b>
</p>
<p><pre class="brush: plain; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;PrivateConfig&gt;
  &lt;StorageKey&gt;StorageKey1&lt;/StorageKey&gt;
&lt;/PrivateConfig&gt;
</pre>
</p>
<h3>Step 2: Create XML files</h3>
<p>
Using the templates from the previous steps, we create public and private configuration XML files. Let’s assume that we’re only interested in capturing all trace log entries, “Application” event logs and 2 performance counters – “\Processor(_Total)\% Processor Time” and “\Memory\Available Mbytes”. Based on this, this is how our XML files look like:
</p>
<p>
<b>Public Configuration XML:</b>
</p>
<p><pre class="brush: plain; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;PublicConfig xmlns=&quot;http://schemas.microsoft.com/ServiceHosting/2010/10/DiagnosticsConfiguration&quot;&gt;
  &lt;StorageAccount&gt;
    &lt;ConnectionQualifiers/&gt;
    &lt;DefaultEndpointsProtocol&gt;https&lt;/DefaultEndpointsProtocol&gt;
    &lt;Name&gt;[your storage account name]&lt;/Name&gt;
  &lt;/StorageAccount&gt;
  &lt;WadCfg&gt;
    &lt;DiagnosticMonitorConfiguration configurationChangePollInterval=&quot;PT1M&quot; overallQuotaInMB=&quot;4096&quot;&gt;
      &lt;DiagnosticInfrastructureLogs /&gt;
      &lt;Directories&gt;
        &lt;IISLogs container=&quot;wad-iis-logfiles&quot; /&gt;
        &lt;CrashDumps container=&quot;wad-crash-dumps&quot; /&gt;
      &lt;/Directories&gt;
      &lt;Logs bufferQuotaInMB=&quot;1024&quot; scheduledTransferPeriod=&quot;PT1M&quot; scheduledTransferLogLevelFilter=&quot;Verbose&quot; /&gt;
      &lt;PerformanceCounters bufferQuotaInMB=&quot;1024&quot; scheduledTransferPeriod=&quot;PT1M&quot;&gt;
        &lt;PerformanceCounterConfiguration counterSpecifier=&quot;\Processor(_Total)\% Processor Time&quot; sampleRate=&quot;PT1S&quot; /&gt;
        &lt;PerformanceCounterConfiguration counterSpecifier=&quot;\Memory\Available MBytes&quot; sampleRate=&quot;PT1S&quot; /&gt;
      &lt;/PerformanceCounters&gt;
      &lt;WindowsEventLog bufferQuotaInMB=&quot;1024&quot; scheduledTransferPeriod=&quot;PT1M&quot; scheduledTransferLogLevelFilter=&quot;Error&quot;&gt;
        &lt;DataSource name=&quot;Application!*&quot; /&gt;
      &lt;/WindowsEventLog&gt;
    &lt;/DiagnosticMonitorConfiguration&gt;
  &lt;/WadCfg&gt;
&lt;/PublicConfig&gt;
</pre>
</p>
<p>
<b>Private Configuration XML:</b>
</p>
<p><pre class="brush: plain; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;PrivateConfig&gt;
  &lt;StorageKey&gt;[your storage account key]&lt;/StorageKey&gt;
&lt;/PrivateConfig&gt;
</pre>
</p>
<h3>Step 3: Add WAD Extension</h3>
<p>
To add WAD extension, we’ll use public and private key configuration for the extension and add that extension to the cloud service.</p>
<p><pre class="brush: plain; title: ; notranslate">
            string publicConfiguration = @&quot;&lt;?xml version=&quot;&quot;1.0&quot;&quot; encoding=&quot;&quot;utf-8&quot;&quot;?&gt;
                &lt;PublicConfig xmlns=&quot;&quot;http://schemas.microsoft.com/ServiceHosting/2010/10/DiagnosticsConfiguration&quot;&quot;&gt;
                  &lt;StorageAccount&gt;
                    &lt;ConnectionQualifiers/&gt;
                    &lt;DefaultEndpointsProtocol&gt;https&lt;/DefaultEndpointsProtocol&gt;
                    &lt;Name&gt;[your storage account name]&lt;/Name&gt;
                  &lt;/StorageAccount&gt;
                  &lt;WadCfg&gt;
                    &lt;DiagnosticMonitorConfiguration configurationChangePollInterval=&quot;&quot;PT1M&quot;&quot; overallQuotaInMB=&quot;&quot;4096&quot;&quot;&gt;
                      &lt;DiagnosticInfrastructureLogs /&gt;
                      &lt;Directories&gt;
                        &lt;IISLogs container=&quot;&quot;wad-iis-logfiles&quot;&quot; /&gt;
                        &lt;CrashDumps container=&quot;&quot;wad-crash-dumps&quot;&quot; /&gt;
                      &lt;/Directories&gt;
                      &lt;Logs bufferQuotaInMB=&quot;&quot;1024&quot;&quot; scheduledTransferPeriod=&quot;&quot;PT1M&quot;&quot; scheduledTransferLogLevelFilter=&quot;&quot;Verbose&quot;&quot; /&gt;
                      &lt;PerformanceCounters bufferQuotaInMB=&quot;&quot;1024&quot;&quot; scheduledTransferPeriod=&quot;&quot;PT1M&quot;&quot;&gt;
                        &lt;PerformanceCounterConfiguration counterSpecifier=&quot;&quot;\Processor(_Total)\% Processor Time&quot;&quot; sampleRate=&quot;&quot;PT1S&quot;&quot; /&gt;
                        &lt;PerformanceCounterConfiguration counterSpecifier=&quot;&quot;\Memory\Available MBytes&quot;&quot; sampleRate=&quot;&quot;PT1S&quot;&quot; /&gt;
                      &lt;/PerformanceCounters&gt;
                      &lt;WindowsEventLog bufferQuotaInMB=&quot;&quot;1024&quot;&quot; scheduledTransferPeriod=&quot;&quot;PT1M&quot;&quot; scheduledTransferLogLevelFilter=&quot;&quot;Error&quot;&quot;&gt;
                        &lt;DataSource name=&quot;&quot;Application!*&quot;&quot; /&gt;
                      &lt;/WindowsEventLog&gt;
                    &lt;/DiagnosticMonitorConfiguration&gt;
                  &lt;/WadCfg&gt;
                &lt;/PublicConfig&gt;&quot;;

            string privateConfiguration = @&quot;&lt;?xml version=&quot;&quot;1.0&quot;&quot; encoding=&quot;&quot;utf-8&quot;&quot;?&gt;
                &lt;PrivateConfig&gt;
                  &lt;StorageKey&gt;[your storage account key]&lt;/StorageKey&gt;
                &lt;/PrivateConfig&gt;&quot;;

            AzureExtension wadExtension = new AzureExtension()
            {
                ProviderNamespace = &quot;Microsoft.Windows.Azure.Extensions&quot;,
                Type = &quot;Diagnostics&quot;,
                Id = &quot;DiagnosticsExtensionWhichWillSaveMyButt&quot;,
                PublicConfiguration = publicConfiguration,
                PrivateConfiguration = privateConfiguration,
            };

            AddExtension(subscriptionId, cert, cloudServiceName, wadExtension);
</pre>
</p>
<h3>Step 4: Update Configuration</h3>
<p>
Once the extension is added, next step would be to update the cloud service configuration by performing “<a href="http://msdn.microsoft.com/en-us/library/windowsazure/ee460809.aspx">Change Deployment Configuration</a>” operation. For this, first we may need to fetch the current configuration. To do so, we’ll perform “Get Hosted Service Properties” operation and try to get both production and staging configuration settings. Here’s the sample code to get the configuration settings:
</p>
<p><pre class="brush: plain; title: ; notranslate">
        private static string[] GetCloudServiceDeploymentConfigurations(string subscriptionId, X509Certificate2 cert, string cloudServiceName)
        {
            string[] deploymentConfigurations = new string[2];//We'll try to get both production and staging deployment configurations. The 1st element will always be production and the 2nd will be staging.
            string uri = string.Format(&quot;https://management.core.windows.net/{0}/services/hostedservices/{1}?embed-detail=true&quot;, subscriptionId, cloudServiceName);
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
            request.Method = &quot;GET&quot;;
            request.Headers.Add(&quot;x-ms-version&quot;, &quot;2013-03-01&quot;);
            request.ClientCertificates.Add(cert);
            using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse())
            {
                using (var streamReader = new StreamReader(resp.GetResponseStream()))
                {
                    string result = streamReader.ReadToEnd();
                    XElement cloudServiceProperties = XElement.Parse(result);
                    var deployments = cloudServiceProperties.Elements(XName.Get(&quot;Deployments&quot;, &quot;http://schemas.microsoft.com/windowsazure&quot;));
                    foreach (var deployment in deployments.Elements())
                    {
                        var slotElement = deployment.Element(XName.Get(&quot;DeploymentSlot&quot;, &quot;http://schemas.microsoft.com/windowsazure&quot;));
                        var configElement = deployment.Element(XName.Get(&quot;Configuration&quot;, &quot;http://schemas.microsoft.com/windowsazure&quot;));
                        var deploymentSlot = slotElement.Value;
                        var configurationSettings = Encoding.UTF8.GetString(Convert.FromBase64String(configElement.Value));
                        switch (deploymentSlot.ToUpper())
                        {
                            case &quot;PRODUCTION&quot;:
                                deploymentConfigurations[0] = configurationSettings;
                                break;
                            case &quot;STAGING&quot;:
                                deploymentConfigurations[1] = configurationSettings;
                                break;
                        }
                    }
                }
            }
            return deploymentConfigurations;
        }
</pre>
</p>
<p>
Now that we’ve got the configurations for both production and staging slots, let’s apply the changes. Here’s the sample code for change deployment configuration operation:
</p>
<p><pre class="brush: plain; title: ; notranslate">
        private static void ChangeDeploymentConfiguration(string subscriptionId, X509Certificate2 cert, string cloudServiceName, string slot, string configuration)
        {
            try
            {
                string uri = string.Format(&quot;https://management.core.windows.net/{0}/services/hostedservices/{1}/deploymentslots/{2}/?comp=config&quot;, subscriptionId, cloudServiceName, slot);
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
                request.Method = &quot;POST&quot;;
                request.ContentType = &quot;application/xml&quot;;
                request.Headers.Add(&quot;x-ms-version&quot;, &quot;2013-03-01&quot;);
                request.ClientCertificates.Add(cert);
                byte[] content = Encoding.UTF8.GetBytes(configuration);
                request.ContentLength = content.Length;
                using (var requestStream = request.GetRequestStream())
                {
                    requestStream.Write(content, 0, content.Length);
                }

                using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse())
                {
                }
            }
            catch (WebException webEx)
            {
                using (var streamReader = new StreamReader(webEx.Response.GetResponseStream()))
                {
                    string result = streamReader.ReadToEnd();
                    Console.WriteLine(result);
                }
            }

        }
</pre>
</p>
<p>
And this is how you call it:
</p>
<p><pre class="brush: plain; title: ; notranslate">
            string updateConfigurationFormat = @&quot;&lt;?xml version=&quot;&quot;1.0&quot;&quot; encoding=&quot;&quot;utf-8&quot;&quot;?&gt;
                &lt;ChangeConfiguration xmlns=&quot;&quot;http://schemas.microsoft.com/windowsazure&quot;&quot;&gt;
                  &lt;Configuration&gt;{0}&lt;/Configuration&gt;
                &lt;ExtensionConfiguration&gt;
                    &lt;AllRoles&gt;
                      &lt;Extension&gt;
                        &lt;Id&gt;{1}&lt;/Id&gt;
                      &lt;/Extension&gt;
                    &lt;/AllRoles&gt;
                 &lt;/ExtensionConfiguration&gt;
                &lt;/ChangeConfiguration&gt;&quot;;

            var productionConfig = configurations[0];
            if (!string.IsNullOrWhiteSpace(productionConfig))
            {
                var productionConfigurationSetting = string.Format(updateConfigurationFormat, Convert.ToBase64String(Encoding.UTF8.GetBytes(productionConfig)), wadExtension.Id);
                ChangeDeploymentConfiguration(subscriptionId, cert, cloudServiceName, &quot;Production&quot;, productionConfigurationSetting);
            }
</pre>
</p>
<p>
Putting it all together nicely in just one function:
</p>
<p><pre class="brush: plain; title: ; notranslate">
        private static void AddDiagnosticsExtension(string subscriptionId, X509Certificate2 cert, string cloudServiceName)
        {
            string publicConfiguration = @&quot;&lt;?xml version=&quot;&quot;1.0&quot;&quot; encoding=&quot;&quot;utf-8&quot;&quot;?&gt;
                &lt;PublicConfig xmlns=&quot;&quot;http://schemas.microsoft.com/ServiceHosting/2010/10/DiagnosticsConfiguration&quot;&quot;&gt;
                  &lt;StorageAccount&gt;
                    &lt;ConnectionQualifiers/&gt;
                    &lt;DefaultEndpointsProtocol&gt;https&lt;/DefaultEndpointsProtocol&gt;
                    &lt;Name&gt;[your storage account name]&lt;/Name&gt;
                  &lt;/StorageAccount&gt;
                  &lt;WadCfg&gt;
                    &lt;DiagnosticMonitorConfiguration configurationChangePollInterval=&quot;&quot;PT1M&quot;&quot; overallQuotaInMB=&quot;&quot;4096&quot;&quot;&gt;
                      &lt;DiagnosticInfrastructureLogs /&gt;
                      &lt;Directories&gt;
                        &lt;IISLogs container=&quot;&quot;wad-iis-logfiles&quot;&quot; /&gt;
                        &lt;CrashDumps container=&quot;&quot;wad-crash-dumps&quot;&quot; /&gt;
                      &lt;/Directories&gt;
                      &lt;Logs bufferQuotaInMB=&quot;&quot;1024&quot;&quot; scheduledTransferPeriod=&quot;&quot;PT1M&quot;&quot; scheduledTransferLogLevelFilter=&quot;&quot;Verbose&quot;&quot; /&gt;
                      &lt;PerformanceCounters bufferQuotaInMB=&quot;&quot;1024&quot;&quot; scheduledTransferPeriod=&quot;&quot;PT1M&quot;&quot;&gt;
                        &lt;PerformanceCounterConfiguration counterSpecifier=&quot;&quot;\Processor(_Total)\% Processor Time&quot;&quot; sampleRate=&quot;&quot;PT1S&quot;&quot; /&gt;
                        &lt;PerformanceCounterConfiguration counterSpecifier=&quot;&quot;\Memory\Available MBytes&quot;&quot; sampleRate=&quot;&quot;PT1S&quot;&quot; /&gt;
                      &lt;/PerformanceCounters&gt;
                      &lt;WindowsEventLog bufferQuotaInMB=&quot;&quot;1024&quot;&quot; scheduledTransferPeriod=&quot;&quot;PT1M&quot;&quot; scheduledTransferLogLevelFilter=&quot;&quot;Error&quot;&quot;&gt;
                        &lt;DataSource name=&quot;&quot;Application!*&quot;&quot; /&gt;
                      &lt;/WindowsEventLog&gt;
                    &lt;/DiagnosticMonitorConfiguration&gt;
                  &lt;/WadCfg&gt;
                &lt;/PublicConfig&gt;&quot;;

            string privateConfiguration = @&quot;&lt;?xml version=&quot;&quot;1.0&quot;&quot; encoding=&quot;&quot;utf-8&quot;&quot;?&gt;
                &lt;PrivateConfig&gt;
                  &lt;StorageKey&gt;[your storage account key]&lt;/StorageKey&gt;
                &lt;/PrivateConfig&gt;&quot;;

            string updateConfigurationFormat = @&quot;&lt;?xml version=&quot;&quot;1.0&quot;&quot; encoding=&quot;&quot;utf-8&quot;&quot;?&gt;
                &lt;ChangeConfiguration xmlns=&quot;&quot;http://schemas.microsoft.com/windowsazure&quot;&quot;&gt;
                  &lt;Configuration&gt;{0}&lt;/Configuration&gt;
                &lt;ExtensionConfiguration&gt;
                    &lt;AllRoles&gt;
                      &lt;Extension&gt;
                        &lt;Id&gt;{1}&lt;/Id&gt;
                      &lt;/Extension&gt;
                    &lt;/AllRoles&gt;
                 &lt;/ExtensionConfiguration&gt;
                &lt;/ChangeConfiguration&gt;&quot;;

            AzureExtension wadExtension = new AzureExtension()
            {
                ProviderNamespace = &quot;Microsoft.Windows.Azure.Extensions&quot;,
                Type = &quot;Diagnostics&quot;,
                Id = &quot;DiagnosticsExtensionWhichWillSaveMyButt&quot;,
                PublicConfiguration = publicConfiguration,
                PrivateConfiguration = privateConfiguration,
            };

            AddExtension(subscriptionId, cert, cloudServiceName, wadExtension);

            var configurations = GetCloudServiceDeploymentConfigurations(subscriptionId, cert, cloudServiceName);
            var productionConfig = configurations[0];
            if (!string.IsNullOrWhiteSpace(productionConfig))
            {
                var productionConfigurationSetting = string.Format(updateConfigurationFormat, Convert.ToBase64String(Encoding.UTF8.GetBytes(productionConfig)), wadExtension.Id);
                ChangeDeploymentConfiguration(subscriptionId, cert, cloudServiceName, &quot;Production&quot;, productionConfigurationSetting);
            }
            var stagingConfig = configurations[1];
            if (!string.IsNullOrWhiteSpace(stagingConfig))
            {
                var stagingConfigurationSetting = string.Format(updateConfigurationFormat, Convert.ToBase64String(Encoding.UTF8.GetBytes(stagingConfig)), wadExtension.Id);
                ChangeDeploymentConfiguration(subscriptionId, cert, cloudServiceName, &quot;Staging&quot;, stagingConfigurationSetting);
            }
        }
</pre>
</p>
<p>
That’s pretty much it!!! Once the operation is complete, you should be able to see the diagnostics data for your cloud service in some time.
</p>
<p>
<a href="http://gauravmantri.com/wp-content/uploads/2013/05/clip_image0029.jpg"><img title="clip_image002[9]" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="clip_image002[9]" src="http://gauravmantri.com/wp-content/uploads/2013/05/clip_image0029_thumb.jpg" width="810" height="415" /></a>
</p>
<h2>Summary</h2>
<p>
I strongly believe that changes done to diagnostics in SDK 2.0 are pretty significant. From my personal experience working with various users of Cerebrata Azure Diagnostics Manager, I do believe that it’s a boon to developers. Now it is very easy and straight forward to configure the diagnostics and change it on the fly. That&#8217;s it for this post. As always, if you find any issues with the post please let me know and I’ll fix it ASAP.
</p>
<p>
Happy Coding!</p>
<img src="http://feeds.feedburner.com/~r/gmantri/~4/dO_393t2KAA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://gauravmantri.com/2013/05/12/windows-azure-sdk-2-0-for-net-taking-a-second-look-at-windows-azure-diagnostics/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://gauravmantri.com/2013/05/12/windows-azure-sdk-2-0-for-net-taking-a-second-look-at-windows-azure-diagnostics/</feedburner:origLink></item>
		<item>
		<title>Windows Azure Cloud Services, Extensions and Service Management API – Fun with Remote Desktop</title>
		<link>http://feedproxy.google.com/~r/gmantri/~3/2VeyREEELgg/</link>
		<comments>http://gauravmantri.com/2013/05/06/windows-azure-cloud-services-extensions-and-service-management-api-fun-with-remote-desktop/#comments</comments>
		<pubDate>Mon, 06 May 2013 11:47:43 +0000</pubDate>
		<dc:creator>Gaurav</dc:creator>
				<category><![CDATA[Windows Azure]]></category>
		<category><![CDATA[Windows Azure Cloud Service]]></category>
		<category><![CDATA[Windows Azure Service Management API]]></category>
		<category><![CDATA[Cloud Service Extensions]]></category>
		<category><![CDATA[Remote Desktop]]></category>

		<guid isPermaLink="false">http://gauravmantri.com/?p=1244</guid>
		<description><![CDATA[I want you to try something for me (pretty please with cherry on top ). Fire up Visual Studio, create a simple Windows Azure Cloud Service and then without making any changes just publish that service. When you publish the service, DO NOT ENABLE REMOTE DESKTOP! Once the service is deployed, head on to Windows [...]]]></description>
			<content:encoded><![CDATA[<p>I want you to try something for me (pretty please with cherry on top <img class="wlEmoticon wlEmoticon-smile" style="border-style: none;" src="http://gauravmantri.com/wp-content/uploads/2013/05/wlEmoticon-smile.png" alt="Smile" />). Fire up Visual Studio, create a simple Windows Azure Cloud Service and then without making any changes just publish that service. When you publish the service, <strong>DO NOT ENABLE REMOTE DESKTOP!</strong></p>
<p><a href="http://gauravmantri.com/wp-content/uploads/2013/05/image.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="image" src="http://gauravmantri.com/wp-content/uploads/2013/05/image_thumb.png" alt="image" width="810" height="548" border="0" /></a></p>
<p>Once the service is deployed, head on to Windows Azure Portal (<a href="https://manage.windowsazure.com" target="_blank">https://manage.windowsazure.com</a>), navigate to the cloud service you just deployed and click on the “<strong>CONFIGURE</strong>” tab. Once there, just click on the “<strong>REMOTE</strong>” button below. You’ll be greeted with the following screen:</p>
<p><a href="http://gauravmantri.com/wp-content/uploads/2013/05/image1.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="image" src="http://gauravmantri.com/wp-content/uploads/2013/05/image_thumb1.png" alt="image" width="810" height="700" border="0" /></a></p>
<p>Now follow the instructions there and enable remote desktop. Once the process is complete, go to “<strong>INSTANCES</strong>” tab and click on “<strong>CONNECT</strong>” button below. What you’ll notice is that you’re able to RDP into your instances. If you’ve been using Windows Azure for some time, you know that in order to remote desktop into your instances you would have to enable this functionality when you’re publishing the service. If you forgot doing this at the time of deployment, you would need to go through an upgrade or new deployment process just to enable this functionality.</p>
<p>However what you saw just now is that you did not do anything of that sort. You published the service and then enabled this functionality on the fly! So, how did this happen? I’ve got one sentence for you:</p>
<p align="center"><strong>Your Cloud Service just got Extensions!</strong> <img class="wlEmoticon wlEmoticon-smile" style="border-style: none;" src="http://gauravmantri.com/wp-content/uploads/2013/05/wlEmoticon-smile.png" alt="Smile" /></p>
<p>In this blog post, we’ll talk about “<strong>Cloud Services Extensions</strong>”. We’ll talk about what they are, how you can work with them and finally we’ll see some code which will allow you to enable/disable this functionality on the fly.</p>
<p>So, let’s get started!</p>
<h2>Extensions</h2>
<p>Extensions are the newest functionality available through Windows Azure Service Management API. The way I understand it is that <em><strong>extensions allow you to dynamically add/remove some functionality in your cloud services without redeploying your code</strong></em>. At the time of writing this blog, there’re two things which you could do – <strong>Enable/Disable Remote Desktop (RDP)</strong> and <strong>Enable/Disable Windows Azure Diagnostics (WAD)</strong>. Yes, you read it right!! Now you can enable/disable diagnostics for your cloud services on the fly without redeploying your service. No more messy code for diagnostics configuration and trying to remember things. I’ll cover diagnostics in a separate post. For now let’s focus on core extensions functionality.</p>
<p>The way it works today is that Windows Azure team has published some pre-defined extensions and you could enable/disable these extensions in your cloud service using Service Management API. Service Management API has added some functions to work with these extensions. The way the extensions functionality work is that you define settings associated with that extension; some of these settings will be public (i.e. you can fetch them later on e.g. RDP username) while some of the settings are private (i.e. you can’t fetch them after they&#8217;re set e.g. RDP password). You would define public settings in a public configuration file and private settings in a private configuration file. The configuration file are XML files. In order to determine the structure of these XML files, Service Management API exposes relevant schemas (public configuration schema and private configuration schema) using which you can construct XML files. Once the XML configuration files are defined, you can add an extension to your cloud service. However adding an extension does not do any magic. You would need to apply that extension to your cloud service which you can do through “<a href="http://msdn.microsoft.com/en-us/library/windowsazure/ee460809.aspx" target="_blank">Change Deployment Configuration</a>” operation.</p>
<p>In this section we’ll focus on these functions and we’ll put them to practical use in next section. What I did was create a simple console application and defined some classes and methods to work with the extensions.</p>
<p>Based on the data returned by various functions for extensions management, I created a simple class called “<strong>AzureExtension</strong>” and this is what it looks like:</p>
<p><pre class="brush: plain; title: ; notranslate">
    public class AzureExtension
    {
        /// &lt;summary&gt;
        /// The provider namespace of the extension. The provider namespace for 
        /// Windows Azure extensions is Microsoft.WindowsAzure.Extensions.
        /// &lt;/summary&gt;
        public string ProviderNamespace
        {
            get;
            set;
        }

        /// &lt;summary&gt;
        /// The type of the extension e.g. RDP for Remote Desktop.
        /// &lt;/summary&gt;
        public string Type
        {
            get;
            set;
        }

        /// &lt;summary&gt;
        /// The version of the extension.
        /// &lt;/summary&gt;
        public string Version
        {
            get;
            set;
        }

        /// &lt;summary&gt;
        /// The label that is used to identify the extension.
        /// &lt;/summary&gt;
        public string Label
        {
            get;
            set;
        }

        /// &lt;summary&gt;
        /// The description of the extension.
        /// &lt;/summary&gt;
        public string Description
        {
            get;
            set;
        }

        /// &lt;summary&gt;
        /// The type of resource that supports the extension. This value can be 
        /// WebRole, WorkerRole, or WebRole|WorkerRole.
        /// &lt;/summary&gt;
        public string HostingResource
        {
            get;
            set;
        }

        /// &lt;summary&gt;
        /// The thumbprint algorithm of the certificate that is used for encryption.
        /// &lt;/summary&gt;
        public string ThumbprintAlgorithm
        {
            get;
            set;
        }

        /// &lt;summary&gt;
        /// The thumbprint of the certificate that is used to encrypt the configuration specified in PrivateConfiguration. 
        /// If this element is not specified, a certificate may be automatically generated and added to the cloud service.
        /// &lt;/summary&gt;
        public string Thumbprint
        {
            get;
            set;
        }

        /// &lt;summary&gt;
        /// The base64-encoded schema of the public configuration.
        /// &lt;/summary&gt;
        public string PublicConfigurationSchema
        {
            get;
            set;
        }

        /// &lt;summary&gt;
        /// XML configuration based on PublicConfigurationSchema
        /// &lt;/summary&gt;
        public string PublicConfiguration
        {
            get;
            set;
        }

        /// &lt;summary&gt;
        /// The base64-encoded schema of the private configuration.
        /// &lt;/summary&gt;
        public string PrivateConfigurationSchema
        {
            get;
            set;
        }

        /// &lt;summary&gt;
        /// XML configuration based on PrivateConfigurationSchema
        /// &lt;/summary&gt;
        public string PrivateConfiguration
        {
            get;
            set;
        }

        /// &lt;summary&gt;
        /// Extension id.
        /// &lt;/summary&gt;
        public string Id
        {
            get;
            set;
        }

        public static AzureExtension Parse(XElement extensionXml)
        {
            var extension = new AzureExtension();
            foreach (var xe in extensionXml.Elements())
            {
                var elementName = xe.Name.LocalName;
                var elementValue = xe.Value;
                switch (elementName.ToUpperInvariant())
                {
                    case &quot;PROVIDERNAMESPACE&quot;:
                        extension.ProviderNamespace = elementValue;
                        break;
                    case &quot;TYPE&quot;:
                        extension.Type = elementValue;
                        break;
                    case &quot;VERSION&quot;:
                        extension.Version = elementValue;
                        break;
                    case &quot;THUMBPRINT&quot;:
                        extension.Thumbprint = elementValue;
                        break;
                    case &quot;THUMBPRINTALGORITHM&quot;:
                        extension.ThumbprintAlgorithm = elementValue;
                        break;
                    case &quot;PUBLICCONFIGURATION&quot;:
                        extension.PublicConfiguration = Encoding.UTF8.GetString(Convert.FromBase64String(elementValue));
                        break;
                    case &quot;PRIVATECONFIGURATION&quot;:
                        extension.PrivateConfiguration = Encoding.UTF8.GetString(Convert.FromBase64String(elementValue));
                        break;
                    case &quot;PUBLICCONFIGURATIONSCHEMA&quot;:
                        extension.PublicConfigurationSchema = Encoding.UTF8.GetString(Convert.FromBase64String(elementValue));
                        break;
                    case &quot;PRIVATECONFIGURATIONSCHEMA&quot;:
                        extension.PrivateConfigurationSchema = Encoding.UTF8.GetString(Convert.FromBase64String(elementValue));
                        break;
                    case &quot;LABEL&quot;:
                        extension.Label = elementValue;
                        break;
                    case &quot;DESCRIPTION&quot;:
                        extension.Description = elementValue;
                        break;
                    case &quot;HOSTINGRESOURCE&quot;:
                        extension.HostingResource = elementValue;
                        break;
                    case &quot;ID&quot;:
                        extension.Id = elementValue;
                        break;
                }
            }
            return extension;
        }

        public XElement ConvertToXml()
        {
            XElement extensionXElement = new XElement(XName.Get(&quot;Extension&quot;, &quot;http://schemas.microsoft.com/windowsazure&quot;));
            extensionXElement.Add(new XElement(XName.Get(&quot;ProviderNameSpace&quot;, &quot;http://schemas.microsoft.com/windowsazure&quot;), this.ProviderNamespace));
            extensionXElement.Add(new XElement(XName.Get(&quot;Type&quot;, &quot;http://schemas.microsoft.com/windowsazure&quot;), this.Type));
            extensionXElement.Add(new XElement(XName.Get(&quot;Id&quot;, &quot;http://schemas.microsoft.com/windowsazure&quot;), this.Id));
            if (!string.IsNullOrWhiteSpace(this.Thumbprint))
            {
                extensionXElement.Add(new XElement(XName.Get(&quot;Thumbprint&quot;, &quot;http://schemas.microsoft.com/windowsazure&quot;), this.Thumbprint));
                extensionXElement.Add(new XElement(XName.Get(&quot;ThumbprintAlgorithm&quot;, &quot;http://schemas.microsoft.com/windowsazure&quot;), this.ThumbprintAlgorithm));
            }
            extensionXElement.Add(new XElement(XName.Get(&quot;PublicConfiguration&quot;, &quot;http://schemas.microsoft.com/windowsazure&quot;), Convert.ToBase64String(Encoding.UTF8.GetBytes(this.PublicConfiguration))));
            extensionXElement.Add(new XElement(XName.Get(&quot;PrivateConfiguration&quot;, &quot;http://schemas.microsoft.com/windowsazure&quot;), Convert.ToBase64String(Encoding.UTF8.GetBytes(this.PrivateConfiguration))));
            return extensionXElement;
        }
    }
</pre>
</p>
<p>Now that the entity to manipulate extensions is defined, let’s look at the functions.</p>
<h3>List Available Extensions</h3>
<p>This function returns the list of all extensions available to your subscription. Here’s the sample code for listing all extensions available to you:</p>
<p><pre class="brush: plain; title: ; notranslate">
        /// &lt;summary&gt;
        /// Gets a list of all available extensions.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;subscriptionId&quot;&gt;
        /// Subscription id of the subscription.
        /// &lt;/param&gt;
        /// &lt;param name=&quot;cert&quot;&gt;
        /// Management certificate for authenticating Service Management API requests.
        /// &lt;/param&gt;
        /// &lt;returns&gt;
        /// &lt;/returns&gt;
        private static IEnumerable&lt;AzureExtension&gt; ListAvailableExtensions(string subscriptionId, X509Certificate2 cert)
        {
            List&lt;AzureExtension&gt; extensions = new List&lt;AzureExtension&gt;();
            string uri = string.Format(&quot;https://management.core.windows.net/{0}/services/extensions&quot;, subscriptionId);
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
            request.Method = &quot;GET&quot;;
            request.Headers.Add(&quot;x-ms-version&quot;, &quot;2013-03-01&quot;);
            request.ClientCertificates.Add(cert);
            using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse())
            {
                using (var streamReader = new StreamReader(resp.GetResponseStream()))
                {
                    string result = streamReader.ReadToEnd();
                    Console.WriteLine(result);
                    XElement extensionImagesXelement = XElement.Parse(result);
                    foreach (var extensionImageXelement in extensionImagesXelement.Elements(XName.Get(&quot;ExtensionImage&quot;, &quot;http://schemas.microsoft.com/windowsazure&quot;)))
                    {
                        extensions.Add(AzureExtension.Parse(extensionImageXelement));
                    }
                }
            }
            return extensions;
        }
</pre>
</p>
<p>For more details, please click here: <a href="http://msdn.microsoft.com/en-us/library/windowsazure/dn169559.aspx" target="_blank">http://msdn.microsoft.com/en-us/library/windowsazure/dn169559.aspx</a>.</p>
<h3>Add Extension</h3>
<p>This function adds an extension to the list of available extensions in a cloud service. As mentioned above, after adding an extension you would need to perform “<a href="http://msdn.microsoft.com/en-us/library/windowsazure/ee460809.aspx" target="_blank">Change Deployment Configuration</a>” operation for that extension to be enabled on a cloud service. Here’s the sample code for adding an extension to a cloud service:</p>
<p><pre class="brush: plain; title: ; notranslate">
        /// &lt;summary&gt;
        /// Adds an extension to a cloud service. Just by adding an extension won't do any good!
        /// You must call the &quot;Change Deployment Configuration&quot; to apply this extension to the 
        /// running instance of your cloud service.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;subscriptionId&quot;&gt;
        /// Subscription id of the subscription.
        /// &lt;/param&gt;
        /// &lt;param name=&quot;cert&quot;&gt;
        /// Management certificate for authenticating Service Management API requests.
        /// &lt;/param&gt;
        /// &lt;param name=&quot;cloudServiceName&quot;&gt;
        /// Name of cloud service.
        /// &lt;/param&gt;
        /// &lt;param name=&quot;extension&quot;&gt;
        /// Extension which needs to be added.
        /// &lt;/param&gt;
        private static void AddExtension(string subscriptionId, X509Certificate2 cert, string cloudServiceName, AzureExtension extension)
        {
            string uri = string.Format(&quot;https://management.core.windows.net/{0}/services/hostedservices/{1}/extensions&quot;, subscriptionId, cloudServiceName);
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
            request.Method = &quot;POST&quot;;
            request.ContentType = &quot;application/xml&quot;;
            request.Headers.Add(&quot;x-ms-version&quot;, &quot;2013-03-01&quot;);
            request.ClientCertificates.Add(cert);
            string requestPayload = string.Format(&quot;&lt;?xml version=\&quot;1.0\&quot; encoding=\&quot;UTF-8\&quot;?&gt;{0}&quot;, extension.ConvertToXml());
            byte[] content = Encoding.UTF8.GetBytes(requestPayload);
            request.ContentLength = content.Length;
            using (var requestStream = request.GetRequestStream())
            {
                requestStream.Write(content, 0, content.Length);
            }

            using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse())
            {
            }
        } 
</pre>
</p>
<p>Please note that when adding extension, if certificate thumbprint is not provided Service Management API automatically creates a certificate for you and associate that with the cloud service.</p>
<p>For more details, please click here: <a href="http://msdn.microsoft.com/en-us/library/windowsazure/dn169558.aspx" target="_blank">http://msdn.microsoft.com/en-us/library/windowsazure/dn169558.aspx</a>.</p>
<h3>List Extensions</h3>
<p>This function returns all the extensions defined for a particular cloud service. Here’s the sample code to get the list of all extensions for a cloud service:</p>
<p><pre class="brush: plain; title: ; notranslate">
        /// &lt;summary&gt;
        /// Gets a list of all extensions enabled in a cloud service.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;subscriptionId&quot;&gt;
        /// Subscription id of the subscription.
        /// &lt;/param&gt;
        /// &lt;param name=&quot;cert&quot;&gt;
        /// Management certificate for authenticating Service Management API requests.
        /// &lt;/param&gt;
        /// &lt;param name=&quot;cloudServiceName&quot;&gt;
        /// Name of cloud service.
        /// &lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        private static IEnumerable&lt;AzureExtension&gt; ListExtensions(string subscriptionId, X509Certificate2 cert, string cloudServiceName)
        {
            List&lt;AzureExtension&gt; extensions = new List&lt;AzureExtension&gt;();
            string uri = string.Format(&quot;https://management.core.windows.net/{0}/services/hostedservices/{1}/extensions&quot;, subscriptionId, cloudServiceName);
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
            request.Method = &quot;GET&quot;;
            request.Headers.Add(&quot;x-ms-version&quot;, &quot;2013-03-01&quot;);
            request.ClientCertificates.Add(cert);
            using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse())
            {
                using (var streamReader = new StreamReader(resp.GetResponseStream()))
                {
                    string result = streamReader.ReadToEnd();
                    Console.WriteLine(result);
                    XElement extensionImagesXelement = XElement.Parse(result);
                    foreach (var extensionImageXelement in extensionImagesXelement.Elements(XName.Get(&quot;Extension&quot;, &quot;http://schemas.microsoft.com/windowsazure&quot;)))
                    {
                        extensions.Add(AzureExtension.Parse(extensionImageXelement));
                    }
                }
            }
            return extensions;
        } 
</pre>
</p>
<p>For more details, please click here: <a href="http://msdn.microsoft.com/en-us/library/windowsazure/dn169561.aspx" target="_blank">http://msdn.microsoft.com/en-us/library/windowsazure/dn169561.aspx</a>.</p>
<h3>Get Extension</h3>
<p>This function returns the details of a particular extension in a cloud service. Here’s the sample code for getting extension details:</p>
<p><pre class="brush: plain; title: ; notranslate">
        /// &lt;summary&gt;
        /// Gets the details of a particular extension in a cloud service.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;subscriptionId&quot;&gt;
        /// Subscription id of the subscription.
        /// &lt;/param&gt;
        /// &lt;param name=&quot;cert&quot;&gt;
        /// Management certificate for authenticating Service Management API requests.
        /// &lt;/param&gt;
        /// &lt;param name=&quot;cloudServiceName&quot;&gt;
        /// Name of cloud service.
        /// &lt;/param&gt;
        /// &lt;param name=&quot;extensionId&quot;&gt;
        /// Extension id.
        /// &lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        private static AzureExtension GetExtension(string subscriptionId, X509Certificate2 cert, string cloudServiceName, string extensionId)
        {
            string uri = string.Format(&quot;https://management.core.windows.net/{0}/services/hostedservices/{1}/extensions/{2}&quot;, subscriptionId, cloudServiceName, extensionId);
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
            request.Method = &quot;GET&quot;;
            request.Headers.Add(&quot;x-ms-version&quot;, &quot;2013-03-01&quot;);
            request.ClientCertificates.Add(cert);
            using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse())
            {
                using (var streamReader = new StreamReader(resp.GetResponseStream()))
                {
                    string result = streamReader.ReadToEnd();
                    Console.WriteLine(result);
                    XElement extensionDetailsXElement = XElement.Parse(result);
                    return AzureExtension.Parse(extensionDetailsXElement);
                }
            }
        } 
</pre>
</p>
<p>For more details, please click here: <a href="http://msdn.microsoft.com/en-us/library/windowsazure/dn169557.aspx" target="_blank">http://msdn.microsoft.com/en-us/library/windowsazure/dn169557.aspx</a>.</p>
<h3>Delete Extension</h3>
<p>This function removes an extension. Here’s the sample code for deleting an extension from a cloud service:</p>
<p><pre class="brush: plain; title: ; notranslate">
        /// &lt;summary&gt;
        /// Removes a  particular extension from a cloud service.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;subscriptionId&quot;&gt;
        /// Subscription id of the subscription.
        /// &lt;/param&gt;
        /// &lt;param name=&quot;cert&quot;&gt;
        /// Management certificate for authenticating Service Management API requests.
        /// &lt;/param&gt;
        /// &lt;param name=&quot;cloudServiceName&quot;&gt;
        /// Name of cloud service.
        /// &lt;/param&gt;
        /// &lt;param name=&quot;extensionId&quot;&gt;
        /// Extension id.
        /// &lt;/param&gt;
        private static void DeleteExtension(string subscriptionId, X509Certificate2 cert, string cloudServiceName, string extensionId)
        {
            string uri = string.Format(&quot;https://management.core.windows.net/{0}/services/hostedservices/{1}/extensions/{2}&quot;, subscriptionId, cloudServiceName, extensionId);
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
            request.Method = &quot;DELETE&quot;;
            request.Headers.Add(&quot;x-ms-version&quot;, &quot;2013-03-01&quot;);
            request.ClientCertificates.Add(cert);
            using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse())
            {
            }
        } 
</pre>
</p>
<p>For more details, please click here: <a href="http://msdn.microsoft.com/en-us/library/windowsazure/dn169560.aspx" target="_blank">http://msdn.microsoft.com/en-us/library/windowsazure/dn169560.aspx</a>.</p>
<p>That’s pretty much to it!</p>
<h2>Remote Desktop (RDP)</h2>
<p>Now that we’ve seen how extensions work, let’s put this together for some practical use. What we’ll do is enable remote desktop on the fly using the extensions. For the sake of simplicity, we’ll enable RDP on all the roles in our cloud service.</p>
<h3>Step 1: Get the list of all extensions</h3>
<p>To do so, we’ll make use of “<a href="http://msdn.microsoft.com/en-us/library/windowsazure/dn169559.aspx" target="_blank">List Available Extensions</a>” and find out the public and private configuration schema for RDP. Here’s the sample code to do so:</p>
<p><pre class="brush: plain; title: ; notranslate">
            var allExtensions = ListAvailableExtensions(subscriptionId, cert);
            var rdpExtension = allExtensions.FirstOrDefault(e =&gt; e.Type == &quot;RDP&quot;);
</pre>
</p>
<p>Once we get the details about the RDP extension, we can just take the configuration schemas. Here’s what the service currently returns:</p>
<p><strong>Public Configuration Schema:</strong></p>
<p><pre class="brush: plain; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;xs:schema attributeFormDefault=&quot;unqualified&quot; elementFormDefault=&quot;qualified&quot; xmlns:xs=&quot;http://www.w3.org/2001/XMLSchema&quot;&gt;
  &lt;xs:element name=&quot;PublicConfig&quot;&gt;
    &lt;xs:complexType&gt;
      &lt;xs:sequence&gt;
        &lt;xs:element name=&quot;UserName&quot; type=&quot;xs:string&quot; minOccurs=&quot;1&quot; /&gt;
        &lt;xs:element name=&quot;Expiration&quot; type=&quot;xs:string&quot; minOccurs=&quot;1&quot; /&gt;
      &lt;/xs:sequence&gt;
    &lt;/xs:complexType&gt;
  &lt;/xs:element&gt;
&lt;/xs:schema&gt;
</pre>
</p>
<p><strong>Private Configuration Schema:</strong></p>
<p><pre class="brush: plain; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;xs:schema attributeFormDefault=&quot;unqualified&quot; elementFormDefault=&quot;qualified&quot; xmlns:xs=&quot;http://www.w3.org/2001/XMLSchema&quot;&gt;
  &lt;xs:element name=&quot;PrivateConfig&quot;&gt;
    &lt;xs:complexType&gt;
      &lt;xs:sequence&gt;
        &lt;xs:element name=&quot;Password&quot; type=&quot;xs:string&quot; /&gt;
      &lt;/xs:sequence&gt;
    &lt;/xs:complexType&gt;
  &lt;/xs:element&gt;
&lt;/xs:schema&gt;
</pre>
</p>
<p>Based on these, we’ll create public and private configuration:</p>
<p><strong>Public Configuration:</strong></p>
<p><pre class="brush: plain; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;PublicConfig&gt;
  &lt;UserName&gt;{0}&lt;/UserName&gt;
  &lt;Expiration&gt;{1}&lt;/Expiration&gt;
&lt;/PublicConfig&gt;
</pre>
</p>
<p><strong>Private Configuration:</strong></p>
<p><pre class="brush: plain; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;PrivateConfig&gt;
  &lt;Password&gt;{0}&lt;/Password&gt;
&lt;/PrivateConfig&gt;
</pre>
</p>
<h3>Step 2: Add Extension</h3>
<p>Next step is adding extension to the cloud service. To do so, we’ll make use of “<a href="http://msdn.microsoft.com/en-us/library/windowsazure/dn169558.aspx" target="_blank">Add Extension</a>” functionality. Here’s the sample code to do so.</p>
<p><pre class="brush: plain; title: ; notranslate">
            AzureExtension rdpExtension = new AzureExtension()
            {
                ProviderNamespace = &quot;Microsoft.Windows.Azure.Extensions&quot;,
                Type = &quot;RDP&quot;,
                Id = &quot;RDP-&quot; + Guid.NewGuid().ToString(),
                PublicConfiguration = string.Format(publicConfigurationFormat, userName, expiryDate.ToString(&quot;yyyy-MM-dd&quot;)),
                PrivateConfiguration = string.Format(privateConfigurationFormat, password),
            };

            AddExtension(subscriptionId, cert, cloudServiceName, rdpExtension);
</pre>
</p>
<p>Here I’m passing the username, password and the RDP expiry date. Please note that since I&#8217;ve not specified a certificate thumbprint Windows Azure will automatically create a new certificate and associate with my cloud service. <strong>Also I noticed that the password needs to be a strong password</strong>. I actually spent quite some time to realize this. If you provide a simple password (like &#8220;password&#8221;), the operation would complete however you will not be able to connect to your role instances using RDP. You&#8217;ll get a &#8220;login failed&#8221; message. Your password should have 3 of the following &#8211; a lowercase character, an uppercase character, a number, and a special character. </p>
<h3>Step 3: Update Configuration</h3>
<p>Once the extension is added, next step would be to update the cloud service configuration by performing “<a href="http://msdn.microsoft.com/en-us/library/windowsazure/ee460809.aspx" target="_blank">Change Deployment Configuration</a>” operation. For this, first we may need to fetch the current configuration. To do so, we’ll perform “Get Hosted Service Properties” operation and try to get both production and staging configuration settings. Here’s the sample code to get the configuration settings:</p>
<p><pre class="brush: plain; title: ; notranslate">
        private static string[] GetCloudServiceDeploymentConfigurations(string subscriptionId, X509Certificate2 cert, string cloudServiceName)
        {
            string[] deploymentConfigurations = new string[2];//We'll try to get both production and staging deployment configurations. The 1st element will always be production and the 2nd will be staging.
            string uri = string.Format(&quot;https://management.core.windows.net/{0}/services/hostedservices/{1}?embed-detail=true&quot;, subscriptionId, cloudServiceName);
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
            request.Method = &quot;GET&quot;;
            request.Headers.Add(&quot;x-ms-version&quot;, &quot;2013-03-01&quot;);
            request.ClientCertificates.Add(cert);
            using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse())
            {
                using (var streamReader = new StreamReader(resp.GetResponseStream()))
                {
                    string result = streamReader.ReadToEnd();
                    XElement cloudServiceProperties = XElement.Parse(result);
                    var deployments = cloudServiceProperties.Elements(XName.Get(&quot;Deployments&quot;, &quot;http://schemas.microsoft.com/windowsazure&quot;));
                    foreach (var deployment in deployments.Elements())
                    {
                        var slotElement = deployment.Element(XName.Get(&quot;DeploymentSlot&quot;, &quot;http://schemas.microsoft.com/windowsazure&quot;));
                        var configElement = deployment.Element(XName.Get(&quot;Configuration&quot;, &quot;http://schemas.microsoft.com/windowsazure&quot;));
                        var deploymentSlot = slotElement.Value;
                        var configurationSettings = Encoding.UTF8.GetString(Convert.FromBase64String(configElement.Value));
                        switch (deploymentSlot.ToUpper())
                        {
                            case &quot;PRODUCTION&quot;:
                                deploymentConfigurations[0] = configurationSettings;
                                break;
                            case &quot;STAGING&quot;:
                                deploymentConfigurations[1] = configurationSettings;
                                break;
                        }
                    }
                }
            }
            return deploymentConfigurations;
        }
</pre>
</p>
<p>Now that we’ve got the configurations for both production and staging slots, let’s apply the changes. Here’s the sample code for change deployment configuration operation:</p>
<p><pre class="brush: plain; title: ; notranslate">
        private static void ChangeDeploymentConfiguration(string subscriptionId, X509Certificate2 cert, string cloudServiceName, string slot, string configuration)
        {
            string uri = string.Format(&quot;https://management.core.windows.net/{0}/services/hostedservices/{1}/deploymentslots/{2}/?comp=config&quot;, subscriptionId, cloudServiceName, slot);
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
            request.Method = &quot;POST&quot;;
            request.ContentType = &quot;application/xml&quot;;
            request.Headers.Add(&quot;x-ms-version&quot;, &quot;2013-03-01&quot;);
            request.ClientCertificates.Add(cert);
            byte[] content = Encoding.UTF8.GetBytes(configuration);
            request.ContentLength = content.Length;
            using (var requestStream = request.GetRequestStream())
            {
                requestStream.Write(content, 0, content.Length);
            }

            using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse())
            {
            }
        }
</pre>
</p>
<p>And this is how you can call it.</p>
<p><pre class="brush: plain; title: ; notranslate">
            string updateConfigurationFormat = @&quot;&lt;?xml version=&quot;&quot;1.0&quot;&quot; encoding=&quot;&quot;utf-8&quot;&quot;?&gt;
                &lt;ChangeConfiguration xmlns=&quot;&quot;http://schemas.microsoft.com/windowsazure&quot;&quot;&gt;
                    &lt;Configuration&gt;{0}&lt;/Configuration&gt;
                    &lt;ExtensionConfiguration&gt;
                        &lt;AllRoles&gt;
                          &lt;Extension&gt;
                            &lt;Id&gt;{1}&lt;/Id&gt;
                          &lt;/Extension&gt;
                        &lt;/AllRoles&gt;
                     &lt;/ExtensionConfiguration&gt;
                &lt;/ChangeConfiguration&gt;&quot;;
</pre>
</p>
<p><pre class="brush: plain; title: ; notranslate">
                var productionConfigurationSetting = string.Format(updateConfigurationFormat, Convert.ToBase64String(Encoding.UTF8.GetBytes(productionConfig)), rdpExtension.Id);
                ChangeDeploymentConfiguration(subscriptionId, cert, cloudServiceName, &quot;Production&quot;, productionConfigurationSetting);
</pre>
</p>
<p>Putting it all together nicely in just one function:</p>
<p><pre class="brush: plain; title: ; notranslate">
        private static void EnableRemoteDesktop(string subscriptionId, X509Certificate2 cert, string cloudServiceName, string userName, string password, DateTime expiryDate)
        {
            string publicConfigurationFormat = @&quot;&lt;?xml version=&quot;&quot;1.0&quot;&quot; encoding=&quot;&quot;UTF-8&quot;&quot;?&gt;
                &lt;PublicConfig&gt;
                    &lt;UserName&gt;{0}&lt;/UserName&gt;
                    &lt;Expiration&gt;{1}&lt;/Expiration&gt;
                &lt;/PublicConfig&gt;&quot;;

            string privateConfigurationFormat = @&quot;&lt;?xml version=&quot;&quot;1.0&quot;&quot; encoding=&quot;&quot;UTF-8&quot;&quot;?&gt;
                &lt;PrivateConfig&gt;
                    &lt;Password&gt;{0}&lt;/Password&gt;
                &lt;/PrivateConfig&gt;&quot;;

            string updateConfigurationFormat = @&quot;&lt;?xml version=&quot;&quot;1.0&quot;&quot; encoding=&quot;&quot;utf-8&quot;&quot;?&gt;
                &lt;ChangeConfiguration xmlns=&quot;&quot;http://schemas.microsoft.com/windowsazure&quot;&quot;&gt;
                    &lt;Configuration&gt;{0}&lt;/Configuration&gt;
                    &lt;ExtensionConfiguration&gt;
                        &lt;AllRoles&gt;
                          &lt;Extension&gt;
                            &lt;Id&gt;{1}&lt;/Id&gt;
                          &lt;/Extension&gt;
                        &lt;/AllRoles&gt;
                     &lt;/ExtensionConfiguration&gt;
                &lt;/ChangeConfiguration&gt;&quot;;

            //Define RDP Extension
            AzureExtension rdpExtension = new AzureExtension()
            {
                ProviderNamespace = &quot;Microsoft.Windows.Azure.Extensions&quot;,
                Type = &quot;RDP&quot;,
                Id = &quot;RDP-&quot; + Guid.NewGuid().ToString(),
                PublicConfiguration = string.Format(publicConfigurationFormat, userName, expiryDate.ToString(&quot;yyyy-MM-dd&quot;)),
                PrivateConfiguration = string.Format(privateConfigurationFormat, Convert.ToBase64String(Encoding.UTF8.GetBytes(password))),
            };

            //Add extension
            AddExtension(subscriptionId, cert, cloudServiceName, rdpExtension);

            //Get deployment configurations
            var configurations = GetCloudServiceDeploymentConfigurations(subscriptionId, cert, cloudServiceName);

            var productionConfig = configurations[0];
            if (!string.IsNullOrWhiteSpace(productionConfig))
            {
                //Apply RDP extension to production slot.
                var productionConfigurationSetting = string.Format(updateConfigurationFormat, Convert.ToBase64String(Encoding.UTF8.GetBytes(productionConfig)), rdpExtension.Id);
                ChangeDeploymentConfiguration(subscriptionId, cert, cloudServiceName, &quot;Production&quot;, productionConfigurationSetting);
            }
            var stagingConfig = configurations[1];
            if (!string.IsNullOrWhiteSpace(stagingConfig))
            var stagingConfig = configurations[1];
            if (!string.IsNullOrWhiteSpace(stagingConfig))
            {
                //Apply RDP extension to staging slot.
                var stagingConfigurationSetting = string.Format(updateConfigurationFormat, Convert.ToBase64String(Encoding.UTF8.GetBytes(stagingConfig)), rdpExtension.Id);
                ChangeDeploymentConfiguration(subscriptionId, cert, cloudServiceName, &quot;Staging&quot;, stagingConfigurationSetting);
            }
        }
</pre>
</p>
<p>That’s pretty much it!!! Once the operation is complete, you should be able to RDP into your instances.</p>
<h3>Wish List</h3>
<p>My only wish here is that the API team has not clubbed this extensions functionality with change deployment configuration and provided direct operations for enabling/disabling the extensions. Clubbing this functionality with change deployment configuration may lead to some inadvertent errors. Other than that, I wish they had an “Update Extension” operation. Currently, I don’t know how I would update an extension. That functionality can be real handy.</p>
<h2>Summary</h2>
<p>I think the extensions functionality is pretty awesome. In due course of time when Windows Azure team starts accepting components from ISVs, it would open up a lot of opportunities. Even now, the flexibility offered by built-in extensions is quite helpful to the developers. As always, if you find any issues with the post please let me know and I’ll fix it ASAP.</p>
<p>Happy Coding!</p>
<img src="http://feeds.feedburner.com/~r/gmantri/~4/2VeyREEELgg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://gauravmantri.com/2013/05/06/windows-azure-cloud-services-extensions-and-service-management-api-fun-with-remote-desktop/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://gauravmantri.com/2013/05/06/windows-azure-cloud-services-extensions-and-service-management-api-fun-with-remote-desktop/</feedburner:origLink></item>
		<item>
		<title>Introducing Windows Azure SDK 2.0 for .Net</title>
		<link>http://feedproxy.google.com/~r/gmantri/~3/SiEtoseHG6Q/</link>
		<comments>http://gauravmantri.com/2013/04/30/introducing-windows-azure-sdk-2-0-for-net/#comments</comments>
		<pubDate>Tue, 30 Apr 2013 18:21:42 +0000</pubDate>
		<dc:creator>Gaurav</dc:creator>
				<category><![CDATA[Windows Azure]]></category>
		<category><![CDATA[Windows Azure SDK]]></category>
		<category><![CDATA[Windows Azure SDK 2.0]]></category>

		<guid isPermaLink="false">http://gauravmantri.com/?p=1234</guid>
		<description><![CDATA[Today Microsoft announced the availability of Windows Azure SDK 2.0 for .Net. You can read more about the announcement in Scott Guthrie’s blog post here: http://weblogs.asp.net/scottgu/archive/2013/04/30/announcing-the-release-of-windows-azure-sdk-2-0-for-net.aspx. In this blog post, we’ll cover some of the features introduced in this newest version. Downloading/Installing SDK 2.0 You can download and install SDK 2.0 using Web Platform Installer [...]]]></description>
			<content:encoded><![CDATA[<p>Today Microsoft announced the availability of Windows Azure SDK 2.0 for .Net. You can read more about the announcement in Scott Guthrie’s blog post here: <a href="http://weblogs.asp.net/scottgu/archive/2013/04/30/announcing-the-release-of-windows-azure-sdk-2-0-for-net.aspx">http://weblogs.asp.net/scottgu/archive/2013/04/30/announcing-the-release-of-windows-azure-sdk-2-0-for-net.aspx</a>. In this blog post, we’ll cover some of the features introduced in this newest version.</p>
<h2>Downloading/Installing SDK 2.0</h2>
<p>You can download and install SDK 2.0 using Web Platform Installer from Windows Azure Developer center: <a href="http://www.windowsazure.com/en-us/develop/net/">http://www.windowsazure.com/en-us/develop/net/</a>.</p>
<h2>Improved Tooling in Visual Studio</h2>
<p>A number of improvements done in Visual Studio as part of this release. Some of these changes are:</p>
<h3>Windows Azure Diagnostics</h3>
<p>IMO, this is the most important improvement in the tooling. Windows Azure Diagnostics (WAD) is a crucial part of any cloud service deployment and unfortunately it was really tough to get diagnostics working. In the latest version, the tooling team has made it extremely easy to manage WAD.</p>
<p>You get an easy to use way of configuring diagnostics. See the screenshot below for example.</p>
<p><a href="http://gauravmantri.com/wp-content/uploads/2013/04/clip_image002.jpg"><img style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="clip_image002" src="http://gauravmantri.com/wp-content/uploads/2013/04/clip_image002_thumb.jpg" alt="clip_image002" width="810" height="203" border="0" /></a></p>
<p>You get 3 options – “Errors only”, “All information” and “Custom plan”.</p>
<p>When you choose “Errors only”, only log entries (trace, event, and infrastructure) with “Error” type will be transferred to storage. When you choose “All information”, all logs entries will be transferred to storage. <strong>Please note that in both the cases the transfer interval is one minute and performance counters data will not be transferred</strong>. If you want to transfer performance counters data or wish to have more granular control, you would need to choose “Custom plan” where you would be able to configure not only performance counters but also scheduled transfer period and buffer size as well among other things.</p>
<p><a href="http://gauravmantri.com/wp-content/uploads/2013/04/clip_image004.jpg"><img style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="clip_image004" src="http://gauravmantri.com/wp-content/uploads/2013/04/clip_image004_thumb.jpg" alt="clip_image004" width="810" height="551" border="0" /></a></p>
<p>Another important change with WAD is that it is no longer dependent on Storage Client Library 1.7. It makes use of version 2.0.5.1 of the storage client library.</p>
<p>I’ll probably write another blog post focusing exclusively on Windows Azure Diagnostics and SDK 2.0 to cover that in more details.</p>
<h3>Support for Windows Azure Websites</h3>
<p>Now you can view and manage Windows Azure Websites through Visual Studio. To manage your websites, you would go to VIEW à Server Explorer à Windows Azure Websites. There you will see all your websites. You will need to provide a publish profile file before you can use this functionality.</p>
<p><a href="http://gauravmantri.com/wp-content/uploads/2013/04/clip_image006.jpg"><img style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="clip_image006" src="http://gauravmantri.com/wp-content/uploads/2013/04/clip_image006_thumb.jpg" alt="clip_image006" width="810" height="505" border="0" /></a></p>
<p>Things you could do with Windows Azure Websites in Visual Studio are:</p>
<p>· Manage configuration – as shown in the screenshot above.</p>
<p>· View / download website logs.</p>
<p>· Improved publishing support. Unfortunately you can’t create a new website through Visual Studio just yet.</p>
<h3>Support for Larger VM Size (A6, A7)</h3>
<p>When Windows Azure Virtual Machine (IaaS) went GA a few days ago, they made 2 new VM sizes available there (A6 and A7). They’re now available in Cloud Services as well i.e. you can deploy cloud services in A6 and A7 sized VMs as well. You get that option in Visual Studio as well.</p>
<p><a href="http://gauravmantri.com/wp-content/uploads/2013/04/clip_image008.jpg"><img style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="clip_image008" src="http://gauravmantri.com/wp-content/uploads/2013/04/clip_image008_thumb.jpg" alt="clip_image008" width="810" height="398" border="0" /></a></p>
<h2>Library Improvements</h2>
<h3>Latest libraries</h3>
<p>SDK 2.0 by default includes latest version of various libraries which at the time of release was 2.0.5.1 for Windows Azure Storage, 2.0 for Windows Azure Service Bus, 2.0 for Windows Azure Caching and 2.0 for Windows Azure Configuration Manager. You can also get these libraries from NuGet as well because these libraries will be constantly updated with latest features in between SDK releases.</p>
<p>Windows Azure Service Bus client library has been updated with support for browsing messages, the event-driven message programming model, and auto-deleting idle messaging entities.</p>
<h2>Breaking Changes</h2>
<p>Following are some of the breaking changes in SDK 2.0 which you would need to keep in mind when upgrading your solution to the latest SDK version:</p>
<h3>.NET Framework Minimum Version</h3>
<p>The minimum version of the .NET Framework required for building web and worker roles is now .NET Framework 4.0. You can still reference .NET Framework 3.5 assemblies in your project, but the project itself must be built targeting .NET Framework 4.0 or 4.5. Furthermore ServiceRuntime, Configuration and Caching assemblies are now built against the .NET Framework 4.0 runtime. Therefore, any of your applications that target the .NET Framework 3.5 should now target the .NET Framework 4.0 before upgrading to the Windows Azure SDK for .NET 2.0.</p>
<h3>Side-by-Side Cloud Service Debugging</h3>
<p>Side-by-Side cloud service debugging is only supported with Windows Azure SDK for .NET versions 1.7, 1.8, and 2.0. For a full debugging experience, projects built using versions prior to version 1.7 must be upgraded. This is done in line with the SDK expiration policy announced some days back.</p>
<h2>Summary</h2>
<p>That’s it for this post. All in all I am quite pleased with the changes introduced in the new SDK and I think they will help users working with Windows Azure immensely. In the next post, I will dig deep into Windows Azure Diagnostics and SDK 2.0.</p>
<p>Stay tuned!</p>
<img src="http://feeds.feedburner.com/~r/gmantri/~4/SiEtoseHG6Q" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://gauravmantri.com/2013/04/30/introducing-windows-azure-sdk-2-0-for-net/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://gauravmantri.com/2013/04/30/introducing-windows-azure-sdk-2-0-for-net/</feedburner:origLink></item>
		<item>
		<title>Windows Azure Primer–Basics</title>
		<link>http://feedproxy.google.com/~r/gmantri/~3/baam_Kgwong/</link>
		<comments>http://gauravmantri.com/2013/04/12/windows-azure-primerbasics/#comments</comments>
		<pubDate>Fri, 12 Apr 2013 12:27:46 +0000</pubDate>
		<dc:creator>Gaurav</dc:creator>
				<category><![CDATA[Cloud Computing]]></category>
		<category><![CDATA[Windows Azure]]></category>

		<guid isPermaLink="false">http://gauravmantri.com/?p=1221</guid>
		<description><![CDATA[There’re many articles which cover Windows Azure and it’s functionality in great details however I could not find much information when it comes to novice users (or may be I need to brush up on my searching skills ). Anyways, through these series of blog posts I will try and explain Windows Azure as I [...]]]></description>
			<content:encoded><![CDATA[<p>There’re many articles which cover Windows Azure and it’s functionality in great details however I could not find much information when it comes to novice users (or may be I need to brush up on my searching skills <img class="wlEmoticon wlEmoticon-smile" style="border-style: none;" src="http://gauravmantri.com/wp-content/uploads/2013/04/wlEmoticon-smile.png" alt="Smile" />). Anyways, through these series of blog posts I will try and explain Windows Azure as I understand it to users who are just starting out with Windows Azure. We’ll cover some basic functionalities available in Windows Azure and try to understand that. If you’ve worked with Windows Azure, you may find these posts trivial but I still want you to read this so that you can correct me if I have provided some incorrect information.</p>
<p>With that intent, let’s start!</p>
<p>Before we get into the details about what Windows Azure and what it is not, let’s take a moment to define what Windows Azure is. I would define it like the following:</p>
<h4 align="center">Windows Azure is <span style="text-decoration: underline;">Public Cloud Computing Platform</span> offering by Microsoft</h4>
<p>&nbsp;</p>
<p>However before we talk about Windows Azure, let’s take a moment and talk about Cloud Computing first as I feel folks who are starting out have a different notion of what cloud computing is (and what it’s not). Then we get into Windows Azure.</p>
<h2>Cloud Computing</h2>
<p>In this section we’ll focus on cloud computing. We’ll start with definition, then talk about key characteristics of a cloud environment and then talk about some application scenarios where cloud can be used.</p>
<h3>Definition</h3>
<p>Wikipedia defines <a href="http://en.wikipedia.org/wiki/Cloud_computing" target="_blank">Cloud Computing</a> as follows:</p>
<blockquote><p>Cloud computing is the use of computing resources (hardware and software) that are delivered as a service over a network (typically the Internet)</p></blockquote>
<p>However as I understand it (and at a very basic level):</p>
<h4 align="center">It’s Just a Hosting Platform (with some differences)!</h4>
<p>Let me explain. Let’s say I have built a website and now I want to host it. Depending on my application requirement, I may decide to go with a hosting provider and they would offer me different environments to choose from (Shared, VPS, Dedicated) to run my application; different storage options (disk quota, choice of data stores); bandwidth quota and some value added services etc. This is exactly the same with any cloud provider. At the very least, each cloud provider provides an environment to run the application (typically referred to as “<strong>compute</strong>”), choice of data stores (Relational, NoSql, Object) and network infrastructure (bandwidth, firewall etc.). So the application I would host with any hosting provider could easily be hosted with any cloud provider. There’re some differences and I’ll talk about those in the next section.</p>
<h3>Key Principles/Characteristics</h3>
<p>Any cloud computing infrastructure is built on the certain key principles and we talk about them below. Also I see a number of folks want to build their own cloud infrastructure (my advice to them: please, don’t! It’s bloody expensive <img class="wlEmoticon wlEmoticon-smile" style="border-style: none;" src="http://gauravmantri.com/wp-content/uploads/2013/04/wlEmoticon-smile.png" alt="Smile" />). So if you’re one the guys who want to build your own cloud infrastructure, make sure it has the characteristics described below.</p>
<h4>Shared Resources</h4>
<p>When you run your applications in your data centers, you own each and every part of it. You own the servers, you own the infrastructure, everything. However with cloud, it’s different. You don’t own anything there other than the application (and application data) you’re hosting.</p>
<p>Hosting an application in the cloud is quite similar to booking a room in a hotel.</p>
<p>You get a room which you rent for a few days. You can’t claim ownership of that room but at the same time you’re the only tenant in that room. In a cloud environment, you get one or more virtual machines in which you would run your applications but you don’t own those virtual machines. Like your hotel room, cloud provider would guarantee you that you’re the only tenant of those virtual machines. They won’t put more tenants in that virtual machine.</p>
<p>Hotel may offer other amenities (like Internet access, Gym, Restaurant etc.) but you share those amenities with other guests in the hotel. Similarly in a cloud environment, you share resources like internet bandwidth, physical infrastructure (like routers and stuff) with other tenants. Like you can’t have another guest sharing the same treadmill with you at the Gym <img class="wlEmoticon wlEmoticon-smile" style="border-style: none;" src="http://gauravmantri.com/wp-content/uploads/2013/04/wlEmoticon-smile.png" alt="Smile" />, cloud provider provides you with some isolation for these shared resources and ensures that you’re not impacted by “rude/noisy neighbor behavior” but that’s pretty much it.</p>
<h4>Self-Service Model</h4>
<p>All cloud provider provides a self-service model. As I understand it, <strong>a self-service model allows you to manage the resources you consume in a cloud environment by yourself without going to the cloud provider</strong>.</p>
<p>Again taking the analogy of the hotel, think of it that way: Let’s say you want to extend the reservation or may be change a room type. One way you could do it is to go to front desk and ask them to make those changes however that’s not the self-service model. Now let’s assume that the hotel provides a web site or a kiosk using which you can make the changes you want. Now that’s a self-service model.</p>
<p>Similarly in a cloud environment, each cloud provider provides a self-service model (either in form of raw API or through easy-to-use applications) using which you can manipulate the resources you want to consume e.g. you may want to run your application in a larger virtual machine or you want to increase (or decrease) the number of virtual machines in which your application runs. You don’t have to contact your cloud provider (by phone/email etc.) to do the same.</p>
<p>Another aspect of self-service model is “<strong>self healing</strong>”. Wouldn’t it be nice if the hotel automatically detects that your room is dirty and needs cleaning or you’ve run out of coffee in your room and automatically replenishes it! It doesn’t happen in hotel (at least in my experience) but it sure happens in the cloud. Through their advanced monitoring, a cloud provider knows that there’s something wrong with one or more virtual machines in which your application is running and it tries to heal them automatically. Self healing could happen in the form of taking out a troubled virtual machine out of the picture and spinning off a new virtual machine automatically.</p>
<h4>Elasticity</h4>
<p>In cloud computing, <strong>elasticity means the ability to expand or shrink resource consumption based on the need</strong>. It is sometimes related to <strong>scalability</strong> also. To give an example, let’s say you’ve an application which gets used more on weekdays than on weekends. In cloud environment you have the flexibility to put more resources (typically virtual machines) to serve your application during weekdays and then reduce the resources over the weekend. Combined with “self-service model” characteristic of the cloud infrastructure makes it quite attractive hosting choice for some kinds of applications (we’ll discuss that in a bit).</p>
<p>Another aspect of elasticity is the notion of <em><strong>infinite limit</strong></em>. To give you an example, when we buy a computer we get it with a hark disk with a pre-defined size e.g. 512 GB, 1 TB etc. Now we can’t go beyond that. If we need to go beyond that, we would either need to purchase an additional hard disk with higher capacity and replace the current one with a new one or get additional hard disk and attach it along with existing hard drive. But again there’s a limit to which you could go. In cloud you have the notion of infinite limit. You can increase as much as you want to.</p>
<p>I used the word “<em><strong>notion</strong></em>” and there’s a reason for that. It may seem like there’s no limit but in reality there’s one however generally speaking the limit is too high so we may never reach that limit.</p>
<h4>Pay Per Use</h4>
<p>Pay per use or consumption based billing is the most important characteristic of a cloud environment. In a typical cloud environment, <strong>you only pay for the resources you consume – nothing more, nothing less</strong>. So if you’re running a virtual machine for 12 hours, you only pay for 12 hours. This becomes really attractive for some companies (especially startups) because they don’t have to make upfront investment in procuring infrastructure. Today you need one server to serve your application, you use one server and you pay for just one. Tomorrow you need say ten servers to server your application, you use ten servers and you pay for those ten servers. Day after tomorrow you need again just one server, you use and pay for that one server.</p>
<p>When I talk to students about cloud computing, a common example I give is the computer buying experience. Let’s say you’re in the market for buying a computer and you don’t really need 4 GB of RAM or 512 GB of hard disk to begin with but then when you’re working on a special project you might need that kind of capability. You can’t tell your computer vendor that since you’ll be using a part of the resources available on the computer, you’ll only pay for that. They’ll laugh at you. You would either have to buy a low-end computer (and then worry about upgrading it later) or buy a high-end computer and underutilize it. Either way you look at it, you lose.</p>
<p>Not in cloud though!!! You need a low-end virtual machine to begin with, you go with that and pay a lower price for that (and only for the time you use) but then later on you need a high-end virtual machine, you just rent that high-end machine and use that and pay only for the time you use that machine. Makes complete sense, doesn’t it!</p>
<h3>Key Application Scenarios/Patterns</h3>
<p>Since a cloud computing infrastructure is a hosting environment and you could possibly host any kind of application there. However to take full advantage of the benefits offered by cloud, there’re a few key application scenarios/patterns. If your application fits those scenarios/patterns, then you may want to consider hosting your application in the cloud.</p>
<p>Here’re some of those scenarios/patterns:</p>
<h4>On and Off Pattern</h4>
<p><a href="http://gauravmantri.com/wp-content/uploads/2013/04/image.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="image" src="http://gauravmantri.com/wp-content/uploads/2013/04/image_thumb.png" alt="image" width="810" height="209" border="0" /></a></p>
<p>Let’s say you’re making a digital movie. Once the movie is complete, you would need massive compute capacity to create a render farm to render the movie. However once the rendering is done, you really don’t need that compute capacity. That’s “On and Off” pattern and cloud could be a perfect choice for that. Another example could be monthly data processing where you would need to generate lots and lots of reports for your clients however the whole exercise of generating reports is a few days task. This kind of application can also be considered to be deployed in the cloud.</p>
<h4>Growing Fast Pattern</h4>
<p><a href="http://gauravmantri.com/wp-content/uploads/2013/04/image1.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="image" src="http://gauravmantri.com/wp-content/uploads/2013/04/image_thumb1.png" alt="image" width="810" height="149" border="0" /></a></p>
<p>This is where typical startups come into picture. Let’s assume that you’re running a startup. Like every startup, you expect your startup to be extremely successful and wish to have millions of users using your application. As much as you want to do it, it’s impractical (both physically and financially) to start with having an infrastructure to support extreme load. So what you do is host your application in the cloud. If the startup is successful and you start getting more and more visitors, you just tap into “elastic” characteristic of your cloud provider and increase the resources really needed to support your user base.</p>
<h4>Unpredictable Bursting Pattern</h4>
<p><a href="http://gauravmantri.com/wp-content/uploads/2013/04/image2.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="image" src="http://gauravmantri.com/wp-content/uploads/2013/04/image_thumb2.png" alt="image" width="810" height="156" border="0" /></a></p>
<p>Everybody likes pleasant surprises. Let’s say you’re running a startup and unknown to you, suddenly you got “Techcrunched”!!! As a result, you see a sudden spike in the visitation to your application. Again the “elastic” characteristic of your cloud provider would allow you to increase the resources in no time to handle is unpredictable increase in load. Another example is that you’re providing an event management application as a service and one of the subscriber announces this really special event and that kind of catches you off guard. Having hosted this application in the cloud would give the ability and flexibility to meet with this unexpected demand.</p>
<h4>Predictable Bursting Pattern</h4>
<p><a href="http://gauravmantri.com/wp-content/uploads/2013/04/image3.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="image" src="http://gauravmantri.com/wp-content/uploads/2013/04/image_thumb3.png" alt="image" width="810" height="146" border="0" /></a></p>
<p>In one of my previous jobs, we developed a system where people would make reservations for camping sites all across the US. Summer time, especially long weekends (memorial day, labor day) were dreaded period for us because we knew that our application will be hammered badly on those days. Also there were some National Parks (like Yosemite National Park in California) which opened their booking on a particular date so we knew that we’ll get extensive load on that day. My only wish today is that we had cloud infrastructure during that time so that we didn’t have those nightmarish days and weekends <img class="wlEmoticon wlEmoticon-smile" style="border-style: none;" src="http://gauravmantri.com/wp-content/uploads/2013/04/wlEmoticon-smile.png" alt="Smile" />.</p>
<p>When you know well in advance that you would get more visitors on a particular day/time, you may want to consider cloud as a hosting option. You don’t have to build that excess capacity in-house just to take care of peak demand.</p>
<p>Another example I give here in India is Indian Railways train reservation website!!! They open their booking every morning at 8:00 AM and it is next to impossible to book a train ticket between 8:00 – 10:00 AM if you’re trying to book a train for summer vacation as everybody’s on that site. They could certainly use cloud, provision excess capacity for those two hours and have a lot of happy customers.</p>
<h2>Windows Azure</h2>
<p>Now that we’ve some basic understanding of cloud computing, let’s talk about Windows Azure. As I said above:</p>
<h4 align="center">Windows Azure is <span style="text-decoration: underline;">Public Cloud Computing Platform</span> offering by Microsoft</h4>
<p>At a very high level it provides a compute environment to run your application, different storage options to store your application data and some value added services apart from core infrastructure. In this section we’ll briefly talk about these components (we’ll cover them in details in subsequent posts), answer the question if Windows Azure is right for your application and then answer some common questions (or debunk some myths). Plus we’ll also talk about how to get started with Windows Azure.</p>
<h3>Components</h3>
<p>First, let’s talk about components. In this post we’ll keep the discussion real short as we’ll cover them in great details in the subsequent posts.</p>
<h4>Compute</h4>
<p>This is the execution environment for your applications. Windows Azure provides both shared and dedicated execution environments with varied compute resource size (in terms of processing power, RAM etc.) and a wide range of operating systems (including but not limited to Windows Server 2012, 2008, some flavors of Linux etc.).</p>
<h4>Storage</h4>
<p>Every application either need to store some data or work on a stored data. Windows Azure provides many storage options including but not limited to Relational Databases (SQL Server, MySQL as a service), NoSql Databases (Table Storage) and Object Storage (Blob Storage). Through it’s Infrastructure as a Service (IaaS) offering, it is possible for you to support other relational and NoSql databases as well.</p>
<h4>Value Added Services</h4>
<p>This post is already quite long <img class="wlEmoticon wlEmoticon-smile" style="border-style: none;" src="http://gauravmantri.com/wp-content/uploads/2013/04/wlEmoticon-smile.png" alt="Smile" /> so for the sake of not making it longer I’ve clubbed all other services under just one bucket – value added services. These include messaging (Windows Azure Queues/Service Bus), CDN, Caching, Identity Management (Windows Azure Active Directory/Windows Azure Access Control Service), Windows Azure Mobile Service, Windows Azure Media Service etc. It also offers a store which allows you to avail other value added services like monitoring etc. from 3rd party providers.</p>
<h3>Is Windows Azure Right For Me?</h3>
<p>I guess the right question to ask: “<strong>Is Cloud Right For Me?</strong>”. Simple answer to the question: it depends <img class="wlEmoticon wlEmoticon-smile" style="border-style: none;" src="http://gauravmantri.com/wp-content/uploads/2013/04/wlEmoticon-smile.png" alt="Smile" />.</p>
<p>Well, one criteria is the <strong>key scenarios/patterns</strong> described above. If your application fits one or more of the scenarios described above then yes you could consider Windows Azure.</p>
<p>Yet another criteria would be the <strong>application business domain</strong>. You would need to remember is that Windows Azure is <strong>Public Cloud</strong> and you don’t get physical access to the underlying infrastructure or data centers where your application is hosted. If your application business domain is constrained by certain rules and regulations (like HIPPA for healthcare, SOX for Finance etc.) you may want to check that first.</p>
<p>Also you would need to consider <strong>data sovereignty laws</strong> as Windows Azure does not have data center in every country/region. If your application has a requirement that the application data can’t leave the physical boundary of your country/region and Windows Azure does not have a data center in your country/region, you’re kind of out of luck! Windows Azure won’t stop you from hosting the application but then you would be in breach of your local laws.</p>
<h3>Some Questions Answered</h3>
<p>I participate in a number of forums and when people start with Windows Azure, they have some common set of questions. I’ve picked a few of them:</p>
<h4>If I choose Windows Azure, do I let go of my existing skills and need to learn new ones?</h4>
<p>No. Most folks think that cloud computing is yet another programming language they would need to master. Remember, Windows Azure is just another hosting platform for your application. You would still develop the application the way you’ve been developing them and when you’re ready to deploy your applications, you just deploy them in Windows Azure.</p>
<p>Obviously, to take full advantage of the platform you would need to learn some platform specific tricks but you don’t discard your existing skills. You learn new skills to complement your existing skills. One common example here is that when we build traditional web applications we either store images on the file system or in the application database. You could still do that but that’s not recommended as the file system in the cloud is volatile and there’re better alternatives than application database e.g. Blob Storage. So you would need to learn how to save images in blob storage.</p>
<p>A key benefit of Windows Azure is scalability however to achieve this you may have to build applications which have loosely coupled components (or modules) so that each component can be scaled independently. So in order to do that you may need to learn how to build loosely coupled components.</p>
<h4>Isn’t Windows Azure all about .Net?</h4>
<p>Absolutely not! Just because Windows Azure is from Microsoft we tend to assume that it’s all about .Net but that’s just not true. Windows Azure supports many languages and platforms including but not limited to .Net, Java, PHP, Python, Node.Js etc. If your programming environment is not supported natively you could still use Windows Azure by making use of IaaS feature.</p>
<h3>Getting Started</h3>
<p>Let’s wrap up this post by how to get started with Windows Azure. Well, Windows Azure offers a 90 day free trial which you can sign up for. You would be asked to provide a credit card number but it won’t be charged (with the exception of a $1.00 charge to verify your card) so it’s completely risk free. However you must realize that free trial comes with a preset quota for a month and if you exceed that quota, Windows Azure will suspend your account for the rest of that month. So please ensure that you don’t exceed that quota. <strong>You can avoid account suspension by removing the spending limit but during trial phase I would strongly recommend NOT to do that</strong>. This is one common mistake we do is not realize that in Windows Azure we pay based on consumption. We think that the consumption is the “consumption of our application” i.e. we only pay if somebody is using our application. That’s not true. Consumption is how much of Windows Azure’s resources are we consuming. When we deploy our application, we’re consuming virtual machines provided by Windows Azure. So please keep that in mind when using Windows Azure. To get started with Windows Azure free 90 day trial, please click here: <a href="http://www.windowsazure.com/en-us/pricing/free-trial/" target="_blank">http://www.windowsazure.com/en-us/pricing/free-trial/</a>.</p>
<p>Windows Azure also provides a compute and storage emulator using which you can try some features without even signing up for the trial. So you may want to look into that as well. Compute and storage emulator are part of Windows Azure SDK which you can download from here: <a href="http://www.windowsazure.com/en-us/downloads/" target="_blank">http://www.windowsazure.com/en-us/downloads/</a>.</p>
<p>Other than that, I would strongly recommend going through <strong>development centers for different languages</strong> (<a href="http://www.windowsazure.com/en-us/documentation/" target="_blank">http://www.windowsazure.com/en-us/documentation/</a>) and trying out <strong>Windows Azure Training Kit</strong> (<a href="http://www.microsoft.com/en-US/download/details.aspx?id=8396" target="_blank">http://www.microsoft.com/en-US/download/details.aspx?id=8396</a>). Please ensure that you’re downloading the latest training kit.</p>
<h2>Summary</h2>
<p>That’s it for this post. Pretty long post, eh!!! In the subsequent posts, we’ll explore functionality in greater details. As always, your feedback is most welcome. If I have made a mistake in the post, please let me know and I’ll fix it ASAP.</p>
<img src="http://feeds.feedburner.com/~r/gmantri/~4/baam_Kgwong" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://gauravmantri.com/2013/04/12/windows-azure-primerbasics/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://gauravmantri.com/2013/04/12/windows-azure-primerbasics/</feedburner:origLink></item>
		<item>
		<title>Moving On – Goodbye Cerebrata, Hello Cynapta!</title>
		<link>http://feedproxy.google.com/~r/gmantri/~3/sVkBy-KGaOc/</link>
		<comments>http://gauravmantri.com/2013/03/29/moving-on-goodbye-cerebrata-hello-cynapta/#comments</comments>
		<pubDate>Thu, 28 Mar 2013 19:27:42 +0000</pubDate>
		<dc:creator>Gaurav</dc:creator>
				<category><![CDATA[Cerebrata]]></category>
		<category><![CDATA[Cynapta]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[Personal]]></category>
		<category><![CDATA[Red Gate]]></category>

		<guid isPermaLink="false">http://gauravmantri.com/?p=1183</guid>
		<description><![CDATA[Today’s my last day at Cerebrata. Wow!!! It has been an incredible journey for the last 5 years. I vividly remember when around the same time 5 years ago, I told my team in the US about my decision to move back to India to “do my own thing”. I was not 100% sure what [...]]]></description>
			<content:encoded><![CDATA[<p>Today’s my last day at Cerebrata. Wow!!! It has been an incredible journey for the last 5 years. I vividly remember when around the same time 5 years ago, I told my team in the US about my decision to move back to India to “<strong>do my own thing</strong>”. I was not 100% sure what I’ll be doing; there was no concrete plan – only thing I was sure of was to build a product development company in India. Never in my dream, I thought of achieving the success I achieved – First, built a pure product company that too in a small town in India. Second, successfully running and selling the company. Third, awarded Windows Azure MVP three years in a row. Honestly, I couldn’t have asked for more.</p>
<h2>Looking Back &#8211; Some Random Thoughts</h2>
<p>Looking back, some thoughts on few important things:</p>
<h3>On My Team</h3>
<p>You may get sick of hearing this thing but <strong>I’m really fond of my team</strong>! They trusted me with their careers and for that I&#8217;m grateful. Going down the memory lane, I see young graduates coming in becoming part of my dream and helping me achieve those. When they came in, they were raw out of college having no idea how industry worked. Now I look at them, I see them all grown up and thorough professionals. Together we built a culture of mutual respect and openness in the company and I thank them for that. I&#8217;ll always cherish their love, affection and adulation. They see me more as their mentor than their boss and I take pride in that. My only hope is that when their time comes, they would do the same. Only then, I would be able to pat my back. I’ll certainly miss working with them.</p>
<p><a href="http://gauravmantri.com/wp-content/uploads/2013/03/DSCF8988.jpg"><img style="display: inline; border: 0px;" title="DSCF8988" src="http://gauravmantri.com/wp-content/uploads/2013/03/DSCF8988_thumb.jpg" alt="DSCF8988" width="810" height="611" border="0" /></a></p>
<p style="text-align: center;">Picture of current &amp; ex-team members taken during our grand farewell party</p>
<h3>On Our Users</h3>
<p>Our products are successful only because of our users. Like I said in the past, neither I nor my team were experts in programming or Windows Azure for that matter but our users were, and they helped us shape our products. Our software had issues (in fact many issues) but our users were patient and were willing to help us out and I thank them from the bottom of my heart for that. Some of them worked with us diligently during the beta phases of our products while some of them found issues and provided resolutions in the released products. There were countless occasions where our users went out of the way to help us out from doing code reviews, providing solutions to just making our software better. My wish is to have same users helping me out in the next phase of my professional life.</p>
<h3>On Red Gate</h3>
<p>Prior to Red Gate, I was just an entrepreneur. <strong>Because of Red Gate, I am now a successful entrepreneur</strong>!!! I thank Red Gate for that. I’ve been working with them for past 18 months now (since the acquisition) and I can tell you they’re the best guys to work with. Not only these guys are real smart, their practice of “<strong>delightful user experience before anything else</strong>” is something I’ll take away from this relationship.</p>
<p>Every relationship has ups and downs and we had our share of the same as well. But they treated me like one of their own (in fact, sometimes better than their own). They simply pampered me. I’ve gone through many acquisitions in my professional career and generally speaking acquisitions suck (big time) however I can say that this was the best experience I had.</p>
<h3>On Microsoft</h3>
<p>We built products exclusively for Microsoft platform (that too Windows Azure only). If they wanted, they could have cannibalized us in no time but they didn’t, and I thank Microsoft for doing that. They really know how to build and nurture a true partner eco-system.</p>
<p>On top of that, they recognized the work I was doing in the community and awarded me with prestigious <strong>Most Valuable Professional (MVP)</strong> award. This is really huge for me!!!</p>
<p>One last thing I would like to mention about Microsoft is their <a href="http://www.microsoft.com/bizspark/" target="_blank">BizSpark</a> program. For a guy who was starting out on his own, I can’t tell you how valuable was it for me. Their MSDN subscription was a big boon for me. I was once doing an interview with somebody and he asked me about the biggest benefit of this program to me and my response was – <strong>BizSpark let me stay legit with software</strong> <img src='http://gauravmantri.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Otherwise it would have been tough!!! Anybody who’s starting out must try it out whether you love or hate Microsoft (or in other words whether or not building products for Microsoft platform).</p>
<p>Kind of cheesy confession: Back in the day when I was starting out, anybody with a <strong>microsoft.com</strong> email address was a celebrity in my eye <img src='http://gauravmantri.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . &lt;blush/&gt;</p>
<h2>Whats’ Next</h2>
<p>Next up for me is <strong>Cynapta</strong> (<a href="http://www.cynapta.com" target="_blank">http://www.cynapta.com</a> – really, there’s nothing to see there just yet). It’s my new company. I’ve some product ideas which I want to explore. Building products is more of a gamble and more than likely I will fail but I still want to scratch that itch (so to speak) <img src='http://gauravmantri.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . So wish me luck!!!</p>
<p>I’ll be building my team again from ground up so that should be an interesting experience to relive and I&#8217;m really looking forward to that. Hopefully I won’t make the same mistakes I made with my previous team.</p>
<p>Other than that, I would be spending my time on two of my favorite places on the Internet – MSDN Forums &amp; StackOverflow, and obviously on this blog sharing things and on Twitter.</p>
<p>Going forward, my Cerebrata email account won’t work (though Red Gate folks have been kind enough to keep it active and if you write to me there, you’ll probably get an OOF) so if you wish to reach out to me you can do so by writing me an email at gaurav @ cynapta.com.</p>
<h2>Closing Thoughts</h2>
<p>I would like to end this post thanking my team and our users. If I didn’t have the support and encouragement from you guys, I would not have been writing this post. So from the bottom of my heart (and one last time) thank you, thank you, thank you!!!</p>
<p>&lt;Taking a Bow/&gt;</p>
<p>Cheers!!!</p>
<img src="http://feeds.feedburner.com/~r/gmantri/~4/sVkBy-KGaOc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://gauravmantri.com/2013/03/29/moving-on-goodbye-cerebrata-hello-cynapta/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		<feedburner:origLink>http://gauravmantri.com/2013/03/29/moving-on-goodbye-cerebrata-hello-cynapta/</feedburner:origLink></item>
		<item>
		<title>Uploading Large Files in Windows Azure Blob Storage Using Shared Access Signature, HTML, and JavaScript</title>
		<link>http://feedproxy.google.com/~r/gmantri/~3/b_ie6IXW0ok/</link>
		<comments>http://gauravmantri.com/2013/02/16/uploading-large-files-in-windows-azure-blob-storage-using-shared-access-signature-html-and-javascript/#comments</comments>
		<pubDate>Sat, 16 Feb 2013 07:54:09 +0000</pubDate>
		<dc:creator>Gaurav</dc:creator>
				<category><![CDATA[HTML 5]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Shared Access Signature]]></category>
		<category><![CDATA[Windows Azure]]></category>
		<category><![CDATA[Windows Azure Blob Storage]]></category>

		<guid isPermaLink="false">http://gauravmantri.com/?p=1166</guid>
		<description><![CDATA[In my last post I talked about Shared Access Signature feature of Windows Azure Storage. You can read that post here: http://gauravmantri.com/2013/02/13/revisiting-windows-azure-shared-access-signature/. In this post we’ll put that to some practical use . One thing I wanted to accomplish recently is the ability to upload very large files into Windows Azure Blob Storage from a [...]]]></description>
			<content:encoded><![CDATA[<p>In my last post I talked about Shared Access Signature feature of Windows Azure Storage. You can read that post here: <a title="http://gauravmantri.com/2013/02/13/revisiting-windows-azure-shared-access-signature/" href="http://gauravmantri.com/2013/02/13/revisiting-windows-azure-shared-access-signature/" target="_blank">http://gauravmantri.com/2013/02/13/revisiting-windows-azure-shared-access-signature/</a>. In this post we’ll put that to some practical use <img src='http://gauravmantri.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p>One thing I wanted to accomplish recently is the ability to <strong>upload very large files into Windows Azure Blob Storage from a web application</strong>. General approach is to read the file through your web application using “<strong>File</strong>” HTML control and upload that entire file to some server side code which would then upload the file in blob storage. This approach would work best for smaller files but would fail terribly when it comes to moderately to very large files as the file upload control would upload the entire file to the server (for bigger files, this would cause timeouts depending on your Internet connection) and then that file resides in the server memory before any action can be taken on that file (again for bigger files, this would cause performance issues assuming you have thousands of users uploading thousands of large files).</p>
<p>In this blog post, we’ll talk about how we can accomplish that using <a href="http://www.w3.org/TR/file-upload/" target="_blank"><strong>File API</strong></a> feature in <strong>HTML5</strong>.</p>
<p>Please be warned that I’m no JavaScript/HTML/CSS expert <img src='http://gauravmantri.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . About 4 – 5 years ago I used to do a lot of JavaScript development and built some really insane applications using JavaScript (like mail merge kind of features, office automation, native device interfacing all using JS) but that was then. For last 4 – 5 years, I have been extensively doing desktop application development. So most of the JS code you’ll see below is copied from various sites and StackOverflow <img src='http://gauravmantri.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<h2>Objectives</h2>
<p>Following were some of the objectives I had in mind:</p>
<ol>
<li>The interface should be web based (possibly pure HTML). </li>
<li>I don’t have to share my storage account credentials with the end users. </li>
<li>If possible, there should not be any server side code (ASP.Net/PHP etc.) i.e. it should be pure HTML and the communication should be between user’s web browser and storage account. </li>
<li>If possible, the solution should upload the file in chunks so that bigger files can be uploaded without reading them in completely in a single go. </li>
</ol>
<p>Now let&#8217;s see how we can meet our objectives. </p>
<h2>Solution</h2>
<p>Here’re some of the things I did to achieve the objectives listed above.</p>
<h3>Chunking File</h3>
<p>The first challenge I ran into is how to upload the file in chunks. All the examples I saw were uploading an entire file however this is not what I wanted. Finally I ran into this example on <a href="http://www.html5rocks.com" target="_blank">HTML5 Rocks</a> where they talked about the <strong>File API</strong>: <a title="http://www.html5rocks.com/en/tutorials/file/dndfiles/" href="http://www.html5rocks.com/en/tutorials/file/dndfiles/" target="_blank">http://www.html5rocks.com/en/tutorials/file/dndfiles/</a>. Basically what caught my interest there is the “<a href="http://www.w3.org/TR/file-upload/#dfn-slice" target="_blank">slicing</a>” feature available in HTML 5’s <a href="http://www.w3.org/TR/file-upload/#dfn-file" target="_blank">File</a> interface. In short, <strong>what this slice feature does is that it reads a portion of a file asynchronously and returns that data</strong>. This is exactly I was looking at. Once I found that, I knew 75% of my work was done! Everything else was a breeze <img src='http://gauravmantri.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h3>Securing Storage Account Credentials</h3>
<p>Next thing on my list was securing storage account credentials and this was rather painless as I knew exactly what I had to do – <strong>Shared Access Signature</strong>. SAS provided me with a secured URI using which users will be able to upload files in my storage account without me giving them access to storage account credentials. This was covered extensively in my post about the same: <a href="http://gauravmantri.com/2013/02/13/revisiting-windows-azure-shared-access-signature/" target="_blank">Revisiting Windows Azure Shared Access Signature</a>.</p>
<h3>Direct Communication Between Client Application and Windows Azure Storage</h3>
<p>Next thing was to facilitate direct communication between the client application and storage. As we know Windows Azure Storage is built on REST so that means I can simply use AJAX functionality to communicate with REST API. One important thing to understand is that Windows Azure Storage still does not support <a href="http://en.wikipedia.org/wiki/Cross-origin_resource_sharing" target="_blank">Cross-Origin Resource Sharing (CORS)</a> at the time of writing this blog. What that means is that your web application and blob storage must be in the same domain. The solution to this problem is to <strong>host your HTML application in a public blob container in the same storage account where you want your users to upload the files</strong>. I’ve been told that CORS support is coming soon in Windows Azure Storage and once that happens then you need not host this application in that storage account but till then you would need to live with this limitation.</p>
<h2>The Code</h2>
<p>Now let’s look at the code.</p>
<h3>HTML Interface</h3>
<p>Since I was trying to hack my way through the code, I kept the interface rather simple. Here’s how my HTML code looks like:</p>
<p><pre class="brush: plain; title: ; notranslate">
&lt;body&gt;
    &lt;form&gt;
        &lt;div style=&quot;margin-left: 20px;&quot;&gt;
            &lt;h1&gt;File Uploader&lt;/h1&gt;
            &lt;p&gt;
                &lt;strong&gt;SAS URI&lt;/strong&gt;: 
                &lt;br/&gt;
                &lt;span class=&quot;input-control text&quot;&gt;
                    &lt;input type=&quot;text&quot; id=&quot;sasUrl&quot; style=&quot;width: 50%&quot;
                           value=&quot;&quot;/&gt;
                &lt;/span&gt;
            &lt;/p&gt;
            &lt;p&gt;
                &lt;strong&gt;File To Upload&lt;/strong&gt;: 
                &lt;br/&gt;
                &lt;span class=&quot;input-control text&quot;&gt;
                    &lt;input type=&quot;file&quot; id=&quot;file&quot; name=&quot;file&quot; style=&quot;width: 50%&quot;/&gt;
                &lt;/span&gt;
            &lt;/p&gt;
            &lt;div id=&quot;output&quot;&gt;
                
                &lt;strong&gt;File Properties:&lt;/strong&gt;
                &lt;br/&gt;
                &lt;p&gt;
                    Name: &lt;span id=&quot;fileName&quot;&gt;&lt;/span&gt;
                &lt;/p&gt;
                &lt;p&gt;
                    File Size: &lt;span id=&quot;fileSize&quot;&gt;&lt;/span&gt; bytes.
                &lt;/p&gt;
                &lt;p&gt;
                    File Type: &lt;span id=&quot;fileType&quot;&gt;&lt;/span&gt;
                &lt;/p&gt;
                &lt;p&gt;
                    &lt;input type=&quot;button&quot; value=&quot;Upload File&quot; onclick=&quot;uploadFileInBlocks()&quot;/&gt;
                &lt;/p&gt;
                &lt;p&gt;
                    &lt;strong&gt;Progress&lt;/strong&gt;: &lt;span id=&quot;fileUploadProgress&quot;&gt;0.00 %&lt;/span&gt;
                &lt;/p&gt;
            &lt;/div&gt;
        &lt;/div&gt;
        &lt;div&gt;
        &lt;/div&gt;
    &lt;/form&gt;
&lt;/body&gt;
</pre>
</p>
<p><a href="http://gauravmantri.com/wp-content/uploads/2013/02/image2.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; border-bottom-width: 0px; display: inline; border-top-width: 0px" border="0" alt="image" src="http://gauravmantri.com/wp-content/uploads/2013/02/image_thumb2.png" width="810" height="375" /></a> </p>
<p>All it has a textbox for a user to enter SAS URI and HTML File control. Once the user selects a file, I display the file properties and the “Upload” button to start uploading the file.</p>
<h3>Reading File Properties</h3>
<p>To display file properties, I made use of “<a href="http://www.w3schools.com/jsref/event_onchange.asp" target="_blank">onchange</a>” event of <a href="http://www.w3schools.com/jsref/dom_obj_fileupload.asp" target="_blank">File</a> element. The event gave me a list of files. Since I was uploading just one file, I picked up the first file from that list and got its name (blob would have that name), size (blob’s size and determining chunk size) and type (for setting blob’s content type property).</p>
<p><pre class="brush: plain; title: ; notranslate">
//Bind the change event.
$(&quot;#file&quot;).bind('change', handleFileSelect);

        
        //Read the file and find out how many blocks we would need to split it.
        function handleFileSelect(e) {
            var files = e.target.files;
            selectedFile = files[0];
            $(&quot;#fileName&quot;).text(selectedFile.name);
            $(&quot;#fileSize&quot;).text(selectedFile.size);
            $(&quot;#fileType&quot;).text(selectedFile.type);
        }


</pre>
</p>
<h3>Chunking</h3>
<p>In my application I made an assumption that I will split the file in chunks of 256 KB size. Once I found the file’s size, I just found out the total number of chunks.</p>
<p><pre class="brush: plain; title: ; notranslate">
        
        //Read the file and find out how many blocks we would need to split it.
        function handleFileSelect(e) {
            maxBlockSize = 256 * 1024;
            currentFilePointer = 0;
            totalBytesRemaining = 0;
            var files = e.target.files;
            selectedFile = files[0];
            $(&quot;#output&quot;).show();
            $(&quot;#fileName&quot;).text(selectedFile.name);
            $(&quot;#fileSize&quot;).text(selectedFile.size);
            $(&quot;#fileType&quot;).text(selectedFile.type);
            var fileSize = selectedFile.size;
            if (fileSize &lt; maxBlockSize) {
                maxBlockSize = fileSize;
                console.log(&quot;max block size = &quot; + maxBlockSize);
            }
            totalBytesRemaining = fileSize;
            if (fileSize % maxBlockSize == 0) {
                numberOfBlocks = fileSize / maxBlockSize;
            } else {
                numberOfBlocks = parseInt(fileSize / maxBlockSize, 10) + 1;
            }
            console.log(&quot;total blocks = &quot; + numberOfBlocks);
        }
</pre>
</p>
<h3>Endpoint for File Uploading</h3>
<p>The SAS URI actually represented a URI for blob container. Since I had to create an endpoint for uploading file, I split the URI (path and query) and appended the file name to the path and then re-appended the query to the end.</p>
<p><pre class="brush: plain; title: ; notranslate">
            var baseUrl = $(&quot;#sasUrl&quot;).val();
            var indexOfQueryStart = baseUrl.indexOf(&quot;?&quot;);
            submitUri = baseUrl.substring(0, indexOfQueryStart) + '/' + selectedFile.name + baseUrl.substring(indexOfQueryStart);
            console.log(submitUri);
</pre>
</p>
<h3>Reading Chunk</h3>
<p>This is where File API’s chunk function would come in picture. What happens in the code is that when the user clicks the upload button, I read a chunk of that file asynchronously and get a byte array. That byte array will be uploaded.</p>
<p><pre class="brush: plain; title: ; notranslate">

        var reader = new FileReader();
        var fileContent = selectedFile.slice(currentFilePointer, currentFilePointer + maxBlockSize);
        reader.readAsArrayBuffer(fileContent);
</pre>
</p>
<h3>Uploading Chunk</h3>
<p>Since I wanted to implement uploading in chunk, as soon as a chunk is read from the file, I create a <strong>Put Block</strong> request based on <a href="http://msdn.microsoft.com/en-us/library/windowsazure/dd135726.aspx" target="_blank">Put Block REST API</a> specification using jQuery’s AJAX function and pass that chunk as data. Once this request is successfully completed, I read the next chunk and repeat the process till the time all chunks are processed.</p>
<p><pre class="brush: plain; title: ; notranslate">
        reader.onloadend = function (evt) {
            if (evt.target.readyState == FileReader.DONE) { // DONE == 2
                var uri = submitUri + '&amp;comp=block&amp;blockid=' + blockIds[blockIds.length - 1];
                var requestData = new Uint8Array(evt.target.result);
                $.ajax({
                    url: uri,
                    type: &quot;PUT&quot;,
                    data: requestData,
                    processData: false,
                    beforeSend: function(xhr) {
                        xhr.setRequestHeader('x-ms-blob-type', 'BlockBlob');
                        xhr.setRequestHeader('Content-Length', requestData.length);
                    },
                    success: function (data, status) {
                        console.log(data);
                        console.log(status);
                        bytesUploaded += requestData.length;
                        var percentComplete = ((parseFloat(bytesUploaded) / parseFloat(selectedFile.size)) * 100).toFixed(2);
                        $(&quot;#fileUploadProgress&quot;).text(percentComplete + &quot; %&quot;);
                        uploadFileInBlocks();
                    },
                    error: function(xhr, desc, err) {
                        console.log(desc);
                        console.log(err);
                    }
                });
            }
        };
</pre>
</p>
<h3>Committing Blob</h3>
<p>Last step in this process is to commit the blob in blob storage. For this I create a <strong>Put Block List</strong> request based on <a href="http://msdn.microsoft.com/en-us/library/windowsazure/dd179467.aspx" target="_blank">Put Block List REST API</a> specification and process that request again using jQuery’s AJAX function and pass the block list as data. This completed the process.</p>
<p><pre class="brush: plain; title: ; notranslate">
        function commitBlockList() {
            var uri = submitUri + '&amp;comp=blocklist';
            console.log(uri);
            var requestBody = '&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;&lt;BlockList&gt;';
            for (var i = 0; i &lt; blockIds.length; i++) {
                requestBody += '&lt;Latest&gt;' + blockIds[i] + '&lt;/Latest&gt;';
            }
            requestBody += '&lt;/BlockList&gt;';
            console.log(requestBody);
            $.ajax({
                url: uri,
                type: &quot;PUT&quot;,
                data: requestBody,
                beforeSend: function (xhr) {
                    xhr.setRequestHeader('x-ms-blob-content-type', selectedFile.type);
                    xhr.setRequestHeader('Content-Length', requestBody.length);
                },
                success: function (data, status) {
                    console.log(data);
                    console.log(status);
                },
                error: function (xhr, desc, err) {
                    console.log(desc);
                    console.log(err);
                }
            });
</pre>
</p>
<h3>Complete Code</h3>
<p>Here’s the complete code. For CSS, I actually used <strong>Metro UI CSS</strong> &#8211; <a title="http://metroui.org.ua/" href="http://metroui.org.ua/">http://metroui.org.ua/</a>. If you’re planning on building web applications and want to give them Windows 8 applications style look and feel, do give it a try. It’s pretty awesome + it’s open source. Really no reason for you to not give it a try!</p>
<p><pre class="brush: plain; title: ; notranslate">
&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
&lt;head&gt;
    &lt;title&gt;File Uploader&lt;/title&gt;
    &lt;script src=&quot;js/jquery-1.7.1.js&quot;&gt;&lt;/script&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;css/modern.css&quot;/&gt;
    &lt;script&gt;
        var maxBlockSize = 256 * 1024;//Each file will be split in 256 KB.
        var numberOfBlocks = 1;
        var selectedFile = null;
        var currentFilePointer = 0;
        var totalBytesRemaining = 0;
        var blockIds = new Array();
        var blockIdPrefix = &quot;block-&quot;;
        var submitUri = null;
        var bytesUploaded = 0;
        
        $(document).ready(function () {
            $(&quot;#output&quot;).hide();
            $(&quot;#file&quot;).bind('change', handleFileSelect);
            if (window.File &amp;&amp; window.FileReader &amp;&amp; window.FileList &amp;&amp; window.Blob) {
                // Great success! All the File APIs are supported.
            } else {
                alert('The File APIs are not fully supported in this browser.');
            }
        });
        
        //Read the file and find out how many blocks we would need to split it.
        function handleFileSelect(e) {
            maxBlockSize = 256 * 1024;
            currentFilePointer = 0;
            totalBytesRemaining = 0;
            var files = e.target.files;
            selectedFile = files[0];
            $(&quot;#output&quot;).show();
            $(&quot;#fileName&quot;).text(selectedFile.name);
            $(&quot;#fileSize&quot;).text(selectedFile.size);
            $(&quot;#fileType&quot;).text(selectedFile.type);
            var fileSize = selectedFile.size;
            if (fileSize &lt; maxBlockSize) {
                maxBlockSize = fileSize;
                console.log(&quot;max block size = &quot; + maxBlockSize);
            }
            totalBytesRemaining = fileSize;
            if (fileSize % maxBlockSize == 0) {
                numberOfBlocks = fileSize / maxBlockSize;
            } else {
                numberOfBlocks = parseInt(fileSize / maxBlockSize, 10) + 1;
            }
            console.log(&quot;total blocks = &quot; + numberOfBlocks);
            var baseUrl = $(&quot;#sasUrl&quot;).val();
            var indexOfQueryStart = baseUrl.indexOf(&quot;?&quot;);
            submitUri = baseUrl.substring(0, indexOfQueryStart) + '/' + selectedFile.name + baseUrl.substring(indexOfQueryStart);
            console.log(submitUri);
        }

        var reader = new FileReader();

        reader.onloadend = function (evt) {
            if (evt.target.readyState == FileReader.DONE) { // DONE == 2
                var uri = submitUri + '&amp;comp=block&amp;blockid=' + blockIds[blockIds.length - 1];
                var requestData = new Uint8Array(evt.target.result);
                $.ajax({
                    url: uri,
                    type: &quot;PUT&quot;,
                    data: requestData,
                    processData: false,
                    beforeSend: function(xhr) {
                        xhr.setRequestHeader('x-ms-blob-type', 'BlockBlob');
                        xhr.setRequestHeader('Content-Length', requestData.length);
                    },
                    success: function (data, status) {
                        console.log(data);
                        console.log(status);
                        bytesUploaded += requestData.length;
                        var percentComplete = ((parseFloat(bytesUploaded) / parseFloat(selectedFile.size)) * 100).toFixed(2);
                        $(&quot;#fileUploadProgress&quot;).text(percentComplete + &quot; %&quot;);
                        uploadFileInBlocks();
                    },
                    error: function(xhr, desc, err) {
                        console.log(desc);
                        console.log(err);
                    }
                });
            }
        };

        function uploadFileInBlocks() {
            if (totalBytesRemaining &gt; 0) {
                console.log(&quot;current file pointer = &quot; + currentFilePointer + &quot; bytes read = &quot; + maxBlockSize);
                var fileContent = selectedFile.slice(currentFilePointer, currentFilePointer + maxBlockSize);
                var blockId = blockIdPrefix + pad(blockIds.length, 6);
                console.log(&quot;block id = &quot; + blockId);
                blockIds.push(btoa(blockId));
                reader.readAsArrayBuffer(fileContent);
                currentFilePointer += maxBlockSize;
                totalBytesRemaining -= maxBlockSize;
                if (totalBytesRemaining &lt; maxBlockSize) {
                    maxBlockSize = totalBytesRemaining;
                }
            } else {
                commitBlockList();
            }
        }
        
        function commitBlockList() {
            var uri = submitUri + '&amp;comp=blocklist';
            console.log(uri);
            var requestBody = '&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;&lt;BlockList&gt;';
            for (var i = 0; i &lt; blockIds.length; i++) {
                requestBody += '&lt;Latest&gt;' + blockIds[i] + '&lt;/Latest&gt;';
            }
            requestBody += '&lt;/BlockList&gt;';
            console.log(requestBody);
            $.ajax({
                url: uri,
                type: &quot;PUT&quot;,
                data: requestBody,
                beforeSend: function (xhr) {
                    xhr.setRequestHeader('x-ms-blob-content-type', selectedFile.type);
                    xhr.setRequestHeader('Content-Length', requestBody.length);
                },
                success: function (data, status) {
                    console.log(data);
                    console.log(status);
                },
                error: function (xhr, desc, err) {
                    console.log(desc);
                    console.log(err);
                }
            });

        }
        function pad(number, length) {
            var str = '' + number;
            while (str.length &lt; length) {
                str = '0' + str;
            }
            return str;
        }
    &lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form&gt;
        &lt;div style=&quot;margin-left: 20px;&quot;&gt;
            &lt;h1&gt;File Uploader&lt;/h1&gt;
            &lt;p&gt;
                &lt;strong&gt;SAS URI&lt;/strong&gt;: 
                &lt;br/&gt;
                &lt;span class=&quot;input-control text&quot;&gt;
                    &lt;input type=&quot;text&quot; id=&quot;sasUrl&quot; style=&quot;width: 50%&quot;
                           value=&quot;&quot;/&gt;
                &lt;/span&gt;
            &lt;/p&gt;
            &lt;p&gt;
                &lt;strong&gt;File To Upload&lt;/strong&gt;: 
                &lt;br/&gt;
                &lt;span class=&quot;input-control text&quot;&gt;
                    &lt;input type=&quot;file&quot; id=&quot;file&quot; name=&quot;file&quot; style=&quot;width: 50%&quot;/&gt;
                &lt;/span&gt;
            &lt;/p&gt;
            &lt;div id=&quot;output&quot;&gt;
                
                &lt;strong&gt;File Properties:&lt;/strong&gt;
                &lt;br/&gt;
                &lt;p&gt;
                    Name: &lt;span id=&quot;fileName&quot;&gt;&lt;/span&gt;
                &lt;/p&gt;
                &lt;p&gt;
                    File Size: &lt;span id=&quot;fileSize&quot;&gt;&lt;/span&gt; bytes.
                &lt;/p&gt;
                &lt;p&gt;
                    File Type: &lt;span id=&quot;fileType&quot;&gt;&lt;/span&gt;
                &lt;/p&gt;
                &lt;p&gt;
                    &lt;input type=&quot;button&quot; value=&quot;Upload File&quot; onclick=&quot;uploadFileInBlocks()&quot;/&gt;
                &lt;/p&gt;
                &lt;p&gt;
                    &lt;strong&gt;Progress&lt;/strong&gt;: &lt;span id=&quot;fileUploadProgress&quot;&gt;0.00 %&lt;/span&gt;
                &lt;/p&gt;
            &lt;/div&gt;
        &lt;/div&gt;
        &lt;div&gt;
        &lt;/div&gt;
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
</p>
<h2>Some Caveats</h2>
<p>This makes use of HTML5 File API and while all new browsers support that, same can’t be said about older browsers. If your users would be accessing an application like this using older browsers, you would need to think about alternative approaches. You could either make use of <a href="http://code.google.com/p/swfupload/" target="_blank">SWF File Uploader</a> or could write an application using Silverlight. Steve Marx wrote a blog post about uploading files using Shared Access Signature and Silverlight which you can read here: <a title="http://blog.smarx.com/posts/uploading-windows-azure-blobs-from-silverlight-part-1-shared-access-signatures" href="http://blog.smarx.com/posts/uploading-windows-azure-blobs-from-silverlight-part-1-shared-access-signatures" target="_blank">http://blog.smarx.com/posts/uploading-windows-azure-blobs-from-silverlight-part-1-shared-access-signatures</a>.</p>
<p>I found the code working in <strong>IE 10</strong>, <strong>Google Chrome (version 24.0.1312.57 m)</strong> on my Windows 8 machine. I got error when I tried to run the code in <strong>FireFox (version 18.0.2)</strong> and <strong>Safari (version 5.1.7)</strong> browsers so obviously one would need to keep the browser incompatibility in mind.</p>
<h2>Enhancements</h2>
<p>I hacked this code in about 4 hours or so and obviously my knowledge is somewhat limited when it comes to JavaScript and CSS so a lot can be improved on that front <img src='http://gauravmantri.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . However some other features I could think of are:</p>
<p><strong>Generate SAS on demand</strong>: You could possibly have a server side component which would generate SAS URI on demand instead of having a user enter that manually.</p>
<p><strong>Multiple file uploads</strong>: This application can certainly be extended to upload multiple files. A user would select multiple files (or may be even a folder) and have the application upload multiple files.</p>
<p><strong>Drag/drop support</strong>: This application can certainly be extended to support drag/drop scenario where users could drag files from their desktop and drop them to upload.</p>
<p><strong>Do upload in Web Worker</strong>: This is another improvement that can be done where uploads are done through <a href="http://www.w3schools.com/html/html5_webworkers.asp" target="_blank">web worker</a> capability in HTML5.</p>
<p><strong>Parallel uploads</strong>: Currently the code uploads one chunk at a time. A modification could be to upload multiple chunks simultaneously.</p>
<p><strong>Transient error handling</strong>: Since Windows Azure Storage is a remote shared resource, you may encounter transient errors. You could modify the application to handle these transient errors. For more details on transient errors, please see this blog post of mine: <a title="http://gauravmantri.com/2013/01/11/some-best-practices-for-building-windows-azure-cloud-applications/" href="http://gauravmantri.com/2013/01/11/some-best-practices-for-building-windows-azure-cloud-applications/" target="_blank">http://gauravmantri.com/2013/01/11/some-best-practices-for-building-windows-azure-cloud-applications/</a>.</p>
<h2>Summary</h2>
<p>So that’s it for this post! As you saw, it is quite easy to implement a very simple HTML/JS based application for getting data into Windows Azure Blob Storage. Obviously there’re some limitations and there’s cross-browser compatibility issues one would need to consider but once those are sorted out, it opens up a lot of exciting opportunities. I hope you’ve found this post useful. As always, if you find any issues with the post please let me know and I’ll fix it ASAP.</p>
<p>Happy Coding!</p>
<img src="http://feeds.feedburner.com/~r/gmantri/~4/b_ie6IXW0ok" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://gauravmantri.com/2013/02/16/uploading-large-files-in-windows-azure-blob-storage-using-shared-access-signature-html-and-javascript/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		<feedburner:origLink>http://gauravmantri.com/2013/02/16/uploading-large-files-in-windows-azure-blob-storage-using-shared-access-signature-html-and-javascript/</feedburner:origLink></item>
		<item>
		<title>Revisiting Windows Azure Shared Access Signature</title>
		<link>http://feedproxy.google.com/~r/gmantri/~3/qS1G7Gj7umI/</link>
		<comments>http://gauravmantri.com/2013/02/13/revisiting-windows-azure-shared-access-signature/#comments</comments>
		<pubDate>Wed, 13 Feb 2013 08:03:14 +0000</pubDate>
		<dc:creator>Gaurav</dc:creator>
				<category><![CDATA[Shared Access Signature]]></category>
		<category><![CDATA[Windows Azure]]></category>
		<category><![CDATA[Windows Azure Blob Storage]]></category>
		<category><![CDATA[Windows Azure Queue Service]]></category>
		<category><![CDATA[Windows Azure Storage]]></category>
		<category><![CDATA[Windows Azure Table Service]]></category>
		<category><![CDATA[Valet Key Pattern]]></category>
		<category><![CDATA[Windows Azure Queues]]></category>
		<category><![CDATA[Windows Azure Table Storage]]></category>

		<guid isPermaLink="false">http://gauravmantri.com/?p=1149</guid>
		<description><![CDATA[In this blog post, we’ll talk about Shared Access Signature (SAS) functionality in Windows Azure. Steve Marx (@smarx) wrote excellent blog posts on the same subject a few years ago which you can read here: http://blog.smarx.com/posts/shared-access-signatures-are-easy-these-days, http://blog.smarx.com/posts/uploading-windows-azure-blobs-from-silverlight-part-1-shared-access-signatures. However a lot has changed since Steve wrote the posts and I thought it might be useful to [...]]]></description>
			<content:encoded><![CDATA[<p>In this blog post, we’ll talk about <strong>Shared Access Signature (SAS)</strong> functionality in <strong>Windows Azure</strong>. Steve Marx (<a href="http://twitter.com/smarx" target="_blank">@smarx</a>) wrote excellent blog posts on the same subject a few years ago which you can read here: <a href="http://blog.smarx.com/posts/shared-access-signatures-are-easy-these-days" target="_blank">http://blog.smarx.com/posts/shared-access-signatures-are-easy-these-days</a>, <a href="http://blog.smarx.com/posts/uploading-windows-azure-blobs-from-silverlight-part-1-shared-access-signatures" target="_blank">http://blog.smarx.com/posts/uploading-windows-azure-blobs-from-silverlight-part-1-shared-access-signatures</a>. However a lot has changed since Steve wrote the posts and I thought it might be useful to write about it taking those new things into consideration (hence the word “Revisiting” in the title <img src='http://gauravmantri.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> ). This blog will start with a basic explanation of shared access signature and the purpose it serves and then I will show you some code to perform some basic operations against Windows Azure Storage especially Blob Storage.</p>
<p>Now that the agenda is set, let’s start <img src='http://gauravmantri.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h2>Shared Access Signature (SAS) – Why and What?</h2>
<p>This section describes why we need SAS and what exactly it is. If you’re familiar with these concepts, please feel free to skip this section otherwise read on!</p>
<h3>Why?</h3>
<p>First let’s understand why we need SAS. As you may already know that access to Windows Azure Storage is not anonymous. Rather you would need an “<strong>account key</strong>” to access resources in a Storage Account. This account key (actually there&#8217;re 2 account keys &#8211; primary and secondary) is generated automatically for you by Windows Azure Storage and you also get the ability to regenerate the key on demand. The problem with account key based access is that the account key grants “Admin” privileges on the storage account in question. Anybody who has access to this account key can perform any allowed operation on the storage account. This is obviously a security concern and one must attempt to keep the account key secret at all times and guard it with full zeal.</p>
<p>However there’re scenarios where you would want to grant a user (who may be a partner or a customer etc.) restricted access to your storage account. You would that user to perform only a few operations and that too for a limited amount of time. Obviously handing that user your account key won’t do you any good because that would make the user an admin. The answer to this problem is SAS. <b>A SAS allows you to grant temporary access to private resources in your storage account</b>.</p>
<p>I was recently reading a book by <b>Bill Wilder</b> (<a href="https://twitter.com/codingoutloud" target="_blank">@codingoutloud</a>) on <b><a href="http://shop.oreilly.com/product/0636920023777.do" target="_blank">Cloud Architecture Patterns</a></b> and he has explained this concept very nicely by using a “<b>Valet Key</b>” analogy. If you’re planning on building a cloud application in Windows Azure, I would strongly recommend reading this book first before writing code.</p>
<h3>What?</h3>
<p><strong>Simply put, SAS is a URL (or rather a part of it). You, as a creator of SAS define the validity duration of SAS and what a user in possession of this SAS can do with the resources protected by SAS</strong>. For example, you could define a SAS which would allow a user to upload a file into a blob container in your storage account and would expire after say 1 hour. Within that hour for which the SAS is valid, any user who has access to this SAS will be able to upload the files in the blob container. After that hour, the link will become useless.</p>
<p>You could create a SAS for a blob resources (blob containers and blobs), table resources (table and PartitionKey/RowKey ranges) and queue resources (queues and messages). You could give one or more of CRUD operation permissions in a SAS. Lastly, you could define a start and an end date for which the SAS is valid. </p>
<p>With blob storage, you could create a SAS for a blob container or a blob. Following table summarizes the permissions and the purpose they serve on various blob resources:</p>
<table cellspacing="0" cellpadding="2" border="1">
<tbody>
<tr bgcolor="#dfdfdf">
<td valign="top" width="20%">
<p><strong>Permission Type</strong></p>
</td>
<td valign="top" width="40%">
<p><strong>Blob Container</strong></p>
</td>
<td valign="top" width="40%">
<p><strong>Blob</strong></p>
</td>
</tr>
<tr>
<td valign="top" width="20%">
<p>Read</p>
</td>
<td valign="top" width="40%">
<p>Not applicable on blob container.</p>
</td>
<td valign="top" width="40%">
<p>Gives the ability to read the contents of the blob. Also gives the ability to read the metadata and properties of the blob as well.</p>
</td>
</tr>
<tr>
<td valign="top" width="20%">
<p>Write</p>
</td>
<td valign="top" width="40%">
<p>Gives the ability to upload one or more blobs in blob container. Also gives the ability to update properties, metadata and create snapshots of a blob.</p>
</td>
<td valign="top" width="40%">
<p>Give the ability to upload a new blob (by the same name) or overwrite an existing blob (by the same name). Also gives the ability to update properties, metadata and create snapshots of a blob.</p>
</td>
</tr>
<tr>
<td valign="top" width="20%">
<p>List</p>
</td>
<td valign="top" width="40%">
<p>Lists the blobs in the blob container.</p>
</td>
<td valign="top" width="40%">
<p>Not applicable on blobs.</p>
</td>
</tr>
<tr>
<td valign="top" width="20%">
<p>Delete</p>
</td>
<td valign="top" width="40%">
<p>Not applicable on blob container.</p>
</td>
<td valign="top" width="40%">
<p>Gives the ability to delete the blob.</p>
</td>
</tr>
</tbody>
</table>
<p>
<br/><br />
<strong>Update &#8211; 22nd Feb 2013:</strong><br />
By &#8220;<strong>Not applicable on blob container</strong>&#8221; what I mean is that using a SAS that particular operation can&#8217;t be performed on the blob container in question. For example, &#8220;Delete&#8221; permission in SAS on a blob container will not allow the users to delete that blob container. One would need to use storage account credentials to delete the blob container.
</p>
<p>With table storage, you could create a SAS for a table or entity ranges in a table. For entity ranges, you could specify PartitionKey/RowKey ranges. Following table summarizes the permissions and the purpose they serve on various table resources:    </p>
<table cellspacing="0" cellpadding="2" border="1">
<tbody>
<tr bgcolor="#dfdfdf">
<td valign="top" width="20%">
<p><strong>Permission Type</strong></p>
</td>
<td valign="top" width="40%">
<p><strong>Table</strong></p>
</td>
<td valign="top" width="40%">
<p><strong>Entity Ranges (PartitionKey/RowKey Ranges)</strong></p>
</td>
</tr>
<tr>
<td valign="top" width="20%">
<p>Query</p>
</td>
<td valign="top" width="40%">
<p>Gives the ability to query the table.</p>
</td>
<td valign="top" width="40%">
<p>Gives the ability to query a table but the query is limited to entity range specified in the SAS.</p>
</td>
</tr>
<tr>
<td valign="top" width="20%">
<p>Add</p>
</td>
<td valign="top" width="40%">
<p>Gives the ability to add an entity to the table.</p>
</td>
<td valign="top" width="40%">
<p>Gives the ability to add an entity to the table provided the entity’s PartitionKey/RowKey values are within range.</p>
</td>
</tr>
<tr>
<td valign="top" width="20%">
<p>Update</p>
</td>
<td valign="top" width="40%">
<p>Gives the ability to update an entity in the table.</p>
</td>
<td valign="top" width="40%">
<p>Gives the ability to update an entity in the table provided the entity’s PartitionKey/RowKey values are within range.</p>
</td>
</tr>
<tr>
<td valign="top" width="20%">
<p>Delete</p>
</td>
<td valign="top" width="40%">
<p>Gives the ability to delete an entity from the table.</p>
</td>
<td valign="top" width="40%">
<p>Gives the ability to delete an entity from the table provided the entity’s PartitionKey/RowKey values are within range.</p>
</td>
</tr>
</tbody>
</table>
<p>&#160;</p>
<p>With queue storage, you could create a SAS for a queue. Following table summarizes the permissions and the purpose they serve on queue resources:    </p>
<table cellspacing="0" cellpadding="2" border="1">
<tbody>
<tr bgcolor="#dfdfdf">
<td valign="top" width="20%">
<p><strong>Permission Type</strong></p>
</td>
<td valign="top" width="80%">
<p><strong>Queue</strong></p>
</td>
</tr>
<tr>
<td valign="top" width="20%">
<p>Read or Peek</p>
</td>
<td valign="top" width="80%">
<p>Gives the ability to peek at the messages in the queue. Please note that peek messages functionality allows the user to view messages in “Read-Only” mode and does not alter the visibility of the messages.</p>
</td>
</tr>
<tr>
<td valign="top" width="20%">
<p>Add</p>
</td>
<td valign="top" width="80%">
<p>Gives the ability to add messages in the queue.</p>
</td>
</tr>
<tr>
<td valign="top" width="20%">
<p>Process</p>
</td>
<td valign="top" width="80%">
<p>Gives the ability to get messages from the queue. Please note that this would give users the ability to delete the messages as well and it alters the visibility of the messages.</p>
</td>
</tr>
<tr>
<td valign="top" width="20%">
<p>Update</p>
</td>
<td valign="top" width="80%">
<p>Gives the ability to update a message in the queue. For this permission, Process permission is required.</p>
</td>
</tr>
</tbody>
</table>
<p>&#160;</p>
<p>A few more comments about SAS before we jump into the code <img src='http://gauravmantri.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<h4>Revocable SAS</h4>
<p>You could make a SAS revocable. What that means is that you could make a SAS invalid before its expiry time. This is achieved through what is known as “<b><a href="http://msdn.microsoft.com/en-us/library/windowsazure/ee393341.aspx">Blob Container Access Policy</a></b>”. When you create a SAS using blob container access policy, to revoke the SAS, you could just change the access policy identifier or delete that access policy all together. At the time of writing, a blob container can have a maximum of 5 access policies.</p>
<h4>Anonymous SAS</h4>
<p>When a SAS is created without a blob container access policy, it’s called anonymous SAS. Since these are not revocable, proper care must be taken in handling this SAS. Generally speaking, you should try and create very short duration anonymous SAS.</p>
<h4>Never Expiring SAS</h4>
<p><strong>Though not a recommended practice</strong>, it is possible to create a SAS which never expires. To achieve this, you don’t specify the expiry date when creating SAS. In the earlier version of storage service, only revocable SAS can be never expiring and anonymous SAS are only valid for 1 hour duration. However with the latest version of storage service, it is possible to create never expiring anonymous SAS.</p>
<h4>SAS Start Date/Time</h4>
<p>Please note that SAS start and expiry date/time are in UTC. Furthermore these are validated in Windows Azure. There may be a possibility that there may be a mismatch between time on your local computer (where SAS is generated) and time in Windows Azure. To counter this issue, it is generally recommended that you make your SAS start time by subtracting about 5 – 10 minutes from your local computer’s time (in UTC). For example:</p>
<p><pre class="brush: plain; title: ; notranslate">
            var sas = blobContainer.GetSharedAccessSignature(new SharedAccessBlobPolicy()
                {
                    Permissions = permission,
                    SharedAccessStartTime = DateTime.UtcNow.AddMinutes(-5),//SAS Start time is back by 5 minutes to take clock skewness into consideration
                    SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(15),
                });
</pre>
</p>
<p>
<strong>Update &#8211; 22nd Feb 2013:</strong><br />
Please note that SAS start time is optional and if you want the SAS to be valid immediately, you can omit this parameter.
</p>
<p>MSDN has nice documentation about SAS functionality and much more which I recommend you to read: <a title="http://msdn.microsoft.com/en-us/library/windowsazure/ee393343.aspx" href="http://msdn.microsoft.com/en-us/library/windowsazure/ee393343.aspx" target="_blank">http://msdn.microsoft.com/en-us/library/windowsazure/ee393343.aspx</a></p>
<h2>The Code! </h2>
<p>OK, enough talking! Let’s see some code. In the code examples below, I have used latest version of storage client library (2.0.4 at the time of writing this post). I’ve used the storage client library to create SAS URIs however you could use tools like <a href="http://www.cerebrata.com/" target="_blank">Cloud Storage Studio</a> which supports this functionality. Then using that SAS URI, I’m going to demonstrate how you’re going to perform some common operations against blob storage. For each operation, I’ve included how you’re going to perform the operation using storage client library as well as if you’re going to do this by consuming REST API directly using HttpWebRequest/HttpWebResponse. The common theme with storage client library is that it allows you to create instances of <a href="http://msdn.microsoft.com/en-us/library/jj733012.aspx" target="_blank">CloudBlobContainer</a> and <a href="http://msdn.microsoft.com/en-us/library/microsoft.windowsazure.storage.blob.cloudblockblob.aspx" target="_blank">CloudBlockBlob</a> (I’ve focused only on block blobs in this post) using the SAS URI only. Again for simplicity, I just went with anonymous SAS and did not use blob container access policy for creating SAS URIs.</p>
<h3>Helper Functions</h3>
<p>I created two helper functions to create SAS on a blob container and blob. For the sake of simplicity, I hard coded the start and expiry time for SAS:</p>
<p><pre class="brush: plain; title: ; notranslate">
        /// &lt;summary&gt;
        /// Creates a SAS URI for the blob container.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;blobContainer&quot;&gt;&lt;/param&gt;
        /// &lt;param name=&quot;permission&quot;&gt;&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        static string GetSaSForBlobContainer(CloudBlobContainer blobContainer, SharedAccessBlobPermissions permission)
        {
            var sas = blobContainer.GetSharedAccessSignature(new SharedAccessBlobPolicy()
                {
                    Permissions = permission,
                    SharedAccessStartTime = DateTime.UtcNow.AddMinutes(-5),//SAS Start time is back by 5 minutes to take clock skewness into consideration
                    SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(15),
                });
            return string.Format(CultureInfo.InvariantCulture, &quot;{0}{1}&quot;, blobContainer.Uri, sas);
        }
</pre>
</p>
<p><pre class="brush: plain; title: ; notranslate">
        /// &lt;summary&gt;
        /// Creates a SAS URI for the blob.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;blob&quot;&gt;&lt;/param&gt;
        /// &lt;param name=&quot;permission&quot;&gt;&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        static string GetSaSForBlob(CloudBlockBlob blob, SharedAccessBlobPermissions permission)
        {
            var sas = blob.GetSharedAccessSignature(new SharedAccessBlobPolicy()
            {
                Permissions = permission,
                SharedAccessStartTime = DateTime.UtcNow.AddMinutes(-5),
                SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(15),
            });
            return string.Format(CultureInfo.InvariantCulture, &quot;{0}{1}&quot;, blob.Uri, sas);
        }
</pre>
</p>
<h3>Listing Blobs</h3>
<p>Here’s the code for listing blobs in a blob container. For listing blobs, “<strong>List</strong>” permission must be defined in SAS.</p>
<h4>Using Storage Client Library</h4>
<p><pre class="brush: plain; title: ; notranslate">
        /// &lt;summary&gt;
        /// List blobs in a blob container using storage client library.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;blobContainerSasUri&quot;&gt;&lt;/param&gt;
        static void ListBlobsWithStorageClientLibrary(string blobContainerSasUri)
        {
            CloudBlobContainer blobContainer = new CloudBlobContainer(new Uri(blobContainerSasUri));
            var blobs = blobContainer.ListBlobs(null, true);
            foreach (var blob in blobs)
            {
                Console.WriteLine(blob.Uri);
            }
        }
</pre>
</p>
<h4>Using REST API</h4>
<p><pre class="brush: plain; title: ; notranslate">
        /// &lt;summary&gt;
        /// List blobs in a blob container using REST API.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;blobContainerSasUri&quot;&gt;&lt;/param&gt;
        static void ListBlobsWithRestAPI(string blobContainerSasUri)
        {
            string requestUri = string.Format(CultureInfo.InvariantCulture, &quot;{0}&amp;comp=list&quot;, blobContainerSasUri);
            HttpWebRequest request = (HttpWebRequest) WebRequest.Create(requestUri);
            request.Method = &quot;GET&quot;;
            using (HttpWebResponse resp = (HttpWebResponse) request.GetResponse())
            {
                using (Stream s = resp.GetResponseStream())
                {
                    using (StreamReader reader = new StreamReader(s, true))
                    {
                        string blobsData = reader.ReadToEnd();
                        Console.WriteLine(blobsData);
                    }
                }
            }
        }
</pre>
</p>
<p>You must append “<strong>&amp;comp=list</strong>” to the URI for listing blob containers. Also the output is XML. </p>
<p>I could just take the URI (in requestUri variable above) and paste it in browser’s address window and see the list of blobs in the blob container. See screenshot below for example.</p>
<p><a href="http://gauravmantri.com/wp-content/uploads/2013/02/image1.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; border-bottom-width: 0px; display: inline; border-top-width: 0px" border="0" alt="image" src="http://gauravmantri.com/wp-content/uploads/2013/02/image_thumb1.png" width="810" height="375" /></a> </p>
<h3>Upload Blobs</h3>
<p>Here’s the code for uploading a blob in a blob container. For uploading a blob, you could create a SAS with “<strong>Write</strong>” permission on either a blob container or a blob. The blob need not be present in the blob container. If the blob is not present, it will be created otherwise it will be overwritten.</p>
<h4>Using Storage Client Library</h4>
<p><pre class="brush: plain; title: ; notranslate">
        /// &lt;summary&gt;
        /// Uploads a blob in a blob container where SAS permission is defined on a blob container using storage client library.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;blobContainerSasUri&quot;&gt;&lt;/param&gt;
        static void UploadBlobWithStorageClientLibrarySasPermissionOnBlobContainer(string blobContainerSasUri)
        {
            CloudBlobContainer blobContainer = new CloudBlobContainer(new Uri(blobContainerSasUri));
            CloudBlockBlob blob = blobContainer.GetBlockBlobReference(&quot;sample.txt&quot;);
            string sampleContent = &quot;This is sample text.&quot;;
            using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(sampleContent)))
            {
                blob.UploadFromStream(ms);
            }
        }
</pre>
</p>
<p><pre class="brush: plain; title: ; notranslate">
        /// &lt;summary&gt;
        /// Uploads a blob in a blob container where SAS permission is defined on a blob using storage client library.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;blobSasUri&quot;&gt;&lt;/param&gt;
        static void UploadBlobWithStorageClientLibrarySasPermissionOnBlob(string blobSasUri)
        {
            CloudBlockBlob blob = new CloudBlockBlob(new Uri(blobSasUri));
            string sampleContent = &quot;This is sample text.&quot;;
            using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(sampleContent)))
            {
                blob.UploadFromStream(ms);
            }
        }
</pre>
</p>
<h4>Using REST API</h4>
<p><pre class="brush: plain; title: ; notranslate">
        /// &lt;summary&gt;
        /// Uploads a blob in a blob container where SAS permission is defined on a blob container using REST API.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;blobContainerSasUri&quot;&gt;&lt;/param&gt;
        static void UploadBlobWithRestAPISasPermissionOnBlobContainer(string blobContainerSasUri)
        {
            string blobName = &quot;sample.txt&quot;;
            string sampleContent = &quot;This is sample text.&quot;;
            int contentLength = Encoding.UTF8.GetByteCount(sampleContent);
            string queryString = (new Uri(blobContainerSasUri)).Query;
            string blobContainerUri = blobContainerSasUri.Substring(0, blobContainerSasUri.Length - queryString.Length);
            string requestUri = string.Format(CultureInfo.InvariantCulture, &quot;{0}/{1}{2}&quot;, blobContainerUri, blobName, queryString);
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUri);
            request.Method = &quot;PUT&quot;;
            request.Headers.Add(&quot;x-ms-blob-type&quot;, &quot;BlockBlob&quot;);
            request.ContentLength = contentLength;
            using (Stream requestStream = request.GetRequestStream())
            {
                requestStream.Write(Encoding.UTF8.GetBytes(sampleContent), 0, contentLength);
            }
            using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse())
            {
                
            }
        }
</pre>
</p>
<p><pre class="brush: plain; title: ; notranslate">
        /// &lt;summary&gt;
        /// Uploads a blob in a blob container where SAS permission is defined on a blob using REST API.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;blobSasUri&quot;&gt;&lt;/param&gt;
        static void UploadBlobWithRestAPISasPermissionOnBlob(string blobSasUri)
        {
            string sampleContent = &quot;This is sample text.&quot;;
            int contentLength = Encoding.UTF8.GetByteCount(sampleContent);
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(blobSasUri);
            request.Method = &quot;PUT&quot;;
            request.Headers.Add(&quot;x-ms-blob-type&quot;, &quot;BlockBlob&quot;);
            request.ContentLength = contentLength;
            using (Stream requestStream = request.GetRequestStream())
            {
                requestStream.Write(Encoding.UTF8.GetBytes(sampleContent), 0, contentLength);
            }
            using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse())
            {

            }
        }
</pre>
</p>
<p>When working with REST API, you must specify “<strong>x-ms-blob-type</strong>” request header. For block blobs, its value must be “<strong>BlockBlob</strong>” and for page blobs, the value must be “<strong>PageBlob</strong>”.</p>
<h3>Upload Blobs in Blocks</h3>
<p>Here’s the code if you want to upload a blob by splitting it into blocks. For uploading a blob, you could create a SAS with “<strong>Write</strong>” permission on either a blob container or a blob. The blob need not be present in the blob container. If the blob is not present, it will be created otherwise it will be overwritten.</p>
<h4>Using Storage Client Library</h4>
<p><pre class="brush: plain; title: ; notranslate">
        /// &lt;summary&gt;
        /// Uploads a blob by splitting into blocks in a blob container where SAS permission is defined on a blob container using storage client library.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;blobContainerSasUri&quot;&gt;&lt;/param&gt;
        static void UploadBlobInBlocksWithStorageClientLibrarySasPermissionOnBlobContainer(string blobContainerSasUri)
        {
            CloudBlobContainer blobContainer = new CloudBlobContainer(new Uri(blobContainerSasUri));
            CloudBlockBlob blob = blobContainer.GetBlockBlobReference(Guid.NewGuid().ToString() + &quot;.txt&quot;);
            List&lt;string&gt; blockIds = new List&lt;string&gt;();
            for (int i = 0; i &lt; 10; i++)
            {
                string sampleContent = string.Format(CultureInfo.InvariantCulture, &quot;Line {0}: This is sample text.\r\n&quot;, i);
                string blockId = i.ToString(&quot;d4&quot;);
                blockIds.Add(blockId);
                using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(sampleContent)))
                {
                    blob.PutBlock(blockId, ms, null);
                }
            }
            blob.PutBlockList(blockIds);
        }
</pre>
</p>
<p><pre class="brush: plain; title: ; notranslate">
        /// &lt;summary&gt;
        /// Uploads a blob by splitting into blocks in a blob container where SAS permission is defined on a blob using storage client library.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;blobSasUri&quot;&gt;&lt;/param&gt;
        static void UploadBlobInBlocksWithStorageClientLibrarySasPermissionOnBlob(string blobSasUri)
        {
            CloudBlockBlob blob = new CloudBlockBlob(blobSasUri);
            List&lt;string&gt; blockIds = new List&lt;string&gt;();
            for (int i = 0; i &lt; 10; i++)
            {
                string sampleContent = string.Format(CultureInfo.InvariantCulture, &quot;Line {0}: This is sample text.\r\n&quot;, i);
                string blockId = i.ToString(&quot;d4&quot;);
                blockIds.Add(blockId);
                using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(sampleContent)))
                {
                    blob.PutBlock(blockId, ms, null);
                }
            }
            blob.PutBlockList(blockIds);
        }
</pre>
</p>
<h4>Using REST API</h4>
<p><pre class="brush: plain; title: ; notranslate">
        /// &lt;summary&gt;
        /// Uploads a blob by splitting into blocks in a blob container where SAS permission is defined on a blob container using REST API.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;blobContainerSasUri&quot;&gt;&lt;/param&gt;
        static void UploadBlobInBlocksWithRestAPISasPermissionOnBlobContainer(string blobContainerSasUri)
        {
            string blobName = Guid.NewGuid().ToString() + &quot;.txt&quot;;
            string queryString = (new Uri(blobContainerSasUri)).Query;
            string blobContainerUri = blobContainerSasUri.Substring(0, blobContainerSasUri.Length - queryString.Length);
            List&lt;string&gt; blockIds = new List&lt;string&gt;();
            for (int i = 0; i &lt; 10; i++)
            {
                string sampleContent = string.Format(CultureInfo.InvariantCulture, &quot;Line {0}: This is sample text.\r\n&quot;, i);
                string blockId = i.ToString(&quot;d4&quot;);
                blockIds.Add(blockId);
                int contentLength = Encoding.UTF8.GetByteCount(sampleContent);
                string requestUri = string.Format(CultureInfo.InvariantCulture, &quot;{0}/{1}{2}&amp;comp=block&amp;blockid={3}&quot;, blobContainerUri, blobName, queryString, Convert.ToBase64String(Encoding.UTF8.GetBytes(blockId)));
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUri);
                request.Method = &quot;PUT&quot;;
                request.ContentLength = contentLength;
                using (Stream requestStream = request.GetRequestStream())
                {
                    requestStream.Write(Encoding.UTF8.GetBytes(sampleContent), 0, contentLength);
                }
                using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse())
                {

                }
            }
            string commitBlockListRequestBodyFormat = @&quot;&lt;?xml version=&quot;&quot;1.0&quot;&quot; encoding=&quot;&quot;utf-8&quot;&quot; ?&gt;&lt;BlockList&gt;{0}&lt;/BlockList&gt;&quot;;

            string blockListReuestBodyFormat = &quot;&lt;Latest&gt;{0}&lt;/Latest&gt;&quot;;
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i &lt; blockIds.Count; i++)
            {
                sb.AppendFormat(CultureInfo.InvariantCulture, blockListReuestBodyFormat,
                                Convert.ToBase64String(Encoding.UTF8.GetBytes(blockIds[i])));
            }
            string requestPayLoad = string.Format(CultureInfo.InvariantCulture, commitBlockListRequestBodyFormat,
                                                  sb.ToString());
            int contentLengthForCommitBlockList = Encoding.UTF8.GetByteCount(requestPayLoad);
            string requestUriForCommitBlockList = string.Format(CultureInfo.InvariantCulture, &quot;{0}/{1}{2}&amp;comp=blockList&quot;, blobContainerUri, blobName, queryString);
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(requestUriForCommitBlockList);
            req.Method = &quot;PUT&quot;;
            req.ContentLength = contentLengthForCommitBlockList;
            using (Stream requestStream = req.GetRequestStream())
            {
                requestStream.Write(Encoding.UTF8.GetBytes(requestPayLoad), 0, contentLengthForCommitBlockList);
            }
            using (HttpWebResponse resp = (HttpWebResponse)req.GetResponse())
            {

            }
        }
</pre>
</p>
<p><pre class="brush: plain; title: ; notranslate">
        /// &lt;summary&gt;
        /// Uploads a blob by splitting into blocks in a blob container where SAS permission is defined on a blob using REST API.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;blobSasUri&quot;&gt;&lt;/param&gt;
        static void UploadBlobInBlocksWithRestAPISasPermissionOnBlob(string blobSasUri)
        {
            List&lt;string&gt; blockIds = new List&lt;string&gt;();
            for (int i = 0; i &lt; 10; i++)
            {
                string sampleContent = string.Format(CultureInfo.InvariantCulture, &quot;Line {0}: This is sample text.\r\n&quot;, i);
                string blockId = i.ToString(&quot;d4&quot;);
                blockIds.Add(blockId);
                int contentLength = Encoding.UTF8.GetByteCount(sampleContent);
                string requestUri = string.Format(CultureInfo.InvariantCulture, &quot;{0}&amp;comp=block&amp;blockid={1}&quot;, blobSasUri, Convert.ToBase64String(Encoding.UTF8.GetBytes(blockId)));
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUri);
                request.Method = &quot;PUT&quot;;
                request.ContentLength = contentLength;
                using (Stream requestStream = request.GetRequestStream())
                {
                    requestStream.Write(Encoding.UTF8.GetBytes(sampleContent), 0, contentLength);
                }
                using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse())
                {

                }
            }
            string commitBlockListRequestBodyFormat = @&quot;&lt;?xml version=&quot;&quot;1.0&quot;&quot; encoding=&quot;&quot;utf-8&quot;&quot; ?&gt;&lt;BlockList&gt;{0}&lt;/BlockList&gt;&quot;;

            string blockListReuestBodyFormat = &quot;&lt;Latest&gt;{0}&lt;/Latest&gt;&quot;;
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i &lt; blockIds.Count; i++)
            {
                sb.AppendFormat(CultureInfo.InvariantCulture, blockListReuestBodyFormat,
                                Convert.ToBase64String(Encoding.UTF8.GetBytes(blockIds[i])));
            }
            string requestPayLoad = string.Format(CultureInfo.InvariantCulture, commitBlockListRequestBodyFormat,
                                                  sb.ToString());
            int contentLengthForCommitBlockList = Encoding.UTF8.GetByteCount(requestPayLoad);
            string requestUriForCommitBlockList = string.Format(CultureInfo.InvariantCulture, &quot;{0}&amp;comp=blockList&quot;, blobSasUri);
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(requestUriForCommitBlockList);
            req.Method = &quot;PUT&quot;;
            req.ContentLength = contentLengthForCommitBlockList;
            using (Stream requestStream = req.GetRequestStream())
            {
                requestStream.Write(Encoding.UTF8.GetBytes(requestPayLoad), 0, contentLengthForCommitBlockList);
            }
            using (HttpWebResponse resp = (HttpWebResponse)req.GetResponse())
            {

            }
        }
</pre>
</p>
<p>When working with REST API, for putting blocks you must specify “<strong>comp=block</strong>” and <strong>Base64 encoded block id in the request URI</strong>. For putting block list, you must specify “<strong>comp=blockList</strong>” in the request URI.</p>
<h3>Download Blobs</h3>
<p>Here’s the code for downloading a blob from a blob container. For downloading blob, “<strong>Read</strong>” permission must be defined in SAS.</p>
<h4>Using Storage Client Library</h4>
<p><pre class="brush: plain; title: ; notranslate">
        /// &lt;summary&gt;
        /// Downloads a blob from a blob cobtainer using storage client library.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;blobSasUri&quot;&gt;&lt;/param&gt;
        static void DownloadBlobWithStorageClientLibrary(string blobSasUri)
        {
            CloudBlockBlob blob = new CloudBlockBlob(new Uri(blobSasUri));
            using (MemoryStream ms = new MemoryStream())
            {
                blob.DownloadToStream(ms);
                byte[] data = new byte[ms.Length];
                ms.Position = 0;
                ms.Read(data, 0, data.Length);
                string blobContents = Encoding.UTF8.GetString(data);
                Console.WriteLine(blobContents);
            }
        }
</pre>
</p>
<h4>Using REST API</h4>
<p><pre class="brush: plain; title: ; notranslate">
        /// &lt;summary&gt;
        /// Downloads a blob from a blob cobtainer using REST API.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;blobSasUri&quot;&gt;&lt;/param&gt;
        static void DownloadBlobWithRestAPI(string blobSasUri)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(blobSasUri);
            request.Method = &quot;GET&quot;;
            using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse())
            {
                using (Stream s = resp.GetResponseStream())
                {
                    using (StreamReader reader = new StreamReader(s, true))
                    {
                        string blobData = reader.ReadToEnd();
                        Console.WriteLine(blobData);
                    }
                }
            }
        }
</pre>
</p>
<h3>Deleting Blobs</h3>
<p>Here’s the code for deleting a blob from a blob container. For delete operation, “<strong>Delete</strong>” permission must be defined in SAS.</p>
<h4>Using Storage Client Library</h4>
<p><pre class="brush: plain; title: ; notranslate">
        /// &lt;summary&gt;
        /// Deletes a blob from a blob cobtainer using storage client library.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;blobSasUri&quot;&gt;&lt;/param&gt;
        static void DeleteBlobWithStorageClientLibrary(string blobSasUri)
        {
            CloudBlockBlob blob = new CloudBlockBlob(new Uri(blobSasUri));
            blob.Delete();
        }
</pre>
</p>
<h4>Using REST API</h4>
<p><pre class="brush: plain; title: ; notranslate">
        /// &lt;summary&gt;
        /// Deletes a blob from a blob cobtainer using REST API.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;blobSasUri&quot;&gt;&lt;/param&gt;
        private static void DeleteBlobWithRestAPI(string blobSasUri)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(blobSasUri);
            request.Method = &quot;DELETE&quot;;
            using (HttpWebResponse resp = (HttpWebResponse) request.GetResponse())
            {
                
            }
        }
</pre>
</p>
<h2>Summary</h2>
<p>That’s it for this post. I could have possibly done more and included more samples but these should give you an idea about how to use SAS to perform various operations. May be in another post, I will show some functionality related to Tables and Queues with SAS. I hope you’ve found this post useful. If you find any issues with this post, please let me know and I’ll try and fix them ASAP. Feel free to provide your comments below.</p>
<p>Happy Coding!!!</p>
<img src="http://feeds.feedburner.com/~r/gmantri/~4/qS1G7Gj7umI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://gauravmantri.com/2013/02/13/revisiting-windows-azure-shared-access-signature/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		<feedburner:origLink>http://gauravmantri.com/2013/02/13/revisiting-windows-azure-shared-access-signature/</feedburner:origLink></item>
		<item>
		<title>Workaround for IIS Express Crashing When Running Windows Azure Cloud Service Web Role with Multiple Instances in Windows Azure SDK 1.8 Compute Emulator</title>
		<link>http://feedproxy.google.com/~r/gmantri/~3/qywc8J9gf2M/</link>
		<comments>http://gauravmantri.com/2013/02/05/workaround-for-iis-express-crashing-when-running-windows-azure-cloud-service-web-role-with-multiple-instances-in-windows-azure-sdk-1-8-compute-emulator/#comments</comments>
		<pubDate>Tue, 05 Feb 2013 05:49:42 +0000</pubDate>
		<dc:creator>Gaurav</dc:creator>
				<category><![CDATA[Windows Azure]]></category>
		<category><![CDATA[Windows Azure Cloud Service]]></category>
		<category><![CDATA[Windows Azure SDK]]></category>
		<category><![CDATA[IIS Express]]></category>
		<category><![CDATA[Visual Studio 2012]]></category>
		<category><![CDATA[Web Role]]></category>
		<category><![CDATA[Windows 8]]></category>
		<category><![CDATA[Windows Azure SDK 1.8]]></category>

		<guid isPermaLink="false">http://gauravmantri.com/?p=1136</guid>
		<description><![CDATA[I ran into this weird issue when developing a very simple Windows Azure Cloud Service Web Role using Windows Azure SDK 1.8. I started off with a basic ASP.Net MVC 4 Web Role with no changes whatsoever. When I tried to debug it with just one instance running, everything worked great. The moment I increased [...]]]></description>
			<content:encoded><![CDATA[<p>I ran into this weird issue when developing a very simple <strong>Windows Azure Cloud Service Web Role</strong> using <strong>Windows Azure SDK 1.8</strong>. I started off with a basic ASP.Net MVC 4 Web Role with no changes whatsoever. When I tried to debug it with just one instance running, everything worked great. The moment I increased the number of instances to 2 (or more than 1) and tried to debug it, IIS Express crashed with the following entries in event logs:</p>
<hr/>
<p>Faulting application name: iisexpress.exe, version: 8.0.8418.0, time stamp: 0x4fbae3d6<br />
Faulting module name: ntdll.dll, version: 6.2.9200.16420, time stamp: 0x505ab405<br />
Exception code: 0xc0000008<br />
Fault offset: 0x0000000000004c39<br />
Faulting process id: 0x54bc<br />
Faulting application start time: 0x01cdfeb70c1e060e<br />
Faulting application path: C:\Program Files\IIS Express\iisexpress.exe<br />
Faulting module path: C:\Windows\SYSTEM32\ntdll.dll<br />
Report Id: 4a8f54b2-6aaa-11e2-be81-9cb70d025a13<br />
Faulting package full name:<br />
Faulting package-relative application ID:</p>
<hr />
<p>Fault bucket 79240842, type 4<br />
Event Name: APPCRASH<br />
Response: Not available<br />
Cab Id: 0</p>
<p>Problem signature:<br />
P1: iisexpress.exe<br />
P2: 8.0.8418.0<br />
P3: 4fbae3d6<br />
P4: ntdll.dll<br />
P5: 6.2.9200.16420<br />
P6: 505ab405<br />
P7: c0000008<br />
P8: 0000000000004c39<br />
P9:<br />
P10:</p>
<p>Attached files:<br />
C:\Users\Gaurav.Mantri\AppData\Local\Temp\WER4720.tmp.WERInternalMetadata.xml</p>
<p>These files may be available here:<br />
C:\ProgramData\Microsoft\Windows\WER\ReportArchive\AppCrash_iisexpress.exe_1263888cd189f3357758cdc998d7afecf3f28_2dae4eb2</p>
<p>Analysis symbol:<br />
Rechecking for solution: 0<br />
Report Id: 4a8f54b2-6aaa-11e2-be81-9cb70d025a13<br />
Report Status: 17<br />
Hashed bucket: b615b24f7933990317ae65713d680dab</p>
<hr />
<p><strong>This issue does not happen on all machines</strong>. I asked a few of my friends to try on their computers and some of them were able to recreate this problem while others couldn’t. My development environment was <strong>Windows 8</strong>, <strong>Visual Studio 2012</strong> and <strong>Windows Azure SDK 1.8</strong>.</p>
<p>Since I was facing this problem and a few of my friends are also facing the same problem, I thought there may be many more folks who may be facing same problem and hence this blog.</p>
<p>Windows Azure product team helped me find the cause of the problem and gave me a workaround which fixed the problem. I’m also told that this issue will be fixed in the coming versions of SDK but till the time the new SDK comes, the workaround recommended by the team can be used to address this problem.</p>
<h2>Cause</h2>
<p>From what I have been told, this is related to an issue with Windows Azure SDK 1.8 and it happens because <strong>IIS Express is trying to bind same IP address to multiple instances</strong>. Here’re the entries from applicationHost.config file for 2 instances in which I was trying to run my application which let the product team to that conclusion:</p>
<p><strong>Instance 0:</strong></p>
<pre class="brush: plain; title: ; notranslate">
&lt;site name=&quot;deployment18(110).WindowsAzureService3.WindowsAzureService3WebRole_IN_0_Web&quot; id=&quot;1273337584&quot;&gt; 
                &lt;application path=&quot;/&quot; applicationPool=&quot;b31dc554-ad4b-4a18-8a62-098b5079f26d&quot; enabledProtocols=&quot;http&quot;&gt; 
                    &lt;virtualDirectory path=&quot;/&quot; physicalPath=&quot;D:\Projects\WindowsAzureService3\WindowsAzureService3WebRole\&quot; /&gt; 
                &lt;/application&gt; 
                &lt;bindings&gt; 
                    &lt;binding protocol=&quot;http&quot; bindingInformation=&quot;*:82:&quot; /&gt; 
                &lt;/bindings&gt; 
                &lt;logFile logExtFileFlags=&quot;Date, Time, ClientIP, UserName, SiteName, ComputerName, ServerIP, Method, UriStem, UriQuery, HttpStatus, Win32Status, BytesSent, BytesRecv, TimeTaken, ServerPort, UserAgent, Cookie, Referer, ProtocolVersion, Host, HttpSubStatus&quot; logFormat=&quot;W3C&quot; directory=&quot;C:\Users\Gaurav.Mantri\AppData\Local\dftmp\Resources\40fae03f-8519-4c66-a36b-da8e2de73e9d\directory\DiagnosticStore\LogFiles\Web&quot; period=&quot;Hourly&quot; /&gt; 
                &lt;traceFailedRequestsLogging enabled=&quot;true&quot; directory=&quot;C:\Users\Gaurav.Mantri\AppData\Local\dftmp\Resources\40fae03f-8519-4c66-a36b-da8e2de73e9d\directory\DiagnosticStore\FailedReqLogFiles\Web&quot; maxLogFiles=&quot;1000&quot; /&gt; 
            &lt;/site&gt; 
</pre>
<p><strong>Instance 1:</strong></p>
<pre class="brush: plain; title: ; notranslate">
&lt;site name=&quot;deployment18(110).WindowsAzureService3.WindowsAzureService3WebRole_IN_1_Web&quot; id=&quot;1273337584&quot;&gt; 
                &lt;application path=&quot;/&quot; applicationPool=&quot;92214b82-0516-4502-8e38-4d94c3cdf949&quot; enabledProtocols=&quot;http&quot;&gt; 
                    &lt;virtualDirectory path=&quot;/&quot; physicalPath=&quot;D:\Projects\WindowsAzureService3\WindowsAzureService3WebRole\&quot; /&gt; 
                &lt;/application&gt; 
                &lt;bindings&gt; 
                    &lt;binding protocol=&quot;http&quot; bindingInformation=&quot;*:82:&quot; /&gt; 
                &lt;/bindings&gt; 
                &lt;logFile logExtFileFlags=&quot;Date, Time, ClientIP, UserName, SiteName, ComputerName, ServerIP, Method, UriStem, UriQuery, HttpStatus, Win32Status, BytesSent, BytesRecv, TimeTaken, ServerPort, UserAgent, Cookie, Referer, ProtocolVersion, Host, HttpSubStatus&quot; logFormat=&quot;W3C&quot; directory=&quot;C:\Users\Gaurav.Mantri\AppData\Local\dftmp\Resources\3c7c31cb-a2fb-4809-aadb-9238acb2f092\directory\DiagnosticStore\LogFiles\Web&quot; period=&quot;Hourly&quot; /&gt; 
                &lt;traceFailedRequestsLogging enabled=&quot;true&quot; directory=&quot;C:\Users\Gaurav.Mantri\AppData\Local\dftmp\Resources\3c7c31cb-a2fb-4809-aadb-9238acb2f092\directory\DiagnosticStore\FailedReqLogFiles\Web&quot; maxLogFiles=&quot;1000&quot; /&gt; 
            &lt;/site&gt;
</pre>
<p>As you can see from above in the &#8220;binding&#8221; section, both instances were trying to bind to port 82 and hence the error.</p>
<h2>Workaround</h2>
<p>There were two workarounds recommended by the Windows Azure SDK team:</p>
<h3>Install Visual Studio 2010 SP1</h3>
<p>If you’re using Visual Studio 2010, it is recommended that you install SP1 for that. Seemingly that takes care of this problem. Since I don’t have VS 2010 on my machine, I did not try it as it was not applicable to me.</p>
<h3>Add an Environment Variable</h3>
<p>Other workaround recommended was to add an environment variable called “<strong>_CSRUN_DISABLE_WORKAROUNDS</strong>” and set the value of this variable to “<strong>1</strong>”. To set an environment varaible, search for “<strong>Control Panel</strong>” and then go to “<strong>System</strong>” –&gt; “<strong>Advanced system settings</strong>” –&gt; “<strong>Advanced</strong>” tab –&gt; “<strong>Environment Variables&#8230;</strong>” button –&gt; “<strong>New&#8230;</strong>” button.</p>
<p>I’ve also added a screenshot for your convenience as well.</p>
<p><a href="http://gauravmantri.com/wp-content/uploads/2013/02/image.png"><img style="display: inline; border-width: 0px;" title="image" src="http://gauravmantri.com/wp-content/uploads/2013/02/image_thumb.png" alt="image" width="810" height="455" border="0" /></a></p>
<p>After you do that you would need to <strong>restart IIS Express and Compute/Storage Emulator</strong>.</p>
<p>I tried this approach and it worked for me.</p>
<p>Hope this helps!</p>
<img src="http://feeds.feedburner.com/~r/gmantri/~4/qywc8J9gf2M" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://gauravmantri.com/2013/02/05/workaround-for-iis-express-crashing-when-running-windows-azure-cloud-service-web-role-with-multiple-instances-in-windows-azure-sdk-1-8-compute-emulator/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://gauravmantri.com/2013/02/05/workaround-for-iis-express-crashing-when-running-windows-azure-cloud-service-web-role-with-multiple-instances-in-windows-azure-sdk-1-8-compute-emulator/</feedburner:origLink></item>
		<item>
		<title>Windows Azure Access Control Service, Windows 8 and Visual Studio 2012: Setting Up Development Environment – Oh My!</title>
		<link>http://feedproxy.google.com/~r/gmantri/~3/a5xsXTemC5c/</link>
		<comments>http://gauravmantri.com/2013/01/28/windows-azure-access-control-service-windows-8-and-visual-studio-2012-setting-up-development-environment-oh-my/#comments</comments>
		<pubDate>Mon, 28 Jan 2013 12:45:02 +0000</pubDate>
		<dc:creator>Gaurav</dc:creator>
				<category><![CDATA[Visual Studio 2012]]></category>
		<category><![CDATA[Windows 8]]></category>
		<category><![CDATA[Windows Azure]]></category>
		<category><![CDATA[Windows Azure Access Control Service]]></category>
		<category><![CDATA[ACS]]></category>

		<guid isPermaLink="false">http://gauravmantri.com/?p=1125</guid>
		<description><![CDATA[Today I started playing with Windows Azure Access Control Service (ACS) and ran into some issues while making a simple application based on the guide here: http://www.windowsazure.com/en-us/develop/net/how-to-guides/access-control/. I had to search for a number of things on the Internet to finally get it working so I thought I would write a simple blog post which [...]]]></description>
			<content:encoded><![CDATA[<p>Today I started playing with <strong>Windows Azure Access Control Service (ACS)</strong> and ran into some issues while making a simple application based on the guide here: <a title="http://www.windowsazure.com/en-us/develop/net/how-to-guides/access-control/" href="http://www.windowsazure.com/en-us/develop/net/how-to-guides/access-control/" target="_blank">http://www.windowsazure.com/en-us/develop/net/how-to-guides/access-control/</a>. I had to search for a number of things on the Internet to finally get it working so I thought I would write a simple blog post which kind of summarizes the issues and how to resolve them.</p>
<p>The problems I ran into were because the guide was focused on Windows 7/Visual Studio 2010 and I was using Windows 8/Visual Studio 2012.</p>
<p>It may very well be documented somewhere but I could not find them and there may be many “newbies” like me who are just starting out with ACS on Windows 8/VS 2012 and hopefully this blog post will save some time and frustration implementing this ridiculously easy and useful technology for implementing authentication in their web applications.</p>
<p>With this thought, let’s start <img src='http://gauravmantri.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h2>Windows Identity Foundation Setup</h2>
<p><a href="http://gauravmantri.com/wp-content/uploads/2013/01/image10.png"><img style="display: inline; border-width: 0px;" title="image" src="http://gauravmantri.com/wp-content/uploads/2013/01/image_thumb10.png" alt="image" width="810" height="196" border="0" /></a></p>
<p>When I downloaded and tried to run the “Windows Identity Foundation” from &#8220;Windows Identity Foundation&#8221; link from above, I got the following message:</p>
<p><a href="http://gauravmantri.com/wp-content/uploads/2013/01/image11.png"><img style="display: inline; border-width: 0px;" title="image" src="http://gauravmantri.com/wp-content/uploads/2013/01/image_thumb11.png" alt="image" width="810" height="385" border="0" /></a></p>
<p>I found the solution for this problem on Windows 8 Community Forums: <a title="http://answers.microsoft.com/en-us/windows/forum/windows_8-windows_install/error-when-installing-windows-identity-foundation/6e4c65a5-ea24-431c-b4f0-b8740e97cf46?auth=1" href="http://answers.microsoft.com/en-us/windows/forum/windows_8-windows_install/error-when-installing-windows-identity-foundation/6e4c65a5-ea24-431c-b4f0-b8740e97cf46?auth=1" target="_blank">http://answers.microsoft.com/en-us/windows/forum/windows_8-windows_install/error-when-installing-windows-identity-foundation/6e4c65a5-ea24-431c-b4f0-b8740e97cf46?auth=1</a>. Basically, the solution is that <strong>you have to enable WIF through “Turn Windows Feature On/Off” functionality</strong>. To do so, go to <strong>Control Panel &#8211;&gt; Programs and Features &#8211;&gt; Turn Windows Feature on or off</strong>.</p>
<p><a href="http://gauravmantri.com/wp-content/uploads/2013/01/image12.png"><img style="display: inline; border-width: 0px;" title="image" src="http://gauravmantri.com/wp-content/uploads/2013/01/image_thumb13.png" alt="image" width="810" height="654" border="0" /></a></p>
<p>Also once WIF is installed, I was able to install <strong>Windows Identity Foundation SDK</strong>. Prior to that I was not able to do that as well.</p>
<h2>Dude, Where’s My “Add STS Reference” Option!</h2>
<p>OK, moving on. After following some more steps to a &#8220;T&#8221;, I ran into the following set of instructions:</p>
<p><a href="http://gauravmantri.com/wp-content/uploads/2013/01/image13.png"><img style="display: inline; border-width: 0px;" title="image" src="http://gauravmantri.com/wp-content/uploads/2013/01/image_thumb14.png" alt="image" width="810" height="272" border="0" /></a></p>
<p>So I followed step 1 but could not find “<strong>Add STS Reference</strong>” option when I right clicked on the solution in Visual Studio. Back to searching and I found a couple of blog posts:</p>
<p><a title="http://blogs.infosupport.com/equivalent-to-add-sts-reference-for-vs-2012/" href="http://blogs.infosupport.com/equivalent-to-add-sts-reference-for-vs-2012/" target="_blank">http://blogs.infosupport.com/equivalent-to-add-sts-reference-for-vs-2012/</a></p>
<p><a title="http://www.stratospher.es/blog/post/add-sts-reference-missing-in-visual-studio-2012-rc" href="http://www.stratospher.es/blog/post/add-sts-reference-missing-in-visual-studio-2012-rc" target="_blank">http://www.stratospher.es/blog/post/add-sts-reference-missing-in-visual-studio-2012-rc</a></p>
<p>Basically what I needed to do was install “<strong>Identity and Access Tool</strong>” extension. To do so, just click on <strong>Tools</strong> –&gt; <strong>Extensions and Updates&#8230;</strong> and search for “<strong>Identity</strong>” as shown below:</p>
<p><a href="http://gauravmantri.com/wp-content/uploads/2013/01/image14.png"><img style="display: inline; border-width: 0px;" title="image" src="http://gauravmantri.com/wp-content/uploads/2013/01/image_thumb15.png" alt="image" width="810" height="302" border="0" /></a></p>
<p>One I installed it, I was a happy camper again <img src='http://gauravmantri.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><a href="http://gauravmantri.com/wp-content/uploads/2013/01/image15.png"><img style="display: inline; border-width: 0px;" title="image" src="http://gauravmantri.com/wp-content/uploads/2013/01/image_thumb16.png" alt="image" width="412" height="351" border="0" /></a></p>
<p>And instead of “<strong>Add STS Reference</strong>” the options&#8217; name is “<strong>Identity and Access</strong>” <img src='http://gauravmantri.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h2>Configuring Trust between ACS and ASP.NET Web Application</h2>
<p>Next step is configuring trust between ACS and ASP.Net Web Application. The steps provided in the guide were for Visual Studio 2010 and clicking on “<strong>Identity and Access&#8230;</strong>” gave me an entirely different window.</p>
<p><a href="http://gauravmantri.com/wp-content/uploads/2013/01/image16.png"><img style="display: inline; border-width: 0px;" title="image" src="http://gauravmantri.com/wp-content/uploads/2013/01/image_thumb17.png" alt="image" width="810" height="720" border="0" /></a></p>
<p>Again this blog post from Haishi Bai came to my rescue: <a title="http://haishibai.blogspot.in/2012/08/windows-azure-web-site-targeting-net.html" href="http://haishibai.blogspot.in/2012/08/windows-azure-web-site-targeting-net.html" target="_blank">http://haishibai.blogspot.in/2012/08/windows-azure-web-site-targeting-net.html</a>. However one thing that was not clear to me (or consider this my complete ignorance <img src='http://gauravmantri.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> ) is from where I’ll get the <strong>management key</strong>. I logged into the ACS portal (https://&lt;yourservicenamespace&gt;.accesscontrol.windows.net) and first thought I would find the key under “<strong>Certificates and keys</strong>” section there (without reading much above. You can understand, I was desperate <img src='http://gauravmantri.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> ). I copied the key from there and entered that key in the window above but that didn’t work.</p>
<p>As I looked around, I found the “Management service” section under “Administration” section and tried to use the key from there.</p>
<p><a href="http://gauravmantri.com/wp-content/uploads/2013/01/image17.png"><img style="display: inline; border-width: 0px;" title="image" src="http://gauravmantri.com/wp-content/uploads/2013/01/image_thumb18.png" alt="image" width="810" height="196" border="0" /></a></p>
<p><a href="http://gauravmantri.com/wp-content/uploads/2013/01/image18.png"><img style="display: inline; border-width: 0px;" title="image" src="http://gauravmantri.com/wp-content/uploads/2013/01/image_thumb19.png" alt="image" width="810" height="382" border="0" /></a></p>
<p>Clicked on “Generate” button to create a key and used it and voila it worked <img src='http://gauravmantri.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . The portal also generates a key for you which you can also use, BTW.</p>
<p><a href="http://gauravmantri.com/wp-content/uploads/2013/01/image19.png"><img style="display: inline; border-width: 0px;" title="image" src="http://gauravmantri.com/wp-content/uploads/2013/01/image_thumb20.png" alt="image" width="810" height="737" border="0" /></a></p>
<h2>Running The Application</h2>
<p>Assuming the worst part was over, I followed remaining steps in the guide and pressed “F5” to run the application. But the application didn’t run <img src='http://gauravmantri.com/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> . Instead I got this error:</p>
<p><a href="http://gauravmantri.com/wp-content/uploads/2013/01/image20.png"><img style="display: inline; border-width: 0px;" title="image" src="http://gauravmantri.com/wp-content/uploads/2013/01/image_thumb21.png" alt="image" width="810" height="163" border="0" /></a></p>
<p>Again I was at the mercy of search engines <img src='http://gauravmantri.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . I searched for it and found a blog post by Sandrino: <a title="http://sandrinodimattia.net/blog/posts/azure-appfabric-acs-unauthorized-logon-failed-due-to-server-configuration/" href="http://sandrinodimattia.net/blog/posts/azure-appfabric-acs-unauthorized-logon-failed-due-to-server-configuration/">http://sandrinodimattia.net/blog/posts/azure-appfabric-acs-unauthorized-logon-failed-due-to-server-configuration/</a>. I applied the fix he suggested but unfortunately that didn’t work <img src='http://gauravmantri.com/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> . He also mentioned that it worked in an MVC application (this one was a WebForm application) so I tried creating a simple MVC 4 application and guess what, it worked there as Sandrino said <img src='http://gauravmantri.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p><a href="http://gauravmantri.com/wp-content/uploads/2013/01/image21.png"><img style="display: inline; border-width: 0px;" title="image" src="http://gauravmantri.com/wp-content/uploads/2013/01/image_thumb22.png" alt="image" width="810" height="677" border="0" /></a></p>
<p>For now, I’m happy with what I’ve got and will focus on building some applications consuming ACS and see what this service has to offer.</p>
<h2>Alternative Approach</h2>
<p>While working on this, I realized an alternative approach to get up and running with ACS. Here’s what you would need to do:</p>
<ol>
<li>Create a new Access Control Service in Windows Azure Portal.</li>
<li>Once the service is active, click on Manage button to manage that service. You will be taken to the ACS portal for your service.</li>
<li>Configure Identity Providers.</li>
<li>Get the management key from “Management service” section.</li>
<li>Head back to Visual Studio project and configure ACS. You would need the name of the service and the management key.</li>
<li>The tooling in Visual Studio takes care of creating “Relaying party applications” for you based on your project settings.</li>
</ol>
<h2>Summary</h2>
<p>I spent considerable amount of time setting up this thing which kind of frustrated me. I hope this post will save you some time and frustration. Also this is the first time I looked at this service so it is highly likely I may have made some mistakes or included them here based on my sheer ignorance. Please feel free to correct me if I have provided incorrect information.</p>
<p>Happy Coding!!!</p>
<img src="http://feeds.feedburner.com/~r/gmantri/~4/a5xsXTemC5c" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://gauravmantri.com/2013/01/28/windows-azure-access-control-service-windows-8-and-visual-studio-2012-setting-up-development-environment-oh-my/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://gauravmantri.com/2013/01/28/windows-azure-access-control-service-windows-8-and-visual-studio-2012-setting-up-development-environment-oh-my/</feedburner:origLink></item>
	</channel>
</rss><!-- Dynamic page generated in 0.719 seconds. --><!-- Cached page generated by WP-Super-Cache on 2013-05-18 13:24:57 --><!-- Compression = gzip -->
