<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;AkYCR3g5eip7ImA9WhBaEkU.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669</id><updated>2013-05-22T22:49:26.622-07:00</updated><category term="TIY" /><category term="Python" /><category term="User Interface" /><category term="jQuery" /><category term="Architecture" /><category term="Software Engineering" /><category term="MVC/MVVM" /><category term="Cloud Computing" /><category term="CAB" /><category term="Deployment" /><category term="我的中国" /><category term="疯人手札" /><category term="Security" /><category term="English - PDC 2008" /><category term="Algorithms" /><category term="Azure" /><category term="Computer Vision" /><category term="Windows Phone" /><category term="NDepend" /><category term="Silverlight/WPF" /><category term="WCF" /><category term="白玉美人" /><category term="Geneva" /><category term="Sync Framework" /><category term="Service Bus" /><category term="Unity" /><category term="Digital Identity" /><category term="嘈嘈切切" /><category term="电子基盘" /><category term=".Net General" /><category term="Software Matrices" /><category term="Design Patterns" /><category term="史海钩沉" /><category term="Entity Framework" /><title>Haishi's Blog</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://haishibai.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>180</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/HaishisBlog" /><feedburner:info uri="haishisblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;CEMBSHk4eSp7ImA9WhBaEk0.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-8366394673273131045</id><published>2013-05-21T23:00:00.001-07:00</published><updated>2013-05-21T23:00:59.731-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-05-21T23:00:59.731-07:00</app:edited><title>A Message to My Readers: Visual Studio Live! is heading back to Redmond</title><content type="html">&lt;p&gt;Dear readers: &lt;p&gt;I have never ever posted a message like this but I’ll make an exception this time. Visual Studio Live! is heading back to Microsoft campus on August 19-23 in Redmond, WA. Surrounded by your fellow developers, Visual Studio Live! provides you with immediately usable education that will keep you relevant in the workforce. Learn how you can Code like a Rock star at Visual Studio Live! Redmond — bring the issues that keep you up at night and prepare to leave this event with the answers, guidance and training you need. Register now: &lt;a href="http://bit.ly/UGRD6_Reg"&gt;http://bit.ly/UGRD6_Reg&lt;/a&gt; &lt;p&gt;&amp;nbsp; &lt;h3&gt;&lt;strong&gt;SPECIAL OFFER:&lt;/strong&gt; As a thank you to the readers of my blog, I can extend $500 savings on the 5-day package. Register here: &lt;a href="http://bit.ly/UGRD6_Reg"&gt;http://bit.ly/UGRD6_Reg&lt;/a&gt; and use code &lt;b&gt;UGRD6&lt;/b&gt;.&lt;/h3&gt; &lt;p&gt;&amp;nbsp; &lt;p&gt;&lt;a href="http://bit.ly/UGRD6_Reg"&gt;&lt;img title="VSLR 300X250_UGRD4" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="VSLR 300X250_UGRD4" src="http://lh3.ggpht.com/-2GgDI3CE-00/UZxfGiSUHMI/AAAAAAAABK4/QYwyfXZvZvw/VSLR%252520300X250_UGRD4%25255B2%25255D.png?imgmax=800" width="315" height="263"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Thank you for reading!&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Best regards,&lt;/p&gt; &lt;p&gt;Haishi &lt;/p&gt;  &lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/WD80TMVANxk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/8366394673273131045/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2013/05/a-message-to-my-readers-visual-studio.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/8366394673273131045?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/8366394673273131045?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/WD80TMVANxk/a-message-to-my-readers-visual-studio.html" title="A Message to My Readers: Visual Studio Live! is heading back to Redmond" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/-2GgDI3CE-00/UZxfGiSUHMI/AAAAAAAABK4/QYwyfXZvZvw/s72-c/VSLR%252520300X250_UGRD4%25255B2%25255D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2013/05/a-message-to-my-readers-visual-studio.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkIERHk5cCp7ImA9WhBUGUo.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-8383034761619096052</id><published>2013-05-07T17:52:00.001-07:00</published><updated>2013-05-07T17:55:05.728-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-05-07T17:55:05.728-07:00</app:edited><title>Walkthrough: File Sharing Between Your Local Machine And Your Virtual Machines on Windows Azure</title><content type="html">&lt;p&gt;With Windows Azure &lt;a href="http://weblogs.asp.net/scottgu/archive/2013/04/26/windows-azure-improvements-to-virtual-networks-virtual-machines-cloud-services-and-a-new-ruby-sdk.aspx"&gt;Virtual Network Point-to-Site Connectivity&lt;/a&gt;,&amp;nbsp; it’s amazingly easy for cloud developers to connect their development machines to their Windows Azure virtual machines running on Windows Azure Virtual Network. In this walkthrough I’ll walk you through the steps of setting up a file share between your development machine and a virtual machine running on Windows Azure.&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Log on to Windows Azure Management Portal.&lt;/li&gt; &lt;li&gt;On command bar, click on &lt;strong&gt;NEW&lt;/strong&gt; button, then select &lt;strong&gt;NETWORKS&lt;/strong&gt;-&amp;gt;&lt;strong&gt;VIRTUAL NETWORK&lt;/strong&gt;-&amp;gt;&lt;strong&gt;CUSTOM CREATE&lt;/strong&gt; menu.&lt;/li&gt; &lt;li&gt;On &lt;strong&gt;&lt;em&gt;Virtual Network Details&lt;/em&gt;&lt;/strong&gt; page, enter network &lt;strong&gt;NAME&lt;/strong&gt; as &lt;em&gt;pointtosite&lt;/em&gt;, create or select a &lt;strong&gt;AFFINITY GROUP&lt;/strong&gt;, then click next arrow.&lt;/li&gt; &lt;li&gt;On &lt;strong&gt;&lt;em&gt;DNS Servers and VPN Connectivity&lt;/em&gt;&lt;/strong&gt; page, check&lt;strong&gt; Configure Point-to-Site VPN&lt;/strong&gt;, then click next arrow:&lt;br clear="all"&gt;&lt;a href="http://lh5.ggpht.com/-3F2LD0t8AuI/UYmhuoihvEI/AAAAAAAABJ0/6vBnm88dtck/s1600-h/image%25255B4%25255D.png"&gt;&lt;img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://lh5.ggpht.com/-43xK4Vgzhy4/UYmhu9V8fiI/AAAAAAAABJ4/ciqFOEABgq4/image_thumb%25255B2%25255D.png?imgmax=800" width="487" height="296"&gt;&lt;/a&gt;&lt;/li&gt; &lt;li&gt;On &lt;strong&gt;&lt;em&gt;Point-to-Site Connectivity&lt;/em&gt;&lt;/strong&gt; page, click next arrow.&lt;/li&gt; &lt;li&gt;On &lt;em&gt;&lt;strong&gt;Virtual Network Address Spaces&lt;/strong&gt;&lt;/em&gt; page, click on &lt;strong&gt;add gateway subnet&lt;/strong&gt; button, and then click on check icon to complete network creation.&lt;/li&gt; &lt;li&gt;After the virtual network has been created, open its &lt;strong&gt;DASHBOARD&lt;/strong&gt; page, and the click &lt;strong&gt;CREATE GATEWAY&lt;/strong&gt; icon to create the dynamic routing gateway.&lt;/li&gt; &lt;li&gt;Add a new Windows Server 2012 virtual machine to the virtual network. Note that when you specify user credential, make sure to &lt;u&gt;use the same user id and password of your local account&lt;/u&gt;. This is because the virtual machine on Windows Azure is not under your domain controller, and we are using the same user credential on both local and virtual machines to allow file sharing.&lt;/li&gt; &lt;li&gt;As the virtual machine is cooking, let’s create two self-signed certificates: one for root, and another for client identification. During the following steps we’ll need to upload the root certificate to Windows Azure so Windows Azure can validate the client machine using the certificate chain.&lt;/li&gt; &lt;li&gt;Launch &lt;strong&gt;Developer Command Prompt for VS2012&lt;/strong&gt; as administrator. Change current folder to a folder where you want to keep the generated certificates. Here I’ll use folder &lt;em&gt;&lt;strong&gt;c:\books&lt;/strong&gt;&lt;/em&gt;.&lt;/li&gt; &lt;li&gt;Use command &lt;pre class="csharpcode"&gt;makecert -sky exchange -r -n &lt;span class="str"&gt;"CN=MyFakeRoot"&lt;/span&gt; -pe -a sha1 -len 2048 -ss My&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
to create root certificate.&lt;/li&gt;
&lt;li&gt;Use command &lt;pre class="csharpcode"&gt;makecert -n &lt;span class="str"&gt;"CN=MyLaptop"&lt;/span&gt; -pe -sky exchange -m 96 -ss My -&lt;span class="kwrd"&gt;in&lt;/span&gt; &lt;span class="str"&gt;"MyFakeRoot"&lt;/span&gt; -&lt;span class="kwrd"&gt;is&lt;/span&gt; my -a sha1&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
to create client certificate.&lt;/li&gt;
&lt;li&gt;Launch &lt;strong&gt;certmgr&lt;/strong&gt;. Export the root certificate as a &lt;strong&gt;&lt;em&gt;MyFakeRoot.cer&lt;/em&gt;&lt;/strong&gt; file (&lt;u&gt;without&lt;/u&gt; private key).&lt;/li&gt;
&lt;li&gt;[Optional] if you are configuring VPN for another client, you’d need to install the client certificate on target machine.&lt;/li&gt;
&lt;li&gt;Go back to Windows Azure Management Portal. On &lt;strong&gt;DASHBOARD&lt;/strong&gt; page of the virtual network, click on link &lt;strong&gt;Upload client certificate&lt;/strong&gt; to upload the root certificate. Note at this point the gateway should have been created.&lt;br clear="all"&gt;&lt;a href="http://lh5.ggpht.com/-osw9ON6Qq2w/UYmhvdFKn0I/AAAAAAAABKA/iyhbJl7rbRc/s1600-h/image%25255B12%25255D.png"&gt;&lt;img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://lh3.ggpht.com/-UhhXt2Bc--8/UYmhv46a_jI/AAAAAAAABKI/u_QTD_65Ry8/image_thumb%25255B6%25255D.png?imgmax=800" width="504" height="283"&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;After certificate has been uploaded, you can download and install VPN client from the &lt;strong&gt;DASHBOARD&lt;/strong&gt; page (&lt;strong&gt;&lt;em&gt;AMD64 Client&lt;/em&gt;&lt;/strong&gt; link for 64-bit machines, &lt;strong&gt;&lt;em&gt;x86 Client&lt;/em&gt;&lt;/strong&gt; link for 32-bit machines).&lt;/li&gt;
&lt;li&gt;After VPN client has been installed, you can see the VPN connection on your Windows network connection list. Click on the network to connect. When prompted by the VPN client, click &lt;strong&gt;Connect&lt;/strong&gt; button to continue.&lt;/li&gt;
&lt;li&gt;[Optional] Now you can use &lt;strong&gt;&lt;em&gt;ipconfig/all&lt;/em&gt;&lt;/strong&gt; to verify if VPN connection has been successfully established&amp;nbsp; (look for PPP adapter).&lt;/li&gt;
&lt;li&gt;Log on to the virtual machine, create a new &lt;strong&gt;&lt;em&gt;Share&lt;/em&gt;&lt;/strong&gt; folder under&lt;strong&gt;&lt;em&gt; c:\&lt;/em&gt;&lt;/strong&gt;. Share the folder with the user you specified when you created the virtual machine. &lt;/li&gt;
&lt;li&gt;On Management Portal, record the virtual machines private IP on its &lt;strong&gt;DASHBOARD&lt;/strong&gt; page. In my case the IP is 10.0.1.4.&lt;/li&gt;
&lt;li&gt;Now you can use Explorer on your local machine and access the shared folder by \\10.0.1.4\Share.&lt;br clear="all"&gt;&lt;a href="http://lh5.ggpht.com/-2ABXxHd6crE/UYmiZ9vEu7I/AAAAAAAABKU/Fw7T3VTi3_A/s1600-h/image%25255B16%25255D.png"&gt;&lt;img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://lh6.ggpht.com/-TDLPYS8f-4c/UYmiaB34olI/AAAAAAAABKc/Y8Z-_VHOwrw/image_thumb%25255B8%25255D.png?imgmax=800" width="509" height="267"&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;  &lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/PpMhqefyY7g" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/8383034761619096052/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2013/05/walkthrough-file-sharing-between-your.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/8383034761619096052?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/8383034761619096052?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/PpMhqefyY7g/walkthrough-file-sharing-between-your.html" title="Walkthrough: File Sharing Between Your Local Machine And Your Virtual Machines on Windows Azure" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/-43xK4Vgzhy4/UYmhu9V8fiI/AAAAAAAABJ4/ciqFOEABgq4/s72-c/image_thumb%25255B2%25255D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2013/05/walkthrough-file-sharing-between-your.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEIHRXk9cSp7ImA9WhBUFUw.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-5439432433739878957</id><published>2013-04-30T11:08:00.001-07:00</published><updated>2013-05-02T10:42:14.769-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-05-02T10:42:14.769-07:00</app:edited><title>Online Contents on Windows Azure SDK 2.0 (Being Updated NOW!)</title><content type="html">&lt;h3&gt;Announcements and Updates&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://weblogs.asp.net/scottgu/archive/2013/04/30/announcing-the-release-of-windows-azure-sdk-2-0-for-net.aspx"&gt;Announcement (Scott Guthrie's blog)&lt;/a&gt;  &lt;li&gt;&lt;a href="http://www.windowsazure.com/en-us/community/blog/"&gt;Windows Azure team blog&lt;/a&gt;  &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/windowsazure/gg441573.aspx"&gt;What's New in Windows Azure&lt;/a&gt; &lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;MSDN&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/windowsazure/dn169556.aspx"&gt;Windows Azure SDK for .NET 2.0 Release Notes&lt;/a&gt;  &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/dn198643.aspx"&gt;What's New in the Windows Azure SDK 2.0 Release (April 2013)&lt;/a&gt;  &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/windowsazure/ff683673.aspx"&gt;What's New in the Windows Azure Tools&lt;/a&gt; &lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;Channel 9&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://channel9.msdn.com/Shows/Cloud+Cover/Episode-106-Scott-Guthrie-Discusses-Windows-Azure-SDK-20"&gt;Episode 106 - Scott Guthrie Discusses Windows Azure SDK 2.0&lt;/a&gt;  &lt;li&gt;&lt;a href="http://channel9.msdn.com/Blogs/Subscribe/Whats-new-in-the-Service-Bus-NET-SDK-20"&gt;What's new in the Service Bus .NET SDK 2.0&lt;/a&gt;&lt;!--EndFragment--&gt;  &lt;ul&gt;&lt;!--EndFragment--&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;blog.haishibai.com&lt;/h3&gt; &lt;ul&gt; &lt;li&gt; &lt;h3&gt;SDK 2.0&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://haishibai.blogspot.com/2013/04/windows-azure-sdk-20-features-1-even.html"&gt;Windows Azure SDK 2.0 Features (1) – A Even Better Server Explorer&lt;/a&gt;  &lt;li&gt;&lt;a href="http://haishibai.blogspot.com/2013/04/windows-azure-sdk-20-features-2-even.html"&gt;Windows Azure SDK 2.0 Features (2) – A Even Better Web Sites Experience&lt;/a&gt;  &lt;li&gt;&lt;a href="http://haishibai.blogspot.com/2013/04/windows-azure-sdk-20-features-3-even.html"&gt;Windows Azure SDK 2.0 Features (3) – Even Bigger Machines&lt;/a&gt;  &lt;li&gt;&lt;a href="http://haishibai.blogspot.com/2013/04/windows-azure-sdk-20-features-4-even.html"&gt;Windows Azure SDK 2.0 Features (4) – Even More Things You May be Interested&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;li&gt; &lt;h3&gt;Service Bus&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://haishibai.blogspot.com/2013/01/new-features-in-service-bus-preview.html"&gt;New features in Service Bus Preview Library (January 2013) - 1: Message Pump&lt;/a&gt;  &lt;li&gt;&lt;a href="http://haishibai.blogspot.com/2013/01/new-features-in-service-bus-preview_27.html"&gt;New features in Service Bus Preview Library (January 2013) – 2: Auto-expiration&lt;/a&gt;  &lt;li&gt;&lt;a href="http://haishibai.blogspot.com/2013/01/new-features-in-service-bus-preview_29.html"&gt;New features in Service Bus Preview Library (January 2013) – 3: Queue/Subscription Shared Access Authorization&lt;/a&gt;  &lt;li&gt;&lt;a href="http://haishibai.blogspot.com/2013/02/new-features-in-service-bus-preview.html"&gt;New features in Service Bus Preview Library (January 2013) – Epilogue: Message Browse&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;Gaurav Mantri’s Personal Blog&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;a title="http://gauravmantri.com/2013/04/30/introducing-windows-azure-sdk-2-0-for-net/" href="http://gauravmantri.com/2013/04/30/introducing-windows-azure-sdk-2-0-for-net/"&gt;http://gauravmantri.com/2013/04/30/introducing-windows-azure-sdk-2-0-for-net/&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;Service Bus Contents (Thanks to &lt;a href="http://abhishekrlal.com/"&gt;Abhishek&lt;/a&gt; for the list)&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;Release notes: &lt;a href="http://t.co/c5aLW86qNj"&gt;http://t.co/c5aLW86qNj&lt;/a&gt;&lt;/li&gt; &lt;li&gt;Clemens’s video: &lt;a href="http://t.co/CpDjbzSy1z"&gt;http://t.co/CpDjbzSy1z&lt;/a&gt;&lt;/li&gt; &lt;li&gt;Auth docs update: &lt;a href="http://msdn.microsoft.com/en-us/library/dn155925.aspx"&gt;Service Bus Authentication&lt;/a&gt;&lt;/li&gt; &lt;li&gt;Blog on Task based APIs: &lt;a href="http://blogs.msdn.com/b/windowsazure/archive/2013/04/11/task-based-apis-for-service-bus.aspx"&gt;http://blogs.msdn.com/b/windowsazure/archive/2013/04/11/task-based-apis-for-service-bus.aspx&lt;/a&gt;&lt;/li&gt; &lt;li&gt;Samples&lt;/li&gt; &lt;ul&gt; &lt;li&gt;SAS: &lt;a href="http://code.msdn.microsoft.com/Shared-Access-Signature-0a88adf8"&gt;http://code.msdn.microsoft.com/Shared-Access-Signature-0a88adf8&lt;/a&gt;&lt;/li&gt; &lt;li&gt;OnMessage: &lt;a href="http://t.co/YWcSqszHPE"&gt;http://t.co/YWcSqszHPE&lt;/a&gt;&lt;/li&gt; &lt;li&gt;Browse: &lt;a href="http://t.co/ezf6i5uRo5"&gt;http://t.co/ezf6i5uRo5&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;  &lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/sMiwxKPm4_g" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/5439432433739878957/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2013/04/online-contents-on-windows-azure-sdk-20.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/5439432433739878957?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/5439432433739878957?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/sMiwxKPm4_g/online-contents-on-windows-azure-sdk-20.html" title="Online Contents on Windows Azure SDK 2.0 (Being Updated NOW!)" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2013/04/online-contents-on-windows-azure-sdk-20.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0cHSHk8fCp7ImA9WhBUE0k.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-2579275762991312589</id><published>2013-04-30T11:03:00.001-07:00</published><updated>2013-04-30T11:03:59.774-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-04-30T11:03:59.774-07:00</app:edited><title>Windows Azure SDK 2.0 Features (4) – Even More Things You May be Interested</title><content type="html">&lt;p&gt;This is the third part of the blog series of introducing some of the exciting new features of Windows Azure SDK 2.0. In this series I’ll take you on a tour of new Windows Azure SDK 2.0 features and experience them firsthand. You can find the SDK 2.0 announcement &lt;a href="http://weblogs.asp.net/scottgu/archive/2013/04/30/announcing-the-release-of-windows-azure-sdk-2-0-for-net.aspx"&gt;here&lt;/a&gt;. You can acquire SDK 2.0 through Web PI, or you can download it &lt;a href="http://www.windowsazure.com/en-us/develop/net/#"&gt;Windows Azure .NET Developer Center&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Previous parts:&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://haishibai.blogspot.com/2013/04/windows-azure-sdk-20-features-1-even.html"&gt;Windows Azure SDK 2.0 Features (1) – A Even Better Server Explorer&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://haishibai.blogspot.com/2013/04/windows-azure-sdk-20-features-2-even.html"&gt;Windows Azure SDK 2.0 Features (2) – A Even Better Web Sites Experience&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://haishibai.blogspot.com/2013/04/windows-azure-sdk-20-features-3-even.html"&gt;Windows Azure SDK 2.0 Features (3) – Even Bigger Machines&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h2&gt;PowerShell Improvements&lt;/h2&gt; &lt;p&gt;While it is packaged separately, PowerShell cmdlets have gone through some changes in the past few months as well. You can find full list of changes &lt;a href="https://github.com/WindowsAzure/azure-sdk-tools/blob/master/ChangeLog.txt"&gt;here&lt;/a&gt;. Here are some of the new features worth mentioning (many thanks to Guang Yang for providing the list):  &lt;ol&gt; &lt;li&gt;Moved to PowerShell 3.0.  &lt;li&gt;Service bus namespace management&amp;nbsp; cmdlets.  &lt;li&gt;Cloud services scaffolding improvements: new role cmdlets and role template support.  &lt;li&gt;Azure Store cmdlets. Create add-on right from PowerShell console.  &lt;li&gt;Storage Blob CRUD cmdlets.  &lt;li&gt;Website diagnostic log streaming.  &lt;li&gt;PS remoting.  &lt;li&gt;High memory VM images.  &lt;li&gt;IaaS support improvements.&lt;/li&gt;&lt;/ol&gt; &lt;h2&gt;Storage Client 2.0&lt;/h2&gt; &lt;p&gt;Now New Projects uses Storage Client 2.0. You can find out what’s new in Storage Client 2.0 &lt;a href="http://msdn.microsoft.com/en-us/library/windowsazure/jj721952.aspx"&gt;here&lt;/a&gt;.&lt;/p&gt; &lt;h2&gt;Windows Azure Active Directory&lt;/h2&gt; &lt;p&gt;In case if you have missed, Windows Azure Active Directory has gone in GA as well. See the announcement &lt;a href="http://blogs.msdn.com/b/windowsazure/archive/2013/04/08/windows-azure-active-directory-ready-for-production-with-over-265-billion-authentications-amp-2-5-million-organizations-served.aspx"&gt;here&lt;/a&gt; and &lt;a href="http://www.cloudidentity.com/blog/2013/04/08/windows-azure-active-directory-reaches-general-availability/"&gt;here&lt;/a&gt;.&lt;/p&gt; &lt;h2&gt;ASP.NET 2012.2 and Web Tools 2012.2&lt;/h2&gt; &lt;p&gt;NOTE: This is NOT part of SDK 2.0 release, however worth mentioning here as it’s also include tones of improvements in terms of features and tooling. Here are couple of quick links:&lt;/p&gt; &lt;p&gt;&lt;a title="http://weblogs.asp.net/scottgu/archive/2013/02/18/announcing-release-of-asp-net-and-web-tools-2012-2-update.aspx" href="http://weblogs.asp.net/scottgu/archive/2013/02/18/announcing-release-of-asp-net-and-web-tools-2012-2-update.aspx"&gt;http://weblogs.asp.net/scottgu/archive/2013/02/18/announcing-release-of-asp-net-and-web-tools-2012-2-update.aspx&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a title="http://sedodream.com/2013/02/19/VideosOnWebPublishUpdatesInASPNET20122.aspx" href="http://sedodream.com/2013/02/19/VideosOnWebPublishUpdatesInASPNET20122.aspx"&gt;http://sedodream.com/2013/02/19/VideosOnWebPublishUpdatesInASPNET20122.aspx&lt;/a&gt;&lt;/p&gt; &lt;h2&gt;Service Bus New Features&lt;/h2&gt; &lt;p&gt;I’ve written a 4-part series on Service Bus new features while the features were in preview. Now you can use these features in production:&lt;/p&gt; &lt;p&gt;&lt;a href="http://haishibai.blogspot.com/2013/01/new-features-in-service-bus-preview.html"&gt;New features in Service Bus Preview Library (January 2013) - 1: Message Pump&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://haishibai.blogspot.com/2013/01/new-features-in-service-bus-preview_27.html"&gt;New features in Service Bus Preview Library (January 2013) – 2: Auto-expiration&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://haishibai.blogspot.com/2013/01/new-features-in-service-bus-preview_29.html"&gt;New features in Service Bus Preview Library (January 2013) – 3: Queue/Subscription Shared Access Authorization&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://haishibai.blogspot.com/2013/02/new-features-in-service-bus-preview.html"&gt;New features in Service Bus Preview Library (January 2013) – Epilogue: Message Browse&lt;/a&gt;&lt;/p&gt;  &lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/o9LV9eAvYQs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/2579275762991312589/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2013/04/windows-azure-sdk-20-features-4-even.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/2579275762991312589?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/2579275762991312589?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/o9LV9eAvYQs/windows-azure-sdk-20-features-4-even.html" title="Windows Azure SDK 2.0 Features (4) – Even More Things You May be Interested" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2013/04/windows-azure-sdk-20-features-4-even.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkAASHg_fSp7ImA9WhBUE0k.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-3106677148096920522</id><published>2013-04-30T10:59:00.001-07:00</published><updated>2013-04-30T10:59:09.645-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-04-30T10:59:09.645-07:00</app:edited><title>Windows Azure SDK 2.0 Features (3) – Even Bigger Machines</title><content type="html">&lt;p&gt;This is the third part of the blog series of introducing some of the exciting new features of Windows Azure SDK 2.0. In this series I’ll take you on a tour of new Windows Azure SDK 2.0 features and experience them firsthand. You can find the SDK 2.0 announcement &lt;a href="http://weblogs.asp.net/scottgu/archive/2013/04/30/announcing-the-release-of-windows-azure-sdk-2-0-for-net.aspx"&gt;here&lt;/a&gt;. You can acquire SDK 2.0 through Web PI, or you can download it &lt;a href="http://www.windowsazure.com/en-us/develop/net/#"&gt;Windows Azure .NET Developer Center&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Previous parts:&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://haishibai.blogspot.com/2013/04/windows-azure-sdk-20-features-1-even.html"&gt;Windows Azure SDK 2.0 Features (1) – A Even Better Server Explorer&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://haishibai.blogspot.com/2013/04/windows-azure-sdk-20-features-2-even.html"&gt;Windows Azure SDK 2.0 Features (2) – A Even Better Web Sites Experience&lt;/a&gt;&lt;/p&gt; &lt;h2&gt;High Memory Machines&lt;/h2&gt; &lt;p&gt;With Windows Azure IaaS went GA (see announcements on &lt;a href="http://blogs.msdn.com/b/windowsazure/archive/2013/04/16/the-power-of-and.aspx"&gt;MSDN&lt;/a&gt; and &lt;a href="http://weblogs.asp.net/scottgu/archive/2013/04/16/windows-azure-general-availability-of-infrastructure-as-a-service-iaas.aspx"&gt;Scott Gu's blog&lt;/a&gt;), developers and ISVs can now take advantages of&amp;nbsp; more VM image templates, larger VM sizes and reduced VM prices. And because now IaaS is in GA status, their VMs running on Windows Azure&amp;nbsp; are formally assured with one of the industry’s highest monthly SLAs. &lt;/p&gt; &lt;p&gt;Windows IaaS now offer two types of high memory machines, A6 (28GB/4 core) and A7(56GB/8 core). A machine with more cores and higher memory enables you to scale-up your application to improve system performance and to increase system throughput. More importantly, it enables you to run your existing applications against bigger loads instead of having to change your application architecture for scaling out. Of course, scaling out is definitely the preferred way of scaling on Windows Azure (and any other cloud platforms). However, changing application architecture is not an easy task, if even possible at all (for instance when you use 3rd party applications that are designed for single machines). Now with the high memory machines, not only you can deploy your existing applications that require high memory directly on IaaS, you can also design your Cloud Services to take advantage of these machines.&lt;/p&gt; &lt;h2&gt;Sample Scenario&lt;/h2&gt; &lt;p&gt;In this sample scenario, we’ll create a Cloud Service that allows users to navigate through large data sets. The data sets I chose to use in this case are &lt;a href="http://svs.gsfc.nasa.gov/vis/a000000/a003600/a003652/"&gt;Sea Surface Temperature, Salinity and Density data sets from NASA&lt;/a&gt;. The data sets consist of 10,800 1920x1080 .tiff images, which occupy about 7.3G of disk space. The idea is to provide a web site that allows user to navigate through the data sets and switch freely among the three images series. To improve loading speed, I’m using a co-located cache cluster to cache image frames. Obviously the bigger the cache, the more pictures I’ll be able to preload into the cache to provide a better user experience.&lt;/p&gt; &lt;p&gt;I’ve pre-loaded all images to my Windows Azure storage account. When the web role starts, it will start to pre-load&amp;nbsp; as many images as possible. As a user requests for a images, the system will check the cache first, if the image is not in cache, it queues a new loading request. &lt;/p&gt; &lt;p&gt;In future versions, more analytical features will be added, such as looking for sudden changes in image series, comparing different images, etc.&lt;/p&gt; &lt;p&gt;I picked this scenario out of tens of candidates, many of which are compute-intensive scenarios. However, I picked this scenario at the end because it uses every aspects of the powerful machine offering – more cores, abundant memory, and higher network bandwidth allocations. We often hear people saying “that’s a Big Data problem” when they see a large amount of data. However, in my opinion, Big Data is not a problem, it’s a system. It’s a system to gain BI from various of data sources and analysis. A Big Data system include 1) data discovery; 2) data collection; 3) data transforms; 4) data storage; 5) analysis; 6) result presentation and sharing. Running a complex simulation only focuses on the fifth part. On the other hand, this scenario shows how to collect, store, transform, and share large amount of data. &lt;/p&gt; &lt;h2&gt;Implementation&lt;/h2&gt; &lt;p&gt;The project is a&amp;nbsp; Cloud Service with a ASP.NET MVC 4 Web Role (using Internet Application template). I enabled co-located cache with 50% of memory allocated for the cache cluster with cache entities living forever.&amp;nbsp; Images are served to clients via a API controller. The following is the gist of this part of code: &lt;pre class="csharpcode"&gt;DataCache cache = &lt;span class="kwrd"&gt;new&lt;/span&gt; DataCache();
var index = &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(&lt;span class="str"&gt;"{0}-{1:0000}"&lt;/span&gt;, series, frame);
HttpResponseMessage response = &lt;span class="kwrd"&gt;new&lt;/span&gt; HttpResponseMessage();         
var data = cache.Get(index);   
&lt;span class="kwrd"&gt;if&lt;/span&gt; (data != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
{
    response.Content = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamContent(&lt;span class="kwrd"&gt;new&lt;/span&gt; MemoryStream((&lt;span class="kwrd"&gt;byte&lt;/span&gt;[])data));
    response.Content.Headers.ContentType = &lt;span class="kwrd"&gt;new&lt;/span&gt; MediaTypeHeaderValue(&lt;span class="str"&gt;"image/tiff"&lt;/span&gt;);
}
&lt;span class="kwrd"&gt;else&lt;/span&gt;
{
    &lt;span class="rem"&gt;//queue another request to get the image from blog storage and then put it in cache.&lt;/span&gt;
}&lt;/pre&gt;
&lt;h2&gt;Result&lt;/h2&gt;
&lt;p&gt;I’ve published an early version of the app on one of the A7 machines (&lt;a title="http://oceandatasample.cloudapp.net/" href="http://oceandatasample.cloudapp.net/"&gt;http://oceandatasample.cloudapp.net/&lt;/a&gt;). The publish process is exactly as before. The only thing I did was to change my service definition to use a large VM:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://lh6.ggpht.com/-QC8Wv3Fu_yw/UYAGZY9EGlI/AAAAAAAABJM/X9wWiFjWJv4/s1600-h/image11.png"&gt;&lt;img title="image" 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="image" src="http://lh3.ggpht.com/-vIh7G1vw6qM/UYAGZlBAdWI/AAAAAAAABJU/fyu-dr_E1wE/image_thumb5.png?imgmax=800" width="447" height="203"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The application largely works. You can drag the slider to navigate through 3600 frames of HD images of each data series, and you can switch among data series at any time by clicking on corresponding water drops at the top of the screen. &lt;u&gt;The play buttons don’t work quite right yet&lt;/u&gt;. &lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;a href="http://lh6.ggpht.com/-IM4eTygmfHE/UYAGaVVoYJI/AAAAAAAABJc/2cr9ChZWxp4/s1600-h/image7.png"&gt;&lt;img title="image" 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="image" src="http://lh5.ggpht.com/-7I0IAJ2XQvM/UYAGbMMEoaI/AAAAAAAABJk/oDOY8DIJCrg/image_thumb3.png?imgmax=800" width="448" height="354"&gt;&lt;/a&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;  &lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/1xehUi1y98k" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/3106677148096920522/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2013/04/windows-azure-sdk-20-features-3-even.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/3106677148096920522?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/3106677148096920522?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/1xehUi1y98k/windows-azure-sdk-20-features-3-even.html" title="Windows Azure SDK 2.0 Features (3) – Even Bigger Machines" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/-vIh7G1vw6qM/UYAGZlBAdWI/AAAAAAAABJU/fyu-dr_E1wE/s72-c/image_thumb5.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2013/04/windows-azure-sdk-20-features-3-even.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkEESXgzeSp7ImA9WhBUE0k.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-6464468211059161512</id><published>2013-04-30T10:56:00.001-07:00</published><updated>2013-04-30T10:56:48.681-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-04-30T10:56:48.681-07:00</app:edited><title>Windows Azure SDK 2.0 Features (2) – A Even Better Web Sites Experience</title><content type="html">&lt;p&gt;This is the third part of the blog series of introducing some of the exciting new features of Windows Azure SDK 2.0. In this series I’ll take you on a tour of new Windows Azure SDK 2.0 features and experience them firsthand. You can find the SDK 2.0 announcement &lt;a href="http://weblogs.asp.net/scottgu/archive/2013/04/30/announcing-the-release-of-windows-azure-sdk-2-0-for-net.aspx"&gt;here&lt;/a&gt;. You can acquire SDK 2.0 through Web PI, or you can download it &lt;a href="http://www.windowsazure.com/en-us/develop/net/#"&gt;Windows Azure .NET Developer Center&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Previous parts:&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://haishibai.blogspot.com/2013/04/windows-azure-sdk-20-features-1-even.html"&gt;Windows Azure SDK 2.0 Features (1) – A Even Better Server Explorer&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Window Azure Web Sites has been one of the most popular services that new Windows Azure users have been enjoying. You can create a new web site in seconds and your web site is up and running in no time on one of the most advanced data centers of the world – for free! You can learn more about Windows Azure Web Sites on &lt;a href="http://www.windowsazure.com"&gt;www.windowsazure.com&lt;/a&gt;. Ever since the beginning the service has been well known for its simplicity, speed, and friendly developer experience. Now, with Windows Azure SDK 2.0 provide you even better experiences by integrating Web Sites into Visual Studio Explorer, and providing live log data streaming right into Visual Studio.&lt;/p&gt; &lt;h3&gt;Server Explorer Support&lt;/h3&gt; &lt;p&gt;Yes! Now you can manage your Web Sites from Visual Studio Server Explorer as well!&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-YaUlHxBcb3s/UYAFrND8AUI/AAAAAAAABG8/ym6sO_A9K8o/s1600-h/image_thumb192.png"&gt;&lt;img title="image_thumb19" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image_thumb19" src="http://lh4.ggpht.com/-O7W2VrcOY1Y/UYAFsSXmQxI/AAAAAAAABHE/maTjp3_Umnc/image_thumb19_thumb.png?imgmax=800" width="278" height="238"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Right-click on any web site to bring up its contextual menu:&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-U5cvonG171M/UYAFslaFaFI/AAAAAAAABHM/iDXdsIpwzpE/s1600-h/image3.png"&gt;&lt;img title="image" 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="image" src="http://lh5.ggpht.com/-sLaHjKVhnzM/UYAFtdH7NLI/AAAAAAAABHU/MeXcETBbJe0/image_thumb1.png?imgmax=800" width="282" height="170"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;From the menu you can perform common operations such as browsing to the web site, open management portal to manage the site, to stop/start the site, etc.&lt;/p&gt; &lt;p&gt;That’s something cool, but I won’t call it amazing. However, here’s something that will knock your socks off – right-click one of your Web Sites and select &lt;strong&gt;View Stream Logs in Output Window. &lt;/strong&gt;Then, launch your Web Site and perform some operations. You can see your application tracing information in the output window – live! And you can also download the log files by clicking on download button (indicated by the arrow in the following screenshot). In my case the tracing information is in Chinese because I’ve been working on a couple of localization scenarios&amp;nbsp; - but you get the idea!&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-DEmtWe4Xkm4/UYAFttf2HmI/AAAAAAAABHc/b1M_CxOPVAU/s1600-h/image_thumb222.png"&gt;&lt;img title="image_thumb22" 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="image_thumb22" src="http://lh3.ggpht.com/-x7dG_fwVJ6k/UYAFuZaRNFI/AAAAAAAABHk/x8r9tE90wj4/image_thumb22_thumb.png?imgmax=800" width="525" height="161"&gt;&lt;/a&gt;&lt;/p&gt; &lt;h3&gt;More Diagnostics Support &amp;amp; Others &lt;/h3&gt; &lt;p&gt;The log streaming feature is very cool indeed, but that’s not all the diagnostics support the team has put into this release. In this part of the article I’ll walk through you a small web site to experience other diagnostic features as well as some other improvements in this version of SDK.&lt;/p&gt; &lt;ol&gt; &lt;li&gt;In Visual Studio 2012, create a new ASP.NET MVC4 Web Project&amp;nbsp; (using Internet Application template).  &lt;li&gt;Before we publish the site, let’s modify the HomeController to trace each of the actions. For instance, add this line to Index() method (you need to resolve namespace for &lt;strong&gt;&lt;em&gt;Trace&lt;/em&gt;&lt;/strong&gt; ):&lt;pre class="csharpcode"&gt;Trace.TraceInformation(&lt;span class="str"&gt;"Landed on home page"&lt;/span&gt;);&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;li&gt;In solution explorer, right-click on the web site project and select “Publish…”. 
&lt;li&gt;Click “Import…” to import publish profile. Hmm… now there pops a &lt;strong&gt;Import Publish Profile&lt;/strong&gt; dialog,&amp;nbsp; which allows you either to import a Web Site publish profile as before, or to import the profile from an existing site:&lt;br clear="all"&gt;&lt;a href="http://lh3.ggpht.com/-xZEjQjBt5pc/UYAFu3FjZ1I/AAAAAAAABHs/MalMrw9wPAY/s1600-h/image8.png"&gt;&lt;img title="image" 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="image" src="http://lh6.ggpht.com/-udjssk6UThI/UYAFwtoLmCI/AAAAAAAABH0/4ZWIfTRtMiU/image_thumb4.png?imgmax=800" width="387" height="232"&gt;&lt;/a&gt; 
&lt;li&gt;After you’ve imported the profile, follow the wizard to finish publishing. 
&lt;li&gt;Now refresh the Server Explorer, you should see your web site listed. Right-click on the site and select &lt;strong&gt;View Streaming Logs in Output Window &lt;/strong&gt;from the popup menu. 
&lt;li&gt;Navigate to different pages, and you’ll see your traced information appended to output window. The following shows in session I had with my test site. You can see the log messages, as well as inactivity reports before I stopped the streaming. &lt;br clear="all"&gt;&lt;a href="http://lh3.ggpht.com/-35acby4UPmE/UYAFy51njdI/AAAAAAAABH8/kwjoFOhE1to/s1600-h/image16.png"&gt;&lt;img title="image" 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="image" src="http://lh4.ggpht.com/-xsKqIJvP5j0/UYAFzAy_ZoI/AAAAAAAABIE/T0dTjqku97Q/image_thumb8.png?imgmax=800" width="406" height="89"&gt;&lt;/a&gt; 
&lt;li&gt;Right-click on the site and click &lt;strong&gt;View Settings&lt;/strong&gt; in popup menu. 
&lt;li&gt;In the &lt;strong&gt;Configuration&lt;/strong&gt; view, you can configure most of your web site settings here, and you can click on &lt;strong&gt;Full Web Site Settings&lt;/strong&gt; to open Windows Azure Management Portal and directly land on the setting page of the site. You can see you can easily turn on and off web server logging, detailed error messages, as well as failed request tracing here. Our application log is current set to save to local file system with log level set to &lt;strong&gt;&lt;em&gt;Information&lt;/em&gt;&lt;/strong&gt;. You can also &lt;font color="#c0504d"&gt;&lt;strong&gt;save your logs into your Windows Azure storage account&lt;/strong&gt;&lt;/font&gt;. We’ll see how to do it next.&lt;br clear="all"&gt;&lt;a href="http://lh3.ggpht.com/-M7yzu8kKJok/UYAFza41qKI/AAAAAAAABIM/LHA5pi859d4/s1600-h/image20.png"&gt;&lt;img title="image" 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="image" src="http://lh4.ggpht.com/-kUs40WhTXGc/UYAF0Y5awPI/AAAAAAAABIU/jZl84Q3564M/image_thumb10.png?imgmax=800" width="442" height="411"&gt;&lt;/a&gt; 
&lt;li&gt;Go to &lt;strong&gt;Logs&lt;/strong&gt; tab. Click on &lt;strong&gt;Configure Logging&lt;/strong&gt; link. This brings you to the management portal. 
&lt;li&gt;Change &lt;strong&gt;APPLICATION LOGGING (STORAGE)&lt;/strong&gt; to &lt;strong&gt;ON &lt;/strong&gt;(I also changed &lt;strong&gt;LOGGING LEVEL&lt;/strong&gt; to &lt;strong&gt;&lt;em&gt;Information&lt;/em&gt;&lt;/strong&gt; in this case). If you see this option disabled, that means you don’t have a storage account linked to this site yet. Go to &lt;strong&gt;LINKED RESOURCES&lt;/strong&gt; tab and link to a storage account of your choice.&lt;br clear="all"&gt;&lt;a href="http://lh3.ggpht.com/-6K2fV4fdnYg/UYAF1OHugcI/AAAAAAAABIc/do1IKqK6ksY/s1600-h/image39.png"&gt;&lt;img title="image" 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="image" src="http://lh4.ggpht.com/-HssuDlHNncc/UYAF12BshLI/AAAAAAAABIk/H1QHtFLVHJA/image_thumb19.png?imgmax=800" width="310" height="262"&gt;&lt;/a&gt; 
&lt;li&gt;Click &lt;strong&gt;manage connection&lt;/strong&gt; button. Click on &lt;strong&gt;Synchronize primary key&lt;/strong&gt; button and storage key is synced over – isn’t that sweet?&lt;br clear="all"&gt;&lt;a href="http://lh4.ggpht.com/-z9yIDyxJl50/UYAF2TkWGAI/AAAAAAAABIs/WbWSFksG6qM/s1600-h/image28.png"&gt;&lt;img title="image" 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="image" src="http://lh5.ggpht.com/-oy_5S6dRc2M/UYAF241FsyI/AAAAAAAABI0/xX2KQr0tOK8/image_thumb14.png?imgmax=800" width="319" height="242"&gt;&lt;/a&gt; 
&lt;li&gt;Save your changes. 
&lt;li&gt;Navigate through pages. And refresh the &lt;strong&gt;Logs&lt;/strong&gt; tab to see latest trace entries:&lt;br clear="all"&gt;&lt;a href="http://lh6.ggpht.com/-HgpH4qlYuzE/UYAF3GkRvGI/AAAAAAAABI8/YkiC8BQEXp0/s1600-h/image32.png"&gt;&lt;img title="image" 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="image" src="http://lh3.ggpht.com/-eQeMoazx4AQ/UYAF3qwACZI/AAAAAAAABJE/aX3j_PShMcM/image_thumb16.png?imgmax=800" width="447" height="198"&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;  &lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/ZPPZxRF4r4U" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/6464468211059161512/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2013/04/windows-azure-sdk-20-features-2-even.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/6464468211059161512?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/6464468211059161512?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/ZPPZxRF4r4U/windows-azure-sdk-20-features-2-even.html" title="Windows Azure SDK 2.0 Features (2) – A Even Better Web Sites Experience" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/-O7W2VrcOY1Y/UYAFsSXmQxI/AAAAAAAABHE/maTjp3_Umnc/s72-c/image_thumb19_thumb.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2013/04/windows-azure-sdk-20-features-2-even.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkQMQ384eyp7ImA9WhBUE0k.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-4329398851391654701</id><published>2013-04-30T10:53:00.001-07:00</published><updated>2013-04-30T10:53:02.133-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-04-30T10:53:02.133-07:00</app:edited><title>Windows Azure SDK 2.0 Features (1) – A Even Better Server Explorer</title><content type="html">&lt;p&gt;This is the first part of the blog series of introducing some of the exciting new features of Windows Azure SDK 2.0. In this series I’ll take you on a tour of new Windows Azure SDK 2.0 features and experience them firsthand. You can find the SDK 2.0 announcement &lt;a href="http://weblogs.asp.net/scottgu/archive/2013/04/30/announcing-the-release-of-windows-azure-sdk-2-0-for-net.aspx"&gt;here&lt;/a&gt;. You can acquire SDK 2.0 through Web PI, or you can download it &lt;a href="http://www.windowsazure.com/en-us/develop/net/#"&gt;Windows Azure .NET Developer Center&lt;/a&gt;.  &lt;h2&gt;Server Explorer Improvements&lt;/h2&gt; &lt;p&gt;In the past releases, Windows Azure SDK has been steadily supplementing Visual Studio Server Explorer with more and more productivity features. These features put the ability of provisioning and managing cloud resources at the fingertips of developers. Developers don’t have to leave Visual Studio if they found they needed to get some cloud resources provisioned, or to get connection information to a resource. And they can use data manipulation capabilities to quickly test their code while programming. Here are some new features that got added with Windows Azure SDK 2.0.&lt;/p&gt; &lt;h3&gt;Table Storage Tooling Improvements&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;Now you can directly &lt;strong&gt;&lt;font color="#c0504d"&gt;create new storage Tables&lt;/font&gt;&lt;/strong&gt; within Server Explorer:&lt;br clear="all"&gt;&lt;a href="http://lh6.ggpht.com/-QuViCpvTiSU/UYAE5QP0dDI/AAAAAAAABFc/F2R_CSA2Qp4/s1600-h/image3.png"&gt;&lt;img title="image" 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="image" src="http://lh3.ggpht.com/-NqubqqmTuws/UYAE50UXD_I/AAAAAAAABFk/NKC98heXkrw/image_thumb1.png?imgmax=800" width="319" height="204"&gt;&lt;/a&gt;  &lt;li&gt;Now Table explorer provides &lt;strong&gt;&lt;font color="#c0504d"&gt;complete CRUD support&lt;/font&gt;&lt;/strong&gt; of table entities. The following screenshot shows the &lt;strong&gt;Add Entity&lt;/strong&gt; window, which is quite self-explanatory:&lt;br clear="all"&gt;&lt;a href="http://lh3.ggpht.com/-qqroCBSNnaY/UYAE6M3aBDI/AAAAAAAABFs/0f2pBcM6mDk/s1600-h/image7.png"&gt;&lt;img title="image" 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="image" src="http://lh3.ggpht.com/-cOYyyvxl7Bw/UYAE6sZ43oI/AAAAAAAABF0/z0BdGQ-Ml0Y/image_thumb3.png?imgmax=800" width="533" height="304"&gt;&lt;/a&gt;  &lt;li&gt;There’s even a nice &lt;font color="#c0504d"&gt;&lt;strong&gt;Query Builder&lt;/strong&gt;&lt;/font&gt; that allows you to build up table queries without needing to understand Data Service Queries:&lt;br clear="all"&gt;&lt;a href="http://lh5.ggpht.com/-1KruZegYd1o/UYAE6zKti4I/AAAAAAAABF8/S8eFa2KAGAA/s1600-h/image14.png"&gt;&lt;img title="image" 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="image" src="http://lh6.ggpht.com/-tPleEfjPDuM/UYAE7WU8NcI/AAAAAAAABGE/TG38aB9bOoM/image_thumb8.png?imgmax=800" width="537" height="325"&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;Cloud Service Diagnostics&lt;/h3&gt; &lt;p&gt;Throughout the SDK versions Cloud Service diagnostics has been becoming easier and easier. Now with the improved Server Explorer, you can view diagnostics data and modify diagnostics settings direct within Visual Studio. If you had used &lt;strong&gt;&lt;em&gt;diagnostics.wadcfg&lt;/em&gt;&lt;/strong&gt;, or had tried to configure performance counters in code, you’d be delighted to find out the rich editing features provided by diagnostics settings dialog.&lt;/p&gt; &lt;ul&gt; &lt;li&gt;View diagnostics data in a combined view in Visual Studio. Now you can request diagnostics logs at any time from Visual Studio and view them in an intuitive, combined view:&lt;br clear="all"&gt;&lt;a href="http://lh6.ggpht.com/-SEG8x6AJo3A/UYAE75U2krI/AAAAAAAABGM/sC191tBTY9k/s1600-h/image18.png"&gt;&lt;img title="image" 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="image" src="http://lh6.ggpht.com/-Nz3CLFOClbE/UYAE8L-lUPI/AAAAAAAABGU/3uwbucYMf-c/image_thumb10.png?imgmax=800" width="425" height="248"&gt;&lt;/a&gt;  &lt;li&gt;In the combined summary view, you can view Windows Azure application logs, Event logs, Windows Azure infrastructure logs, as well as contents in Windows Azure log directories at the same time. This view allows you to view all log sources at the same time so that you can easily discover correlations of these entries from different sources. This is&amp;nbsp; definitely a very powerful tool to enable more efficient troubleshooting processes. The following screenshots shows the testing diagnostics data one of my test applications generates:&lt;br clear="all"&gt;&lt;a href="http://lh3.ggpht.com/-wlZfbkcWy0g/UYAE9L5ajAI/AAAAAAAABGc/7DGHOoiliic/s1600-h/image34.png"&gt;&lt;img title="image" 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="image" src="http://lh3.ggpht.com/-_I2k-hvXgG8/UYAE97mvU5I/AAAAAAAABGk/LPZShtsD5-o/image_thumb18.png?imgmax=800" width="713" height="344"&gt;&lt;/a&gt;  &lt;li&gt;You can remotely change diagnostics settings from Visual Studio using diagnostics configuration dialog. For instance, you can change data transfer schedules and filters, and you can modify what performance counters to be collected.&lt;br clear="all"&gt;&lt;a href="http://lh6.ggpht.com/-D8ZHCOleh10/UYAE-zRSq3I/AAAAAAAABGs/DWhInk2C2zE/s1600-h/image25.png"&gt;&lt;img title="image" 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="image" src="http://lh4.ggpht.com/-9vXrcUO-b_c/UYAE_CDfJLI/AAAAAAAABG0/QKOeCVhd_P8/image_thumb13.png?imgmax=800" width="437" height="296"&gt;&lt;/a&gt;&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;  &lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/mwAwn5ucXZM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/4329398851391654701/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2013/04/windows-azure-sdk-20-features-1-even.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/4329398851391654701?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/4329398851391654701?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/mwAwn5ucXZM/windows-azure-sdk-20-features-1-even.html" title="Windows Azure SDK 2.0 Features (1) – A Even Better Server Explorer" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/-NqubqqmTuws/UYAE50UXD_I/AAAAAAAABFk/NKC98heXkrw/s72-c/image_thumb1.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2013/04/windows-azure-sdk-20-features-1-even.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkYDQ3Y4fyp7ImA9WhBXEEk.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-4629717919493591095</id><published>2013-03-23T06:09:00.001-07:00</published><updated>2013-03-23T06:09:32.837-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-03-23T06:09:32.837-07:00</app:edited><title>Cloud + Devices Scenarios (1): Say a Picture</title><content type="html">&lt;p&gt;&lt;strong&gt;&lt;em&gt;Say a Picture&lt;/em&gt;&lt;/strong&gt; is a sample Windows Azure Cloud Service that allows remote users to dictate a picture together over connected Kinect sensors. Kinect sensors enable users to interact with the system in a casual living room setting, with multiple participants work together either locally or remotely. The solution combines device’s capability of data collection and cloud’s ability of coordinating work over the Internet to create an enjoyable experience for users. In this post I’ll walk through the creative process of this project so that you can build similar (and cooler) applications like this. I’ll also provide a link to download the complete source code at the end of this post. &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-PmCzA746L-w/UU2pgTjGd2I/AAAAAAAABEU/AoFWdLJqomQ/s1600-h/image%25255B3%25255D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-RzWv80NbaJ4/UU2pgluNsGI/AAAAAAAABEc/9s2SbiE1iRY/image_thumb%25255B1%25255D.png?imgmax=800" width="591" height="283"&gt;&lt;/a&gt;  &lt;h5&gt;&lt;/h5&gt; &lt;h4&gt;What you need&lt;/h4&gt; &lt;ul&gt; &lt;li&gt;Microsoft &lt;a href="http://www.microsoft.com/en-us/kinectforwindows/"&gt;Kinect for Windows&lt;/a&gt; &lt;li&gt;Get &lt;a href="http://www.microsoft.com/en-us/kinectforwindows/develop/developer-downloads.aspx"&gt;Kinect SDK&lt;/a&gt;. I recommend to get both SDK as well as the Toolkit from the page.  &lt;li&gt;Microsoft &lt;a href="http://www.microsoft.com/en-us/download/details.aspx?id=10121"&gt;Speech SDK&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt; &lt;h4&gt;System Architecture&lt;/h4&gt; &lt;p&gt;Our system is comprised of a client and a server. The client talks to the Kinect sensor and uses speech recognition to convert spoken English to short commands, such as “add a horse” and “make it red”. Then, the client sends parsed short commands to the server. The server takes in commands sent from client and converts them into drawings on a HTML 5 canvas. The server is designed to support multiple concurrent sessions. Clients use the same session id share the same canvas so that multiple remote users can join the same painting session to work on the same painting. The following diagram depicts the overall system architecture:  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-5yHJ1CcxMgE/UU2phHRF3tI/AAAAAAAABEk/0A9aFGtNNuc/s1600-h/image%25255B7%25255D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-jj_6MvVSvTs/UU2phVlObyI/AAAAAAAABEs/pZxAzzuFeYs/image_thumb%25255B3%25255D.png?imgmax=800" width="583" height="337"&gt;&lt;/a&gt;  &lt;h4&gt;Client Implementation&lt;/h4&gt; &lt;p&gt;Client is implemented as a Windows Console application using C#, Kinect SDK as well as Speech SDK. The key of client implementation is the grammar tree that is used by speech recognition engine. The grammar tree is an XML document. The following is a picture representation. As you can see, this grammar is quite simple with a very limited vocabulary. In the diagram, &lt;strong&gt;&lt;em&gt;#object&lt;/em&gt;&lt;/strong&gt; represents one of recognized objects – trees, mountains, horses, and birds, etc.. &lt;strong&gt;&lt;em&gt;#color&lt;/em&gt;&lt;/strong&gt; is one of supported colors such as red, green, and blue. Using an explicit grammar tree not only allows command interpretation much easier (comparing to interpreting natural language), but also allows users to chat casually in between the commands, making it a even better experience. &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-Q6hODwYgAys/UU2ph4huG4I/AAAAAAAABE0/Z0u5AyUbdjA/s1600-h/image%25255B11%25255D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-wWK2rL6hFRM/UU2piHUCiAI/AAAAAAAABE8/pRiUjJr8Z0Q/image_thumb%25255B5%25255D.png?imgmax=800" width="595" height="216"&gt;&lt;/a&gt;  &lt;p&gt;Speech recognition using Speech SDK is rather simple, once you create a &lt;strong&gt;&lt;em&gt;SpeechRecognitionEngine&lt;/em&gt;&lt;/strong&gt; instance, you can load the grammar tree and then simply wait for &lt;strong&gt;&lt;em&gt;SpeechRecognized&lt;/em&gt;&lt;/strong&gt; event, in which you can get recognized text as well as a confidence value that indicates how confident the engine is about the result:&lt;pre&gt;mSpeechEngine = new SpeechRecognitionEngine(info.Id);
using (var memoryStream = new MemoryStream(Encoding.ASCII.GetBytes(Properties.Resources.SpeechGrammar)))
{
  var g = new Grammar(memoryStream);
  mSpeechEngine.LoadGrammar(g);
}
mSpeechEngine.SpeechRecognized +=mSpeechEngine_SpeechRecognized;
...&lt;/pre&gt;
&lt;p&gt;once a short sentence that matches defined grammar rules is detected, the client sends the string to server via an API call.
&lt;h4&gt;Server Implementation&lt;/h4&gt;
&lt;p&gt;Server is implemented as a Windows Azure Cloud Service with a single ASP.NET Web Role. The Web Role uses SignalR to broadcast states to all clients within the same session. And it uses HTML 5 + jQuery as the frontend. Because command interpreter is implemented as a browser-side JavaScript, the server-side code is extremely simple – it gets commands that are passed in by clients, and then broadcasts commands to all clients within the same session:&lt;pre&gt;[HttpGet]
public void SendCommand(string group, string text)
{
  var context = GlobalHost.ConnectionManager.GetHubContext&amp;lt;CommandHub&amp;gt;();
  context.Clients.Group(group).command(new { Command = text });
}&lt;/pre&gt;
&lt;h4&gt;Command Interpreter&lt;/h4&gt;
&lt;p&gt;The command interpreter is not that complex in this case, because we are not dealing complex constructs such as sub clauses. We can simply go through the command from left to right and handle the keywords as we go. A recommended way of creating this interpreter is to create a separate function for each of the keywords. Because we can do linear scan of words in this case, I used a simple array. However if your grammar is more complex, you may want to use operator/operand stacks. The interpreter also maintains a reference to latest referenced object as “it”. For instance, once you added a bird to the canvas, you can use command “move it left” to move the bird because “it” automatically references to the last object you interact with. The following code snippet shows the implementation of the two top-level functions. &lt;strong&gt;&lt;em&gt;handlCommand() &lt;/em&gt;&lt;/strong&gt;handles an incoming command by looping through each words and calling &lt;strong&gt;&lt;em&gt;handleWord()&lt;/em&gt;&lt;/strong&gt; on each one. Then, &lt;strong&gt;&lt;em&gt;handleWord()&lt;/em&gt;&lt;/strong&gt; method calls into corresponding functions based on the keyword it encounters.&lt;pre&gt;function handleCommand(commandText) {
  commandWords = commandText.split(' ');
  var i = 0;
  while (i &amp;lt; commandWords.length) {
     i = handleWord(i);
  }
}
function handleWord(index) {
  switch (commandWords[index]) {
    case 'add':
      return handleAddCommand(index + 1);
    case 'move':
       return handleMoveCommand(index + 1);
  ...
      default:
        return index + 1;
  }
}&lt;/pre&gt;
&lt;p&gt;Note the functions don’t return any errors. They simply skip the sentences they don’t understand and wait for users to try again. A very nice command implemented by this interpreter is the “put it on …” command. For instance, in the following scenario, you have a plant that you want to put on the desk. Instead of moving it around step by step, you can directly say “put it on desk” to make the plant land perfectly on desk. Note in this version of the code I added some hardcoded adjustments to make this scenario work perfectly. A more generic implementation requires a more sophisticated object description/interaction system.
&lt;p&gt;&lt;a href="http://lh5.ggpht.com/-QYOyxO2Tk28/UU2piYlOJqI/AAAAAAAABFE/5AljzIrpQXA/s1600-h/image%25255B15%25255D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-9uHCHD1kaQc/UU2pinUxlZI/AAAAAAAABFM/-kGWtLyqPds/image_thumb%25255B7%25255D.png?imgmax=800" width="430" height="199"&gt;&lt;/a&gt; 
&lt;h4&gt;Application Scenarios&lt;/h4&gt;
&lt;p&gt;There are many possible applications scenarios of using Kinect Speech Recognition + Cloud Service. Here is a short list of some of the scenarios I can immediately think of:
&lt;ul&gt;
&lt;li&gt;Collaborative painting as a casual, multiplayer game. 
&lt;li&gt;Interactive interior design system that allows a designer to work with her clients remotely. And they can work together on the room layout by simply talking about it. 
&lt;li&gt;Collaborative software/hardware/system design, where team members can talk about a possible design and see it painted immediately on the screen. 
&lt;li&gt;Automatic picture/animation generation as you tell a story. This could be a nice touch to bedtime stories. &lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;And with more sophisticated codes, you can do things such as running a physical simulation by simply describe it; playing chess by speaking out your next moves;&amp;nbsp; playing multiplayer strategy game by dictating your troops…. the possibilities are endless.
&lt;h4&gt;What’s next&lt;/h4&gt;
&lt;p&gt;This initial version has only limited functionality. As the goal is to allow users to interact with the system naturally, there are quite some improvements can be made to make user experiences even better. One of enhancements I’m planning is to allow the system to learn about new concepts easily so that the system can be extended to accommodate more and more scenarios. Another area of improvements is to allow rich, natural interactions among objects. The “put x on y” command is a preview of such interactions. 
&lt;p&gt;You can get complete source code &lt;a href="http://azure4fun.blob.core.windows.net/code/SayaPicture-v1.zip"&gt;here&lt;/a&gt;. 
  &lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/pUAxwASa9Fc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/4629717919493591095/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2013/03/cloud-devices-scenarios-1-say-picture.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/4629717919493591095?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/4629717919493591095?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/pUAxwASa9Fc/cloud-devices-scenarios-1-say-picture.html" title="Cloud + Devices Scenarios (1): Say a Picture" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/-RzWv80NbaJ4/UU2pgluNsGI/AAAAAAAABEc/9s2SbiE1iRY/s72-c/image_thumb%25255B1%25255D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2013/03/cloud-devices-scenarios-1-say-picture.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEAMRHY9cSp7ImA9WhBWF0U.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-7760850784697517456</id><published>2013-03-04T01:12:00.001-08:00</published><updated>2013-04-12T10:13:05.869-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-04-12T10:13:05.869-07:00</app:edited><title>A Tour of Windows Azure Active Directory Features in Windows Azure Management Portal – Logging in and Enabling Multi-factor Authentication</title><content type="html">&lt;p&gt;With new release of Windows Azure Management Portal (&lt;a href="http://weblogs.asp.net/scottgu/archive/2013/03/04/windows-azure-updates-android-support-sql-reporting-services-active-directory-more.aspx"&gt;Scott Gu’s announcement&lt;/a&gt;), it’s now possible for you to manage your Windows Azure AD objects in the management portal itself (&lt;a href="http://blogs.msdn.com/b/windowsazure/archive/2013/03/04/more-identity-and-access-management-improvements-in-windows-azure.aspx"&gt;team announcement&lt;/a&gt;). This post provides guided tour of these exciting new features. First, we’ll have a brief review what Windows Azure Active Directory is. Then, we’ll introduce how to get a Windows Azure subscription that is linked to your Windows Azure AD tenant. And then, we’ll go through the basics, starting with correct steps to authenticate in order to see these new features. And at last, we’ll go through steps of setting up multi-factor authentication for managing&amp;nbsp; your Windows Azure subscriptions as well as using it in your own ASP.NET applications.&lt;/p&gt; &lt;h1&gt;&lt;/h1&gt; &lt;h1&gt;What is Windows Azure Active Directory&lt;/h1&gt; &lt;p&gt;Windows Azure Active Directory is a REST-based service made by Microsoft that provides multi-tenant directory service for the cloud. You can either project users from your on-premises Active Directory to your Windows Azure AD tenant, or start with a fresh Windows Azure AD tenant and keep the entire directory on the cloud. Windows Azure Active Directory is designed for SaaS application developers to have a low cost (actually, &lt;a href="http://www.windowsazure.com/en-us/pricing/details/#header-10"&gt;it’s completely free!&lt;/a&gt;), scalable, and cloud-ready directory service that they can easily leverage in their applications. It provides WebSSO capabilities with ws-Federation and SAML 2.0. It also provides a REST-based Graph API that you can use to query directory objects.&amp;nbsp; There are many contents available from Microsoft about Windows Azure Active Directory. I did a &lt;a href="http://haishibai.blogspot.com/2013/02/windows-azure-active-directory-current.html"&gt;survey&lt;/a&gt; a while ago. I recommend you to read through the listed resources in the survey if you want to learn more about Windows Azure Active Directory.&lt;/p&gt; &lt;h1&gt;A Subscription with a Tenant&lt;/h1&gt; &lt;p&gt;At the time when this post is written, you need to create a new Windows Azure subscription using your Windows Azure AD tenant credential. If you are an Office365 user, you already have a Windows Azure AD tenant. If you want to sign up for a free testing tenant, you can follow &lt;a href="http://g.microsoftonline.com/0AX00en/5"&gt;this link&lt;/a&gt;. Once you’ve provisioned your administrator for your Windows Azure AD tenant, you can use that account to log in to &lt;a href="http://www.windowsazure.com"&gt;www.windowsazure.com&lt;/a&gt; to get a new Windows Azure subscription associated with the tenant.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;font color="#8fb08c"&gt;[Updated April 12 – 2013] &lt;/font&gt;&lt;/strong&gt;With Windows Azure Active Directory hitting GA, now you can create and manage directory tenant directly using subscriptions based on a Microsoft account. For more information please see &lt;a href="http://www.cloudidentity.com/blog/2013/04/08/windows-azure-active-directory-reaches-general-availability/"&gt;this blog&lt;/a&gt;.&lt;/p&gt; &lt;h1&gt;Basics&lt;/h1&gt; &lt;ol&gt; &lt;li&gt;Go to &lt;a href="https://manage.windowsazure.com"&gt;https://manage.windowsazure.com&lt;/a&gt;.  &lt;li&gt;Instead of typing in your user id and password in the log in form, click on &lt;strong&gt;Office 365 users: sign in with your organizational account&lt;/strong&gt; link to the left of the screen:&lt;br clear="all"&gt;&lt;a href="http://lh3.ggpht.com/-oaF4OTm-VCc/UTRlVWpVqRI/AAAAAAAAA_k/poUsJtHAzgg/s1600-h/image3.png"&gt;&lt;img title="image" 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="image" src="http://lh5.ggpht.com/-Yt5n4G5LgvA/UTRlV9PZXYI/AAAAAAAAA_s/B6hafgX52F0/image_thumb1.png?imgmax=800" width="357" height="301"&gt;&lt;/a&gt;  &lt;li&gt;Log in with your Windows Azure Active Directory tenant account: &lt;br clear="all"&gt;&lt;a href="http://lh3.ggpht.com/-2K8AzXCGSh8/UTRlWTulDhI/AAAAAAAAA_0/aR4pNzr_ExE/s1600-h/image7.png"&gt;&lt;img title="image" 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="image" src="http://lh4.ggpht.com/-4G6E3qM-_X8/UTRlWwsMEXI/AAAAAAAAA_8/8qr2n6Mv-OA/image_thumb3.png?imgmax=800" width="358" height="289"&gt;&lt;/a&gt;  &lt;li&gt;Once you log in, click on &lt;strong&gt;ACTIVE DIRECTORY&lt;/strong&gt; link in the left pane. You’ll see two tabs on the page: one is &lt;strong&gt;ENTERPRISE DIRECTORY&lt;/strong&gt;, where you manage your tenant objects; the other is &lt;strong&gt;ACCESS CONTROL NAMESPACES&lt;/strong&gt;, where you manage your ACS namespaces:&lt;br clear="all"&gt;&lt;a href="http://lh6.ggpht.com/-ggl26GN5-8g/UTRlXOYR_cI/AAAAAAAABAE/2FgN-J3jaUo/s1600-h/image13.png"&gt;&lt;img title="image" 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="image" src="http://lh4.ggpht.com/-WRR7lWjZZWc/UTRlXseBeBI/AAAAAAAABAM/q5MtZA-Qg7A/image_thumb7.png?imgmax=800" width="654" height="440"&gt;&lt;/a&gt;  &lt;li&gt;Click on the tenant name. You’ll enter the page where you can mange your users, domains, as well as directory sync with on-premises directories:&lt;br clear="all"&gt;&lt;a href="http://lh3.ggpht.com/-bv7VkeRsmUM/UTRlYE1OcuI/AAAAAAAABAU/xymK5MW0gsE/s1600-h/image18.png"&gt;&lt;img title="image" 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="image" src="http://lh6.ggpht.com/-_EGJTGBrwCM/UTRlYTh0aGI/AAAAAAAABAc/wjQlxAHIIlo/image_thumb10.png?imgmax=800" width="650" height="301"&gt;&lt;/a&gt;  &lt;li&gt;Now, with &lt;strong&gt;USERS&lt;/strong&gt; tab selected, let’s click on &lt;strong&gt;CREATE&lt;/strong&gt; button on command bar to create a new user.  &lt;li&gt;Fill out the form. At this point you can choose to assign the user to one of two pre-defined roles, &lt;strong&gt;User&lt;/strong&gt; or &lt;strong&gt;Global Administrator&lt;/strong&gt;. Only &lt;strong&gt;Global Administrator&lt;/strong&gt;s can manage your Windows Azure AD tenants. Here we’ll choose &lt;strong&gt;User&lt;/strong&gt; role. Click next arrow to continue.&lt;br clear="all"&gt;&lt;a href="http://lh6.ggpht.com/-HdUT27_pfMM/UTRlYnGPY-I/AAAAAAAABAk/2xEJOA3mTkg/s1600-h/image%25255B4%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh3.ggpht.com/-JfxwQSgspmo/UTRlZMvWejI/AAAAAAAABAs/5ONtbBbLlbo/image_thumb%25255B1%25255D.png?imgmax=800" width="380" height="313"&gt;&lt;/a&gt;  &lt;li&gt;The new user will be assigned with a temporary password, which has to be changed when the user first logs in. Click on &lt;strong&gt;Create&lt;/strong&gt; button to display the temporary password:&lt;br clear="all"&gt;&lt;a href="http://lh4.ggpht.com/-hCHws7tHIbQ/UTRlZ4hcEtI/AAAAAAAABA0/47HMFLt0oC8/s1600-h/image%25255B10%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh3.ggpht.com/-CGl03TsIT-c/UTRlaMVqjvI/AAAAAAAABA8/Jqf6OYPQh0Q/image_thumb%25255B5%25255D.png?imgmax=800" width="379" height="315"&gt;&lt;/a&gt;  &lt;li&gt;Here you can choose to copy the password to clipboard and share the password manually, or to directly send the password to up to 5 mail addresses for the new user. Click check button to complete the process.&lt;br clear="all"&gt;&lt;a href="http://lh4.ggpht.com/-2yFM8u015MI/UTRlai01zjI/AAAAAAAABBE/1KQwUExSRRk/s1600-h/image%25255B14%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh4.ggpht.com/-5WbRPHlmmsU/UTRlbO2H0xI/AAAAAAAABBM/3E24_4kCdU0/image_thumb%25255B7%25255D.png?imgmax=800" width="385" height="318"&gt;&lt;/a&gt;  &lt;li&gt;To allow this new user to log in to management portal, we need to add him as a co-administrator of our subscription. To do this, click on &lt;strong&gt;SETTINGS&lt;/strong&gt; in the left pane (&lt;font color="#ff0000"&gt;1&lt;/font&gt;), then make sure &lt;strong&gt;ADMINISTRATORS&lt;/strong&gt; tab is selected (&lt;font color="#ff0000"&gt;2&lt;/font&gt;), and finally click on &lt;strong&gt;ADD&lt;/strong&gt; button in command bar (&lt;font color="#ff0000"&gt;3&lt;/font&gt;).&lt;br clear="all"&gt;&lt;a href="http://lh4.ggpht.com/-DBDphEcorrw/UTRlbcs-8hI/AAAAAAAABBU/vUNV3tYV8qU/s1600-h/image%25255B18%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh6.ggpht.com/-ZAa2LUNT3UM/UTRlcMAdDxI/AAAAAAAABBc/T7LTx8I5MdE/image_thumb%25255B9%25255D.png?imgmax=800" width="800" height="299"&gt;&lt;/a&gt;  &lt;li&gt;Enter the email address of this new user, select the subscription(s) you want to grant access to, and then click on check icon to complete the process.&lt;br clear="all"&gt;&lt;br clear="all"&gt;&lt;a href="http://lh3.ggpht.com/-TaxQcb9LGyU/UTRlcgbQSSI/AAAAAAAABBk/r1gziB-cpc4/s1600-h/image%25255B22%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh5.ggpht.com/-MSJnCKBVMYE/UTRldNnwSfI/AAAAAAAABBs/u35EDhVpj8c/image_thumb%25255B11%25255D.png?imgmax=800" width="495" height="342"&gt;&lt;/a&gt;  &lt;li&gt;Now you can log out and log in using the new user account. You’ll have to change your password when you log in for the first time:&lt;br clear="all"&gt;&lt;a href="http://lh6.ggpht.com/-U7jfzGpQ_nY/UTRlddS8rnI/AAAAAAAABB0/_KOkoWzuekg/s1600-h/image%25255B26%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh5.ggpht.com/-9Qf-_Cqi97Y/UTRld7gRXoI/AAAAAAAABB8/5L3If_3e7CA/image_thumb%25255B13%25255D.png?imgmax=800" width="226" height="339"&gt;&lt;/a&gt;  &lt;li&gt;Note because now you are logged in as a &lt;strong&gt;User, &lt;/strong&gt;you can’t manage your Windows Azure AD tenant using this account. When you click on &lt;strong&gt;ACTIVE DIRECTORY&lt;/strong&gt; in the left pane, you only see your ACS namespaces but not tenant objects.  &lt;li&gt;Now, log back in as an administrator. Go back to &lt;strong&gt;ACTIVE DIRECTORY&lt;/strong&gt;, open your AD tenant, and click on the user name to bring up his profile. Here you can promote the user to administrator (&lt;font color="#ff0000"&gt;1&lt;/font&gt;), or block user from accessing the portal (&lt;font color="#ff0000"&gt;2&lt;/font&gt;), or rest user’s password (&lt;font color="#ff0000"&gt;3&lt;/font&gt;).&lt;br clear="all"&gt;&lt;a href="http://lh5.ggpht.com/-ukj-YJFCjFY/UTRleVkXZpI/AAAAAAAABCE/bRDz47OLmn0/s1600-h/image%25255B31%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh3.ggpht.com/-s8IztVsOUrs/UTRle16L1uI/AAAAAAAABCM/iGTCpyjs-44/image_thumb%25255B16%25255D.png?imgmax=800" width="563" height="364"&gt;&lt;/a&gt;  &lt;li&gt;Just for fun, let’s block the account, save changes, and log out. Then, when you try to log in using the account, your access is denied:&lt;br clear="all"&gt;&lt;a href="http://lh3.ggpht.com/-cpsL1rru_MU/UTRlfNfyuMI/AAAAAAAABCU/unANkL3GNgk/s1600-h/image%25255B35%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh3.ggpht.com/-7DWY_OmmsD4/UTRlfivIzOI/AAAAAAAABCc/8zMc4lvX-0M/image_thumb%25255B18%25255D.png?imgmax=800" width="358" height="184"&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt; &lt;h1&gt;&lt;/h1&gt; &lt;h1&gt;2-Factored Authentication – the &lt;font style="font-weight: bold"&gt;#&lt;/font&gt; key is your friend!&lt;/h1&gt; &lt;p&gt;Many of our customers have requested the ability of enabling 2-factored authentication when users try to access the management portal. Now this has been enabled and the configuration is really easy.&amp;nbsp; &lt;/p&gt; &lt;ol&gt; &lt;li&gt;The 2-factored authentication only applies to &lt;strong&gt;Global Administrators&lt;/strong&gt;. So first let’s promote the user we just created to administrator. The following screenshot shows that I’ve changed user role to &lt;strong&gt;Global Administrator&lt;/strong&gt; (&lt;font color="#ff0000"&gt;1&lt;/font&gt;), entered an alternative email address as requested (&lt;font color="#ff0000"&gt;2&lt;/font&gt;), checked &lt;strong&gt;Require Multi-factor Authentication&lt;/strong&gt; (&lt;font color="#ff0000"&gt;3&lt;/font&gt;),&amp;nbsp; and I’ve also kindly unblocked user from logging in (&lt;font color="#ff0000"&gt;4&lt;/font&gt;). Once all these are done, click &lt;strong&gt;SAVE&lt;/strong&gt; (&lt;font color="#ff0000"&gt;5&lt;/font&gt;)to save the changes.&lt;br clear="all"&gt;&lt;a href="http://lh4.ggpht.com/-riqBPFxc-Mg/UTRlf4dk4hI/AAAAAAAABCk/E_MGoJag5w8/s1600-h/image%25255B39%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh5.ggpht.com/-DS_WcYtSmvc/UTRlgelLi2I/AAAAAAAABCs/qkkS6s31Bj4/image_thumb%25255B20%25255D.png?imgmax=800" width="511" height="405"&gt;&lt;/a&gt;  &lt;li&gt;Log out and try to log in using the account. You’ll see something different this time, telling you the user has not configured for multi-factor authentication yet. Click on &lt;strong&gt;Set it up now&lt;/strong&gt; to continue.&lt;br clear="all"&gt;&lt;a href="http://lh5.ggpht.com/-5ZzmFKWYSLw/UTUDUkBlLdI/AAAAAAAABC8/8udz96bAmaw/s1600-h/image43.png"&gt;&lt;img title="image" 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="image" src="http://lh3.ggpht.com/-9WGQSLUTzwk/UTUDVMKFBNI/AAAAAAAABDE/v0pnQWh-dqo/image_thumb22.png?imgmax=800" width="281" height="181"&gt;&lt;/a&gt;  &lt;li&gt;You’ll see the page where you are asked to enter a mobile phone number. Enter your phone number (make sure your phone is accessible to you) and click on &lt;strong&gt;Save&lt;/strong&gt;.&lt;br clear="all"&gt;&lt;br clear="all"&gt;&lt;a href="http://lh6.ggpht.com/-EO8L8_tV0y0/UTUDVnauR0I/AAAAAAAABDM/ADIodNvE7Lc/s1600-h/image47.png"&gt;&lt;img title="image" 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="image" src="http://lh5.ggpht.com/-f8E-p8r72Bo/UTUDV5MsvkI/AAAAAAAABDU/uM57soOijaM/image_thumb24.png?imgmax=800" width="522" height="308"&gt;&lt;/a&gt;  &lt;li&gt;A computer will call you and ask you to press &lt;strong&gt;#&lt;/strong&gt; key on your phone. Press the &lt;strong&gt;#&lt;/strong&gt; key to finish verification. Once verification successes, click &lt;strong&gt;Close&lt;/strong&gt; button to complete this step:&lt;br clear="all"&gt;&lt;a href="http://lh4.ggpht.com/-1ltj-N-_NoQ/UTUDWfOVXEI/AAAAAAAABDc/FnTYMzBJYO0/s1600-h/image51.png"&gt;&lt;img title="image" 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="image" src="http://lh3.ggpht.com/-TSfvhJ88RuM/UTUDW3tKgiI/AAAAAAAABDk/TNlX-m_sMlI/image_thumb26.png?imgmax=800" width="423" height="138"&gt;&lt;/a&gt;  &lt;li&gt;Now the log in process continues. A computer will call you again to ask you to press &lt;strong&gt;#&lt;/strong&gt; key. Answering the call and pressing the &lt;strong&gt;#&lt;/strong&gt; key allow you to log in to the management portal. From now on, whenever you try to log in using this user account, you’ll need to answer the phone and press the &lt;strong&gt;#&lt;/strong&gt; key as the second factor authentication before you are granted access to the portal. That’s pretty cool, isn’t it?&lt;/li&gt;&lt;/ol&gt; &lt;h1&gt;A code sample &lt;/h1&gt; &lt;p&gt;At last, let’s have a simple code sample to leverage the multi-factor authentication in your own web applications. It’s amazingly easy:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;If you haven’t done so, download and install &lt;a href="http://go.microsoft.com/fwlink/?LinkID=282306"&gt;Microsoft ASP.NET Tools for Windows Azure Active Directory – Visual Studio 2012&lt;/a&gt; (preview). Note, before installing ASP.NET Tools for Windows Azure AD you need to install &lt;a href="http://go.microsoft.com/fwlink/?LinkId=282650"&gt;ASP.NET and Web Tools 2012.2 Update&lt;/a&gt; first. For more details please read &lt;a href="http://blogs.msdn.com/b/vbertocci/archive/2013/02/18/microsoft-asp-net-tools-for-windows-azure-active-directory-visual-studio-2012.aspx"&gt;here&lt;/a&gt;.  &lt;li&gt;Launch Visual Studio, create a new ASP.NET MVC 4 Internet application.  &lt;li&gt;Click on &lt;strong&gt;PROJECT&lt;/strong&gt; –&amp;gt; &lt;strong&gt;Enable Windows Azure Authentication …&lt;/strong&gt; menu.  &lt;li&gt;You’ll be asked to enter your Windows Azure AD tenant. Enter your Windows Azure AD domain, and click &lt;strong&gt;Enable&lt;/strong&gt;:&lt;br clear="all"&gt;&lt;a href="http://lh4.ggpht.com/-qJnaEAojPpg/UTUDXYGNCoI/AAAAAAAABDs/whSoG5PaZ_w/s1600-h/image%25255B4%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh5.ggpht.com/-luU-U7o8Frk/UTUDXlRNJJI/AAAAAAAABD0/FLB5pXjhT4k/image_thumb%25255B1%25255D.png?imgmax=800" width="413" height="152"&gt;&lt;/a&gt;  &lt;li&gt;A log in window shows up. Log in as an administrator of your tenant.  &lt;li&gt;And it’s done! Click &lt;strong&gt;Close&lt;/strong&gt; to close the dialog box.&lt;br clear="all"&gt;&lt;a href="http://lh4.ggpht.com/-6G1QJgi9EQA/UTUDYM46eVI/AAAAAAAABD8/9aUfPkKrbbQ/s1600-h/image%25255B15%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh3.ggpht.com/-wyE5dV3jbDQ/UTUDYf4IZPI/AAAAAAAABEE/fvR-It9URQA/image_thumb%25255B8%25255D.png?imgmax=800" width="411" height="174"&gt;&lt;/a&gt;  &lt;li&gt;Press &lt;strong&gt;F5&lt;/strong&gt; to launch application.  &lt;li&gt;Log in using a user that you’ve already configured multi-factor authentication. You’ll get the same 2-factored authentication experience using the combination of your credential and mobile phone.&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;Hope this helps. Enjoy!&lt;/p&gt;  &lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/Kml4PTaJwBg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/7760850784697517456/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2013/03/a-tour-of-windows-azure-active.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/7760850784697517456?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/7760850784697517456?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/Kml4PTaJwBg/a-tour-of-windows-azure-active.html" title="A Tour of Windows Azure Active Directory Features in Windows Azure Management Portal – Logging in and Enabling Multi-factor Authentication" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/-Yt5n4G5LgvA/UTRlV9PZXYI/AAAAAAAAA_s/B6hafgX52F0/s72-c/image_thumb1.png?imgmax=800" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2013/03/a-tour-of-windows-azure-active.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUcMQ3czfyp7ImA9WhBREE0.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-6373458371448828312</id><published>2013-02-27T15:18:00.001-08:00</published><updated>2013-02-27T15:18:02.987-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-02-27T15:18:02.987-08:00</app:edited><title>Use GIMP to remove solid background of an image</title><content type="html">&lt;p&gt;Okay, this is not a typical topic I’d write a blog for. But I think this post could be useful to the “accidental graphic designers” like myself to get a very common task done quickly and with high quality – to remove solid background of an image. &lt;/p&gt; &lt;p&gt;When you embedded an image, you usually want to remove image background so that when your website design changes the image will still look perfect. The problem is that very often you get images that are anti-aliased against white background. And when you remove the background using common tools such as color selection tool, there are always some annoying leftover pixels around the image. The image may look fine in front of a light background, but turns ugly when you switch to a darker background:&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-Xoi_CgLlZIA/US6UHVQ-0wI/AAAAAAAAA-E/-621cWfb-08/s1600-h/image%25255B32%25255D.png"&gt;&lt;img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://lh3.ggpht.com/-oNHyA9ieDak/US6UH8MFDdI/AAAAAAAAA-M/IcQoGOHVFOg/image_thumb%25255B14%25255D.png?imgmax=800" width="352" height="271"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Here I’m going to introduce a simple method using &lt;a href="http://www.gimp.org/"&gt;GIMP&lt;/a&gt;. Unlike other methods you can find on Internet, this method doesn’t need you to do any fine-tuned selection or editing. Within a couple of steps you’ll get an image that is perfected anti-aliased against alpha channel.&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Open the picture you want to work on in &lt;strong&gt;GIMP&lt;/strong&gt;.&lt;/li&gt; &lt;li&gt;In &lt;strong&gt;Layers&lt;/strong&gt; window, right-click the layer and select &lt;strong&gt;Add Alpha Channel&lt;/strong&gt;.&lt;/li&gt; &lt;li&gt;Duplicate the layer.&lt;/li&gt; &lt;li&gt;Hide the lower layer, then select the top layer.&lt;/li&gt; &lt;li&gt;Use color selection tool to select background:&lt;br clear="all"&gt;&lt;a href="http://lh6.ggpht.com/-Zj2vkKK-muU/US6UIRhONxI/AAAAAAAAA-U/wiITopSOFgk/s1600-h/image%25255B7%25255D.png"&gt;&lt;img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://lh4.ggpht.com/-8TE72JBO13U/US6UI1Iqi9I/AAAAAAAAA-Y/3WMtofeoRcw/image_thumb%25255B3%25255D.png?imgmax=800" width="355" height="220"&gt;&lt;/a&gt;&lt;/li&gt; &lt;li&gt;Use &lt;strong&gt;Select&lt;/strong&gt;-&amp;gt;&lt;strong&gt;Grow&lt;/strong&gt; menu to grow the selection by 1-2 pixels.&lt;/li&gt; &lt;li&gt;Press &lt;strong&gt;Delete&lt;/strong&gt; key to delete the background. This will remove some image borders. Don’t worry, we’ll recover them later.&lt;/li&gt; &lt;li&gt;Now hide the top layer, show and select the bottom layer.&lt;/li&gt; &lt;li&gt;Press &lt;strong&gt;Ctrl+Shit+A&lt;/strong&gt; to unselect everything.&lt;/li&gt; &lt;li&gt;With bottom layer selected, select &lt;strong&gt;Colors&lt;/strong&gt; –&amp;gt; &lt;strong&gt;Color to Alpha…&lt;/strong&gt; menu.&lt;/li&gt; &lt;li&gt;Select the color you want to change to alpha (in this case white), and click OK to apply the filter:&lt;br clear="all"&gt;&lt;a href="http://lh6.ggpht.com/-mocWWprrqnk/US6UJIO3qDI/AAAAAAAAA-g/DTiJwCxjIkk/s1600-h/image%25255B11%25255D.png"&gt;&lt;img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://lh5.ggpht.com/-lC7JRSnsgwk/US6UJXp56TI/AAAAAAAAA-o/JpTVSSaD2Pc/image_thumb%25255B5%25255D.png?imgmax=800" width="214" height="281"&gt;&lt;/a&gt;&lt;/li&gt; &lt;li&gt;The above step removes all white color from the image. All you need to do is to turn on the top layer again. Then you get a perfect picture!&lt;/li&gt; &lt;li&gt;Optionally, use &lt;strong&gt;Image&lt;/strong&gt; –&amp;gt; &lt;strong&gt;Autocrop&lt;/strong&gt; image to crop the image. &lt;/li&gt; &lt;li&gt;Export to a png file.&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-SrESlGA3rHE/US6UJ2wSaKI/AAAAAAAAA-w/Pyd2WHOc7ZA/s1600-h/image%25255B46%25255D.png"&gt;&lt;img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://lh4.ggpht.com/-U67Rm5WdlpU/US6UKXXQshI/AAAAAAAAA-4/bVjLs_nmZd0/image_thumb%25255B20%25255D.png?imgmax=800" width="365" height="281"&gt;&lt;/a&gt;&lt;/p&gt;       &lt;p&gt;That’s it! Hope this helps!&lt;/p&gt;  &lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/UQ4181Im-no" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/6373458371448828312/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2013/02/use-gimp-to-remove-solid-background-of.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/6373458371448828312?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/6373458371448828312?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/UQ4181Im-no/use-gimp-to-remove-solid-background-of.html" title="Use GIMP to remove solid background of an image" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/-oNHyA9ieDak/US6UH8MFDdI/AAAAAAAAA-M/IcQoGOHVFOg/s72-c/image_thumb%25255B14%25255D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2013/02/use-gimp-to-remove-solid-background-of.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkcEQXoycSp7ImA9WhBSGUQ.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-6113521462529460035</id><published>2013-02-27T12:46:00.001-08:00</published><updated>2013-02-27T12:46:40.499-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-02-27T12:46:40.499-08:00</app:edited><title>A Love Story: Devices and Cloud – Perfect Together</title><content type="html">&lt;p&gt;My new article has just been published on Cloud Computing Journal:&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;a href="http://dotnet.sys-con.com/node/2558051"&gt;A Love Story: Devices and Cloud – Perfect Together&lt;/a&gt;&lt;br&gt;&lt;/p&gt; &lt;p&gt;We’ve heard about Google Glasses. And we’ve heard about Apple iWatch. And yes, we’ve heard about people embedding cellphones into shoes [1]. Once again, the term “wearable computing” is becoming a hot topic in news and literatures. Some have even announced that the age of wearable technology is here [2]. The world is surely changing fast. Aren’t we still debating who makes the best smartphones and the best tablets? What’s going on here? &lt;br&gt;The foreseeable booming of wearable computing is just another chapter of the unstoppable fusion process between cyber space and reality. Eventually, machine computing will become ubiquitous, and the boundary between human bodies and devices will fade away. This is a vision shared by many scientists, innovators, entrepreneurs and Hollywood writers. It’s becoming a reality faster than we might have expected. Devices will no longer be just peripheral augmentations, but be inextricably intertwined with human lives.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Hope this would be an interesting read for you!&lt;/p&gt;  &lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/-RXVQ6AJSoo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/6113521462529460035/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2013/02/a-love-story-devices-and-cloud-perfect.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/6113521462529460035?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/6113521462529460035?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/-RXVQ6AJSoo/a-love-story-devices-and-cloud-perfect.html" title="A Love Story: Devices and Cloud – Perfect Together" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2013/02/a-love-story-devices-and-cloud-perfect.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEAMQXY4fyp7ImA9WhBSFU0.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-8633158084058377437</id><published>2013-02-21T19:00:00.001-08:00</published><updated>2013-02-21T19:13:00.837-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-02-21T19:13:00.837-08:00</app:edited><title>Learn Windows Azure Cloud Services from Beginning: a Mini Online Course</title><content type="html">&lt;p&gt;I just finished publishing 7 episodes of a new video series, &lt;a href="http://channel9.msdn.com/Series/Windows-Azure-Cloud-Services-Tutorials"&gt;Windows Azure Cloud Services&lt;/a&gt;.&amp;nbsp; This series is a mini online course that teaches you Windows Azure Cloud Services from beginning. We'll start our cloud journey by setting up development environment, and then continue to explore some fundamental concepts of Windows Azure Cloud Services. The series builds a solid foundation for you to create highly-available, scalable applications and services using Windows Azure's rich PaaS environment, and to deliver great SaaS solutions to customers anywhere around the world. &lt;/p&gt; &lt;p&gt;There are still more episodes to come, but the first 7 episodes cover all the basic concepts, tools, and procedures you need to know to get started. Here’s the list of episodes:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://channel9.msdn.com/Series/Windows-Azure-Cloud-Services-Tutorials/Introduction-to-Windows-Azure-Cloud-Services"&gt;Episode 1: Introduction to Windows Azure Cloud Services&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://channel9.msdn.com/Series/Windows-Azure-Cloud-Services-Tutorials/Windows-Azure-Cloud-Services-Concepts-Part-1"&gt;Episode 2: Windows Azure Cloud Services Concepts (Part 1)&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://channel9.msdn.com/Series/Windows-Azure-Cloud-Services-Tutorials/Walkthrough-of-the-Management-Portal-for-Windows-Azure-Cloud-Services"&gt;Episode 3: Walkthrough of the Management Portal for Windows Azure Cloud Services&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://channel9.msdn.com/Series/Windows-Azure-Cloud-Services-Tutorials/Windows-Azure-Cloud-Services-Concepts-Part-2"&gt;Episode 4: Windows Azure Cloud Services Concepts (Part 2)&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://channel9.msdn.com/Series/Windows-Azure-Cloud-Services-Tutorials/Introduction-to-Windows-Azure-Worker-Roles-Part-1"&gt;Episode 5: Introduction to Windows Azure Worker Roles (Part 1)&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://channel9.msdn.com/Series/Windows-Azure-Cloud-Services-Tutorials/Introduction-to-Windows-Azure-Worker-Roles-Part-2"&gt;Episode 6: Introduction to Windows Azure Worker Roles (Part 2)&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://channel9.msdn.com/Series/Windows-Azure-Cloud-Services-Tutorials/Windows-Azure-Cloud-Services-Role-Lifecycle"&gt;Episode 7: Windows Azure Cloud Services Role Lifecycle&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Hope you enjoy the series. If you have any feedbacks, please leave comments on the posts, or send me a message to &lt;a href="https://twitter.com/haishibai2010"&gt;@HaishiBai2010&lt;/a&gt;.&lt;/p&gt;  &lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/mlDaJKceJh8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/8633158084058377437/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2013/02/a-mini-windows-azure-cloud-service.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/8633158084058377437?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/8633158084058377437?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/mlDaJKceJh8/a-mini-windows-azure-cloud-service.html" title="Learn Windows Azure Cloud Services from Beginning: a Mini Online Course" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2013/02/a-mini-windows-azure-cloud-service.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0UGSHw9eip7ImA9WhBSE00.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-3965689484242456749</id><published>2013-02-16T13:50:00.001-08:00</published><updated>2013-02-19T11:13:49.262-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-02-19T11:13:49.262-08:00</app:edited><title>Windows Azure Active Directory (current) resource list</title><content type="html">&lt;p&gt;This post is a survey of &lt;u&gt;currently&lt;/u&gt; available Windows Azure Active Directory resources. I’ve listed links to various concepts, tools, and scenarios. Many of the links, unsurprisingly, point to &lt;a href="http://blogs.msdn.com/b/vbertocci/archive/2013/02/13/the-name-claim-sometimes-it-s-the-simple-things.aspx"&gt;Vittorio's blog&lt;/a&gt;. I hope this post can provide a little help for you to sort out WA AD resources. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;WA AD is under active development and things will probably change. I intend to keep this post refreshed once a while, with preview features clearly marked. If you’ve spot a mistake or out-of-date info, or have anything you want to add to this list, please let me know!&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;font color="#4bacc6"&gt;Last updated: February 19, 2013&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt; &lt;h2&gt;Concepts &lt;/h2&gt; &lt;ul&gt; &lt;li&gt;Introduction&lt;br clear="all"&gt;&lt;a title="http://www.windowsazure.com/en-us/home/features/identity/" href="http://www.windowsazure.com/en-us/home/features/identity/"&gt;http://www.windowsazure.com/en-us/home/features/identity/&lt;/a&gt;  &lt;li&gt;MSDN&lt;br clear="all"&gt;&lt;a title="http://msdn.microsoft.com/en-us/library/windowsazure/jj673460.aspx" href="http://msdn.microsoft.com/en-us/library/windowsazure/jj673460.aspx"&gt;http://msdn.microsoft.com/en-us/library/windowsazure/jj673460.aspx&lt;/a&gt;  &lt;li&gt;Windows Azure Active Directory is not a FP. If anything, it is an IP; or rather, it defines an IPs space.&lt;br clear="all"&gt;&lt;a title="http://blogs.msdn.com/b/vbertocci/archive/2013/02/08/multitenant-sts-and-token-validation.aspx" href="http://blogs.msdn.com/b/vbertocci/archive/2013/02/08/multitenant-sts-and-token-validation.aspx"&gt;http://blogs.msdn.com/b/vbertocci/archive/2013/02/08/multitenant-sts-and-token-validation.aspx&lt;/a&gt;  &lt;ul&gt; &lt;li&gt;Tokens from Windows Azure AD are all signed with the same certificate for every tenant&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt; &lt;h2&gt;Tooling for Common Tasks&lt;/h2&gt; &lt;h3&gt;&lt;/h3&gt; &lt;h3&gt;To provision a new Windows Azure Active Directory Tenant&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;If you are an Office365 customer, you already have one.  &lt;li&gt;Use &lt;a href="http://g.microsoftonline.com/0AX00en/5"&gt;this link&lt;/a&gt; to set up one tenant for free as part of our developer preview program.&lt;strong&gt;&lt;em&gt;&lt;font color="#ff0000"&gt; [PREVIEW!]&lt;/font&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;To manage a Windows Azure Active Directory Tenant&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="https://activedirectory.windowsazure.com/"&gt;https://activedirectory.windowsazure.com/&lt;/a&gt;&amp;nbsp;&lt;strong&gt;&lt;em&gt;&lt;font color="#ff0000"&gt;[PREVIEW!]&lt;/font&gt;&lt;/em&gt;&lt;/strong&gt; &lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;To provision a service principal&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://onlinehelp.microsoft.com/en-us/office365-enterprises/hh124998.aspx"&gt;Office265 cmdlets&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;&lt;/h3&gt; &lt;h3&gt;To validate token by signer and issuer pair&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="https://nuget.org/packages/System.IdentityModel.Tokens.ValidatingIssuerNameRegistry/4.5.0"&gt;NuGet: System.IdentityModel.Tokens.ValidatingIssuerNameRegistry&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;To configure applications that use WIF&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://blogs.msdn.com/b/vbertocci/archive/2012/10/23/windows-identity-foundation-tools-for-visual-studio-2012-rtm.aspx"&gt;Identity and Access Tools&lt;/a&gt;&amp;nbsp; (For Visual Studio 2012)&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;To query Windows Azure Active Directory&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/windowsazure/hh974476.aspx"&gt;Windows Azure Active Directory Graph&lt;/a&gt;  &lt;li&gt;Use AAL (&lt;a href="https://nuget.org/packages/Microsoft.WindowsAzure.ActiveDirectory.Authentication/"&gt;beta NuGet&lt;/a&gt;) to obtain a token for calling the Graph API. &lt;strong&gt;&lt;em&gt;&lt;font color="#ff0000"&gt;[Beta!]&lt;/font&gt;&lt;/em&gt;&lt;/strong&gt;&lt;br clear="all"&gt;&lt;a title="http://blogs.msdn.com/b/vbertocci/archive/2013/01/22/group-amp-role-claims-use-the-graph-api-to-get-back-isinrole-and-authorize-in-windows-azure-ad-apps.aspx" href="http://blogs.msdn.com/b/vbertocci/archive/2013/01/22/group-amp-role-claims-use-the-graph-api-to-get-back-isinrole-and-authorize-in-windows-azure-ad-apps.aspx"&gt;http://blogs.msdn.com/b/vbertocci/archive/2013/01/22/group-amp-role-claims-use-the-graph-api-to-get-back-isinrole-and-authorize-in-windows-azure-ad-apps.aspx&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;To handle JWT token&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="https://nuget.org/packages/Microsoft.IdentityModel.Tokens.JWT"&gt;NuGet: Microsoft.IdentityModel.Tokens.JWT&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;To configure a web application to use Windows Azure AD&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://go.microsoft.com/fwlink/?LinkID=282306"&gt;Microsoft ASP.NET Tool for Windows Azure Active Directory - Visual Studio 2012&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;h2&gt;Scenarios&lt;/h2&gt; &lt;h3&gt;How to provision a Windows Azure Active Directory Tenant as an Identity Provider in an ACS Namespace&lt;/h3&gt; &lt;p&gt;&lt;a href="http://blogs.msdn.com/b/vbertocci/archive/2012/11/07/provisioning-a-directory-tenant-as-an-identity-provider-in-an-acs-namespace.aspx"&gt;http://blogs.msdn.com/b/vbertocci/archive/2012/11/07/provisioning-a-directory-tenant-as-an-identity-provider-in-an-acs-namespace.aspx&lt;/a&gt;&lt;/p&gt; &lt;h3&gt;Integrating Multi-Tenant Cloud Applications with Windows Azure Active Directory&lt;/h3&gt; &lt;p&gt;&lt;a title="http://www.windowsazure.com/en-us/develop/net/tutorials/multitenant-apps-for-active-directory/" href="http://www.windowsazure.com/en-us/develop/net/tutorials/multitenant-apps-for-active-directory/"&gt;http://www.windowsazure.com/en-us/develop/net/tutorials/multitenant-apps-for-active-directory/&lt;/a&gt;&amp;nbsp;&lt;strong&gt;&lt;em&gt;&lt;font color="#ff0000"&gt;[Preview]&lt;/font&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt; &lt;h3&gt;To use Windows Azure Active Directory as a trusted IP of a Windows Azure Web Site&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;Use &lt;a href="http://www.asp.net/vnext/overview/fall-2012-update/windows-azure-authentication"&gt;Windows Azure Authentication&lt;/a&gt;.  &lt;li&gt;Use &lt;a href="http://blogs.msdn.com/b/vbertocci/archive/2012/10/23/windows-identity-foundation-tools-for-visual-studio-2012-rtm.aspx"&gt;Identity and Access Tools&lt;/a&gt; to configure RP. Beware of cookie protection method constrains:&lt;br clear="all"&gt;&lt;a href="http://blogs.msdn.com/b/vbertocci/archive/2013/01/28/running-wif-based-apps-in-windows-azure-web-sites.aspx"&gt;http://blogs.msdn.com/b/vbertocci/archive/2013/01/28/running-wif-based-apps-in-windows-azure-web-sites.aspx&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;To use Windows Azure Active Directory as a trusted IP of a Windows Azure Cloud Service&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;Use &lt;a href="http://blogs.msdn.com/b/vbertocci/archive/2012/10/23/windows-identity-foundation-tools-for-visual-studio-2012-rtm.aspx"&gt;Identity and Access Tools&lt;/a&gt; to configure RP. Create service principal on Windows Azure Active Directory tenant.&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;How to get role and group membership claims for users signing in via Windows Azure Active Directory&lt;/h3&gt; &lt;p&gt;&lt;a title="http://blogs.msdn.com/b/vbertocci/archive/2013/01/22/group-amp-role-claims-use-the-graph-api-to-get-back-isinrole-and-authorize-in-windows-azure-ad-apps.aspx" href="http://blogs.msdn.com/b/vbertocci/archive/2013/01/22/group-amp-role-claims-use-the-graph-api-to-get-back-isinrole-and-authorize-in-windows-azure-ad-apps.aspx"&gt;http://blogs.msdn.com/b/vbertocci/archive/2013/01/22/group-amp-role-claims-use-the-graph-api-to-get-back-isinrole-and-authorize-in-windows-azure-ad-apps.aspx&lt;/a&gt;&lt;/p&gt; &lt;h3&gt;Delegation without ActAs token&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;Both frontend and backend belongs to the same owner/realm.  &lt;li&gt;Bearer tokens are allowed.  &lt;li&gt;The risk of token being stolen across layers is understood and managed. &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;a title="http://blogs.msdn.com/b/vbertocci/archive/2013/01/09/using-the-jwt-handler-for-implementing-poor-man-s-delegation-actas.aspx" href="http://blogs.msdn.com/b/vbertocci/archive/2013/01/09/using-the-jwt-handler-for-implementing-poor-man-s-delegation-actas.aspx"&gt;http://blogs.msdn.com/b/vbertocci/archive/2013/01/09/using-the-jwt-handler-for-implementing-poor-man-s-delegation-actas.aspx&lt;/a&gt;&lt;/p&gt; &lt;h3&gt;Windows Store app accessing Web PI&lt;/h3&gt; &lt;p&gt;&lt;a title="http://blogs.msdn.com/b/vbertocci/archive/2013/02/18/use-the-jwt-handler-to-write-a-authorization-server-in-3-lines-of-code-see-it-in-action-with-a-windows-store-app-client-amp-web-api-pr.aspx" href="http://blogs.msdn.com/b/vbertocci/archive/2013/02/18/use-the-jwt-handler-to-write-a-authorization-server-in-3-lines-of-code-see-it-in-action-with-a-windows-store-app-client-amp-web-api-pr.aspx"&gt;http://blogs.msdn.com/b/vbertocci/archive/2013/02/18/use-the-jwt-handler-to-write-a-authorization-server-in-3-lines-of-code-see-it-in-action-with-a-windows-store-app-client-amp-web-api-pr.aspx&lt;/a&gt;&lt;/p&gt; &lt;h3&gt;&lt;/h3&gt; &lt;h2&gt;Claims issued by a Windows Azure Active Directory Tenant&lt;/h2&gt; &lt;p&gt;This is not a complete list. It contains only claims that are known to be provided&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"&gt;http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name&lt;/a&gt;&amp;nbsp;&amp;nbsp; (UPN of the user – &lt;a href="mailto:&amp;ldquo;user@domain"&gt;“user@domain&lt;/a&gt;”, see &lt;a href="http://blogs.msdn.com/b/vbertocci/archive/2013/02/13/the-name-claim-sometimes-it-s-the-simple-things.aspx"&gt;Vittorio's blog&lt;/a&gt;)  &lt;li&gt;&lt;strong&gt;&lt;a href="http://schemas.xmlsoap.org/claims/FirstName"&gt;http://schemas.xmlsoap.org/claims/FirstName&lt;/a&gt;&lt;/strong&gt; &lt;/li&gt;&lt;/ul&gt; &lt;h2&gt;Common URLs&lt;/h2&gt; &lt;ul&gt; &lt;li&gt;Active Directory tenant federation metadata&lt;br clear="all"&gt;https://accounts.accescontrol.windows.net/[tenant&amp;nbsp; (???.onmicrosoft.com)]/FederationMetadata/2007-06/FederationMetadata.xml  &lt;li&gt;ws-Federation endpoint&lt;br clear="all"&gt;&lt;a href="https://accounts.accesscontrol.windows.net/[tenant"&gt;https://accounts.accesscontrol.windows.net/[tenant&lt;/a&gt; id]/v2/wsfederation (you can get tenant id from the metadata above - entityID)&lt;/li&gt;&lt;/ul&gt;  &lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/W60qT1xwqL8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/3965689484242456749/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2013/02/windows-azure-active-directory-current.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/3965689484242456749?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/3965689484242456749?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/W60qT1xwqL8/windows-azure-active-directory-current.html" title="Windows Azure Active Directory (current) resource list" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2013/02/windows-azure-active-directory-current.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUcGRHw-fip7ImA9WhBTEE8.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-2763494225051679391</id><published>2013-02-04T16:10:00.001-08:00</published><updated>2013-02-04T16:10:25.256-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-02-04T16:10:25.256-08:00</app:edited><title>New features in Service Bus Preview Library (January 2013) – Epilogue: Message Browse</title><content type="html">&lt;p&gt;&lt;em&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;[This post series is based on preview features that are subject to change]&lt;/font&gt;&lt;/strong&gt;&lt;/em&gt;  &lt;p&gt;This is an epilogue of my 3-part blog series on the recently released &lt;a href="http://nuget.org/packages/ServiceBus.Preview"&gt;Service Bus preview features&lt;/a&gt;.&amp;nbsp; &lt;p&gt;&lt;a href="http://haishibai.blogspot.com/2013/01/new-features-in-service-bus-preview.html"&gt;part 1: Message Pump&lt;/a&gt;  &lt;p&gt;&lt;a href="http://haishibai.blogspot.com/2013/01/new-features-in-service-bus-preview_27.html"&gt;part 2: Auto-expiration&lt;/a&gt;  &lt;p&gt;&lt;a href="http://haishibai.blogspot.com/2013/01/new-features-in-service-bus-preview_29.html"&gt;part 3: Shared Access Authorization&lt;/a&gt;  &lt;h3&gt;&lt;/h3&gt; &lt;h2&gt;Why an epilogue?&lt;/h2&gt; &lt;p&gt;I’ve missed another feature in the preview library – message browse, which allows you to iterate through the messages without blocking any receivers. But, before I get to that, I have to clarify one thing regarding what I said in the &lt;a href="http://haishibai.blogspot.com/2013/01/new-features-in-service-bus-preview.html"&gt;Message Pump post&lt;/a&gt;. When you call &lt;strong&gt;&lt;em&gt;Client.Receive()&lt;/em&gt;&lt;/strong&gt; method, you can specify a timeout of any duration to wait for a message to arrive. This is not a long-polling, but it does allow you to specify a timeout period before the method returns. So, the price comparison in the original post isn’t that relevant after all. However, the gist of that post is never about price reduction, but about how Message Pump enables&amp;nbsp; event-driven programming model, which is really natural to client applications, especially rich clients. With that said, let’s move on to the main topic: Message Browse.&lt;/p&gt; &lt;h2&gt;Message Browse&lt;/h2&gt; &lt;p&gt;Message browse can be useful in scenarios where you need to provide monitoring or tracing capabilities without affecting existing clients. For example, you can examine top 10 messages from dead-lettered queue. Or, you can provide live monitoring of pending jobs (such as if a job related to a specific customer has appeared on the queue). Here I’ll just present a very simple Console application as an example: &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Main(&lt;span class="kwrd"&gt;string&lt;/span&gt;[] args)
{
    var conString = &lt;span class="str"&gt;"[SB Connection String]"&lt;/span&gt;;
    var queueName = &lt;span class="str"&gt;"workqueue"&lt;/span&gt;;
    QueueClient sender = QueueClient.CreateFromConnectionString(conString, queueName);
    &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; i = 0; i &amp;lt; 10; i++)
        sender.Send(&lt;span class="kwrd"&gt;new&lt;/span&gt; BrokeredMessage(&lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(&lt;span class="str"&gt;"Message {0}"&lt;/span&gt;, i+1)));
    QueueClient receiver = QueueClient.CreateFromConnectionString(conString, queueName, 
        ReceiveMode.ReceiveAndDelete);

    BrokeredMessage message = &lt;span class="kwrd"&gt;null&lt;/span&gt;;
    &lt;span class="kwrd"&gt;do&lt;/span&gt;
    {
        &lt;font style="background-color: #ffff00"&gt;message = receiver.Peek();&lt;/font&gt;
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (message != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
            Console.WriteLine(&lt;span class="str"&gt;"Message found: "&lt;/span&gt; + message.GetBody&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;());
    } &lt;span class="kwrd"&gt;while&lt;/span&gt; (message != &lt;span class="kwrd"&gt;null&lt;/span&gt;);

    Console.ReadLine();

    message = &lt;span class="kwrd"&gt;null&lt;/span&gt;;

    &lt;span class="kwrd"&gt;do&lt;/span&gt;
    {
        &lt;font style="background-color: #00ff00"&gt;message = receiver.Receive();&lt;/font&gt;
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (message != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
            Console.WriteLine(&lt;span class="str"&gt;"Message received: "&lt;/span&gt; + message.GetBody&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;());
    } &lt;span class="kwrd"&gt;while&lt;/span&gt; (message != &lt;span class="kwrd"&gt;null&lt;/span&gt;);

    Console.ReadLine();
}&lt;/pre&gt;
&lt;p&gt;The above code sends 10 messages to a queue, browses the messages by using the &lt;strong&gt;&lt;em&gt;Peek()&lt;/em&gt;&lt;/strong&gt; method (highlighted yellow), and then retrieves the messages using the &lt;strong&gt;&lt;em&gt;Receive()&lt;/em&gt;&lt;/strong&gt; method (highlighted green). Because the &lt;strong&gt;&lt;em&gt;Peek()&lt;/em&gt;&lt;/strong&gt; method doesn’t remove any messages from the queue, &lt;strong&gt;&lt;em&gt;Recevie()&lt;/em&gt;&lt;/strong&gt; calls are not affected afterwards and all the messages can be received.&lt;/p&gt;
&lt;h2&gt;Send us your feedbacks!&lt;/h2&gt;
&lt;p&gt;I hope you’ve learned some useful information from this blog series. And I know the production team is eager to hear from you. Are the features useful in your scenarios? What are we missing? Where do we need to improve? The whole idea of the preview library is to get your feedbacks so that we can make the final product better. So, if you have any feedbacks, either positive or negative, please don’t hesitate to send them my way, and I’ll make sure they are heard by the team. You can either leave comments to this blog, or send tweets to &lt;a href="https://twitter.com/HaishiBai2010"&gt;@HaishiBai2010&lt;/a&gt;. Thank you for reading!&lt;/p&gt;&lt;/p&gt;  &lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/lJgMIBlXE6M" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/2763494225051679391/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2013/02/new-features-in-service-bus-preview.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/2763494225051679391?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/2763494225051679391?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/lJgMIBlXE6M/new-features-in-service-bus-preview.html" title="New features in Service Bus Preview Library (January 2013) – Epilogue: Message Browse" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2013/02/new-features-in-service-bus-preview.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEYAR3kyeSp7ImA9WhNaFk0.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-4039560743212293649</id><published>2013-01-29T19:44:00.001-08:00</published><updated>2013-01-30T19:15:46.791-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-30T19:15:46.791-08:00</app:edited><title>New features in Service Bus Preview Library (January 2013) – 3: Queue/Subscription Shared Access Authorization</title><content type="html">&lt;p&gt;This is the last part of my 3-part blog series on the recently released &lt;a href="http://nuget.org/packages/ServiceBus.Preview"&gt;Service Bus preview features&lt;/a&gt;.&amp;nbsp; &lt;p&gt;&lt;em&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;[This post series is based on preview features that are subject to change]&lt;/font&gt;&lt;/strong&gt;&lt;/em&gt;  &lt;p&gt;&lt;a href="http://haishibai.blogspot.com/2013/01/new-features-in-service-bus-preview.html"&gt;part 1: Message Pump&lt;/a&gt;  &lt;p&gt;&lt;a href="http://haishibai.blogspot.com/2013/01/new-features-in-service-bus-preview_27.html"&gt;part 2: Auto-expiration&lt;/a&gt;  &lt;h2&gt;Queue/Subscription Shared Access Authorization&lt;/h2&gt; &lt;p&gt;Service Bus uses Windows Azure AD Access Control (a.k.a. Access Control Service or ACS) for authentication. And it uses claims generated by ACS for authorizations. For each Service Bus namespace, there’s a corresponding ACS namespace of the same name (suffixed with “-sb”). In this ACS namespace, there’s a “owner” server identity, for which ACS issues three &lt;em&gt;&lt;strong&gt;net.windows.servicebus.action&lt;/strong&gt;&lt;/em&gt; claims with values &lt;strong&gt;Manage&lt;/strong&gt;, &lt;strong&gt;Listen&lt;/strong&gt;, and &lt;strong&gt;Send&lt;/strong&gt;. These claims are in turn used by Service Bus to authorize user for different operations. Because “owner” comes with all three claims, he is entitled to perform any operations that are allowed by Service Bus. I wrote a &lt;a href="http://haishibai.blogspot.com/2012/05/window-azure-service-bus-give-read-only.html"&gt;blog article&lt;/a&gt; talking about why it’s a good practice to create additional server identities with minimum access rights - these additional identities can only perform a limited set of operations that are designated to them. &lt;/p&gt; &lt;p&gt;However, there are still two problems: first, by default the security scope of these claims are &lt;u&gt;global to the namespace&lt;/u&gt;. For example, once a user is granted &lt;strong&gt;&lt;em&gt;Listen&lt;/em&gt;&lt;/strong&gt; access, he can listen to any queues and subscriptions. If you want &lt;u&gt;granular access control at entity level&lt;/u&gt;, you’ll need to create additional Relying Parties with entity paths as realms, and a “longest prefix match” policy is applied when authorization is performed (see &lt;a href="http://msdn.microsoft.com/en-us/library/windowsazure/hh403962.aspx"&gt;this doc&lt;/a&gt;). Second, identity management is cumbersome as you have to go through ACS and manage service identities.&amp;nbsp; With Service Bus preview features, you’ll be able to create &lt;u&gt;authorization rules by users or clients&lt;/u&gt;. And because you can apply multiple authorization rules, you can manage end user access rights separately even if they share the same queue or subscription. This design gives you great flexibility in managing access rights. &lt;/p&gt; &lt;p&gt;Now let’s walk through a sample to see how that works. In this scenario I’ll create two queues for three users: Tom, Jack, and an administrator. Tom has send/listen access to the first queue. Jack has send/listen access to the second queue. In addition, he can also receive messages from the first queue. The administrator can manage both queues. Their access rights are summarized in the following table:&lt;/p&gt; &lt;table cellspacing="0" cellpadding="2" width="368" border="1"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="top" width="130"&gt;&lt;strong&gt;User&lt;/strong&gt;&lt;/td&gt; &lt;td valign="top" width="121"&gt;&lt;strong&gt;Queue 1&lt;/strong&gt;&lt;/td&gt; &lt;td valign="top" width="115"&gt;&lt;strong&gt;Queue 2&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="128"&gt;Tom&lt;/td&gt; &lt;td valign="top" width="122"&gt;Listen/Send&lt;/td&gt; &lt;td valign="top" width="116"&gt;No access&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="127"&gt;Jack&lt;/td&gt; &lt;td valign="top" width="122"&gt;Listen only&lt;/td&gt; &lt;td valign="top" width="117"&gt;Listen/Send&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="127"&gt;Admin&lt;/td&gt; &lt;td valign="top" width="122"&gt;Manage&lt;/td&gt; &lt;td valign="top" width="118"&gt;Manage&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;ol&gt; &lt;li&gt;Create a new Windows Console application.  &lt;li&gt;Install the preview NuGet package:&lt;pre class="csharpcode"&gt;install-package &lt;strong&gt;ServiceBus.Preview&lt;/strong&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;li&gt;Implement the &lt;strong&gt;&lt;em&gt;Main()&lt;/em&gt;&lt;/strong&gt; method:&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Main(&lt;span class="kwrd"&gt;string&lt;/span&gt;[] args)
{
  var queuePath1 = &lt;span class="str"&gt;"sasqueue1"&lt;/span&gt;;
  var queuePath2 = &lt;span class="str"&gt;"sasqueue2"&lt;/span&gt;;

  NamespaceManager nm = &lt;span class="kwrd"&gt;new&lt;/span&gt; NamespaceManager(
    ServiceBusEnvironment.CreateServiceUri(&lt;span class="str"&gt;"https"&lt;/span&gt;, &lt;span class="str"&gt;"&lt;em&gt;[Your SB namespace]&lt;/em&gt;"&lt;/span&gt;, &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty),
    TokenProvider.CreateSharedSecretTokenProvider(&lt;span class="str"&gt;"owner"&lt;/span&gt;, &lt;span class="str"&gt;"&lt;em&gt;[Your secret key]&lt;/em&gt;"&lt;/span&gt;));

  QueueDescription desc1 = &lt;span class="kwrd"&gt;new&lt;/span&gt; QueueDescription(queuePath1);
  QueueDescription desc2 = &lt;span class="kwrd"&gt;new&lt;/span&gt; QueueDescription(queuePath2);

  desc1.Authorization.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; SharedAccessAuthorizationRule(&lt;span class="str"&gt;"ForTom"&lt;/span&gt;, &lt;span class="str"&gt;"pass@word1"&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; AccessRights[] { AccessRights.Listen, AccessRights.Send }));
            
  desc2.Authorization.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; SharedAccessAuthorizationRule(&lt;span class="str"&gt;"ForJack"&lt;/span&gt;, &lt;span class="str"&gt;"pass@word2"&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; AccessRights[] { AccessRights.Listen, AccessRights.Send }));
  desc2.Authorization.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; SharedAccessAuthorizationRule(&lt;span class="str"&gt;"ForJack"&lt;/span&gt;, &lt;span class="str"&gt;"pass@word2"&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; AccessRights[] { AccessRights.Listen }));
            
  desc1.Authorization.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; SharedAccessAuthorizationRule(&lt;span class="str"&gt;"ForAdmin"&lt;/span&gt;, &lt;span class="str"&gt;"pass@word3"&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; AccessRights[] { AccessRights.Manage }));
  desc2.Authorization.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; SharedAccessAuthorizationRule(&lt;span class="str"&gt;"ForAdmin"&lt;/span&gt;, &lt;span class="str"&gt;"pass@word3"&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; AccessRights[] { AccessRights.Manage }));

  nm.CreateQueue(desc1);
  nm.CreateQueue(desc2);
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;Okay, that’s not the most exciting code. But it should be fairly easy to understand. For each queue I’m attaching multiple &lt;strong&gt;&lt;em&gt;SharedAccessAuthorizationRule, &lt;/em&gt;&lt;/strong&gt;in which I can specify the shared key, as well as assigned rights associated with the rule. And I have implemented desired security policy with few lines of code. These entity-level keys have several advantages (comparing to the two problems stated above): first, they provide fine-granular user access control. Second, they are easier to manage. And third, when they are compromised,&amp;nbsp; the damage can be constrained within the scope of affected entity or even affected user only.&lt;/p&gt;
&lt;p&gt;This concludes my 3-part blog series on Service Bus preview features. Many thanks to &lt;a href="https://twitter.com/AbhishekRLal"&gt;Abhishek Lal&lt;/a&gt; for help and guidance on the way, and to the friends on Twitter who helped to get the words out. Thank you for reading!&lt;/p&gt;  &lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/tZIjAjjsETE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/4039560743212293649/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2013/01/new-features-in-service-bus-preview_29.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/4039560743212293649?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/4039560743212293649?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/tZIjAjjsETE/new-features-in-service-bus-preview_29.html" title="New features in Service Bus Preview Library (January 2013) – 3: Queue/Subscription Shared Access Authorization" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2013/01/new-features-in-service-bus-preview_29.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUcDSHg6eyp7ImA9WhNaE0Q.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-1952780880609068405</id><published>2013-01-27T00:56:00.001-08:00</published><updated>2013-01-28T10:17:59.613-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-28T10:17:59.613-08:00</app:edited><title>New features in Service Bus Preview Library (January 2013) – 2: Auto-expiration</title><content type="html">&lt;p&gt;This is the second part of my blog series on the recently released &lt;a href="http://nuget.org/packages/ServiceBus.Preview"&gt;Service Bus preview features&lt;/a&gt;.&amp;nbsp; &lt;/p&gt; &lt;p&gt;&lt;font color="#ff0000"&gt;&lt;em&gt;&lt;strong&gt;[This post series is based on preview features that are subject to change]&lt;/strong&gt;&lt;/em&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://haishibai.blogspot.com/2013/01/new-features-in-service-bus-preview.html"&gt;part 1: Message Pump&lt;/a&gt;&lt;/p&gt; &lt;h2&gt;Auto-Expiration&lt;/h2&gt; &lt;p&gt;There’s a new property, &lt;strong&gt;&lt;em&gt;AutoDeleteOnIdle&lt;/em&gt;&lt;/strong&gt;, added to Service Bus entity descriptions such as &lt;strong&gt;&lt;em&gt;QueueDescription&lt;/em&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;em&gt;TopicDescription&lt;/em&gt;&lt;/strong&gt;, and &lt;strong&gt;&lt;em&gt;SubscriptionDescription&lt;/em&gt;&lt;/strong&gt;. When this property is set to a TimeSpan (from 1 minute to &lt;em&gt;TimeSpan.MaxValue&lt;/em&gt;), the corresponding entity will be automatically deleted after being inactive during the given time period. &lt;strong&gt;&lt;em&gt;AutoDeleteOnIdle&lt;/em&gt;&lt;/strong&gt; attribute can make entity managements a lot easier in many cases. For instance, a chat server won’t need to monitor chat room activities to clean up topics and subscriptions it may have created for a chat room – the entities clean themselves up when the chat room becomes inactive. Now let’s walk through a sample to see how this property works.&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Create a new Windows Console application.  &lt;li&gt;Install the preview NuGet package:&lt;pre class="csharpcode"&gt;install-package &lt;strong&gt;ServiceBus.Preview&lt;/strong&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;li&gt;Implement the &lt;em&gt;&lt;strong&gt;Main()&lt;/strong&gt;&lt;/em&gt; method:&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Main(&lt;span class="kwrd"&gt;string&lt;/span&gt;[] args)
{
  var queuePath = &lt;span class="str"&gt;"autodeletequeue"&lt;/span&gt;;
            
  NamespaceManager nm = &lt;span class="kwrd"&gt;new&lt;/span&gt; NamespaceManager(
    ServiceBusEnvironment.CreateServiceUri(&lt;span class="str"&gt;"https"&lt;/span&gt;, &lt;span class="str"&gt;"&lt;em&gt;[Your SB namespace]&lt;/em&gt;"&lt;/span&gt;, &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty),
    TokenProvider.CreateSharedSecretTokenProvider(&lt;span class="str"&gt;"owner"&lt;/span&gt;, &lt;span class="str"&gt;"&lt;em&gt;[Your secret key]&lt;/em&gt;"&lt;/span&gt;));
           
  QueueDescription queue = &lt;span class="kwrd"&gt;new&lt;/span&gt; QueueDescription(queuePath);
  &lt;font style="background-color: #ffff00"&gt;queue.AutoDeleteOnIdle = TimeSpan.FromMinutes(1);
&lt;/font&gt;            
  Console.WriteLine(&lt;span class="str"&gt;"Creating queue..."&lt;/span&gt;);
  nm.CreateQueue(queue);
  Console.WriteLine(&lt;span class="str"&gt;"Queue created!"&lt;/span&gt;);
  
  DateTime creation = DateTime.Now;
  &lt;span class="kwrd"&gt;while&lt;/span&gt; (nm.QueueExists(queuePath))
  {
    Console.WriteLine(&lt;span class="str"&gt;"Queue exists after: "&lt;/span&gt; + (DateTime.Now - creation).TotalSeconds.ToString(&lt;span class="str"&gt;"#.#"&lt;/span&gt;) + &lt;span class="str"&gt;" seconds"&lt;/span&gt;);
    Thread.Sleep(1000);
  }
            
  Console.WriteLine(&lt;span class="str"&gt;"Queue removed!"&lt;/span&gt;);
            
  Console.ReadLine();
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;The code is very straightforward – it creates a queue with the &lt;strong&gt;&lt;em&gt;AutoDeleteOnIdle&lt;/em&gt;&lt;/strong&gt; property set to 1 minute. And it waits till the queue disappears. The following is a screenshot of the program when I ran it in a coffee shop (whose Internet isn’t that great):&lt;/p&gt;
&lt;p&gt;&lt;a href="http://lh3.ggpht.com/-7s5ZHOg7cEE/UQTrrnCQUMI/AAAAAAAAA9U/PecAXkI_-Os/s1600-h/image%25255B4%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh5.ggpht.com/-18UqR69Yylo/UQTrsO8oEaI/AAAAAAAAA9c/vaakpkRLHJA/image_thumb%25255B2%25255D.png?imgmax=800" width="273" height="212"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As you can see the queue disappears in about 2 minutes. I tried the program several times and the queue went away in about 1.5 to 3 minutes (though the &lt;strong&gt;&lt;em&gt;AutoDeleteOnIdel&lt;/em&gt;&lt;/strong&gt; is set to 1 minute). This should not be a concern as in this case we are leaving the system to automatically recycle the entities for us. The entities being removed a bit later isn’t unacceptable. On the other hand, we need to have a better understanding of what “Idle” means. Does it count as “idle” if there are no messages passing through the pipeline, or there has to be absolutely no activities? It turned out, &lt;u&gt;“Idle” means no attached clients are trying to send or receive messages&lt;/u&gt;. Let’s modify the &lt;strong&gt;&lt;em&gt;Main()&lt;/em&gt;&lt;/strong&gt; method a little: &lt;pre class="csharpcode"&gt;...
&lt;font style="background-color: #ffff00"&gt;QueueClient client = QueueClient.CreateFromConnectionString(&lt;span class="str"&gt;"[Connection String]"&lt;/span&gt;, queuePath);&lt;/font&gt;

DateTime creation = DateTime.Now;
&lt;span class="kwrd"&gt;while&lt;/span&gt; (nm.QueueExists(queuePath))
{
  &lt;font style="background-color: #ffff00"&gt;client.Receive(TimeSpan.FromSeconds(3));&lt;/font&gt;
  Console.WriteLine(&lt;span class="str"&gt;"Queue exists after: "&lt;/span&gt; + (DateTime.Now - creation).TotalSeconds.ToString(&lt;span class="str"&gt;"#.#"&lt;/span&gt;) + &lt;span class="str"&gt;" seconds"&lt;/span&gt;);
  Thread.Sleep(1000);
}
...&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
The &lt;strong&gt;&lt;em&gt;Receive()&lt;/em&gt; &lt;/strong&gt;calls make the queue active, though they don’t get any messages back. Now consider the following code: &lt;pre class="csharpcode"&gt;...
QueueClient client = QueueClient.CreateFromConnectionString(&lt;span class="str"&gt;"[Connection String]"&lt;/span&gt;, queuePath);
&lt;font style="background-color: #ffff00"&gt;client.OnMessage((m) =&amp;gt; {}, 1);
&lt;/font&gt;            
DateTime creation = DateTime.Now;
&lt;span class="kwrd"&gt;while&lt;/span&gt; (nm.QueueExists(queuePath))
{
  Console.Write(&lt;span class="str"&gt;"Queue exists after: "&lt;/span&gt; + (DateTime.Now - creation).TotalSeconds.ToString(&lt;span class="str"&gt;"#.#"&lt;/span&gt;) + &lt;span class="str"&gt;" seconds"&lt;/span&gt;);
  Thread.Sleep(1000);
}
...&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
In this version, I’m not calling &lt;strong&gt;&lt;em&gt;Receive()&lt;/em&gt;&lt;/strong&gt; method anymore. However, because I subscribed to &lt;strong&gt;&lt;em&gt;OnMessage&lt;/em&gt;&lt;/strong&gt; event, the queue is kept alive. If you want to release the queue in this case, you’ll need to close the attached client(s) by calling &lt;strong&gt;&lt;em&gt;Close()&lt;/em&gt;&lt;/strong&gt; method on &lt;strong&gt;&lt;em&gt;QueueClient&lt;/em&gt;&lt;/strong&gt; class.

&lt;p&gt;And this concludes the second part of this series. I hope this helps. Thank you reading!&lt;/p&gt;  &lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/43kwDlDFv98" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/1952780880609068405/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2013/01/new-features-in-service-bus-preview_27.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/1952780880609068405?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/1952780880609068405?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/43kwDlDFv98/new-features-in-service-bus-preview_27.html" title="New features in Service Bus Preview Library (January 2013) – 2: Auto-expiration" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/-18UqR69Yylo/UQTrsO8oEaI/AAAAAAAAA9c/vaakpkRLHJA/s72-c/image_thumb%25255B2%25255D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2013/01/new-features-in-service-bus-preview_27.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUcFSXw5fip7ImA9WhNaEko.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-3889656944412860870</id><published>2013-01-25T15:31:00.001-08:00</published><updated>2013-01-27T00:56:58.226-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-27T00:56:58.226-08:00</app:edited><title>New features in Service Bus Preview Library (January 2013) - 1: Message Pump</title><content type="html">&lt;p&gt;Recently Microsoft has announced the new Windows Azure Service Bus &lt;a href="http://weblogs.asp.net/scottgu/archive/2013/01/22/broadcast-push-notifications-to-millions-of-mobile-devices-using-windows-azure-notification-hubs.aspx"&gt;Push Notification Hubs&lt;/a&gt;. And many &lt;a href="http://msdn.microsoft.com/en-us/library/jj891130.aspx"&gt;samples&lt;/a&gt; and &lt;a href="http://channel9.msdn.com/Blogs/Subscribe/Service-Bus-Notification-Hubs-Code-Walkthrough-Windows-8-Edition"&gt;videos&lt;/a&gt; have been posted on the new feature. To support Notification Hubs, a new Service Bus previews features library (&lt;strong&gt;Microsoft.ServiceBus.Preview.dll&lt;/strong&gt;) has been released to &lt;a href="http://nuget.org/packages/ServiceBus.Preview"&gt;NuGet gallery&lt;/a&gt;. In this series of post I’ll drill down to several other cool new features and important enhancements contained in this library.&lt;/p&gt; &lt;p&gt;&lt;em&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;[This post series is based on preview features that are subject to change]&lt;/font&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt; &lt;h2&gt;Message Pump&lt;/h2&gt; &lt;p&gt;Up until now, if you want to receive messages from a Windows Azure Service Bus queue or topic/subscription, you need to periodically poll the queue or the subscription asking for new messages. The following code should look quite familiar:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;while&lt;/span&gt; (!IsStopped)
{
    ...
    BrokeredMessage receivedMessage = &lt;span class="kwrd"&gt;null&lt;/span&gt;;
    receivedMessage = Client.Receive();

     &lt;span class="kwrd"&gt;if&lt;/span&gt; (receivedMessage != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
    {
        ...
        receivedMessage.Complete();
    }
    ...    
    Thread.Sleep(10000);
}&lt;/pre&gt;
&lt;p&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
Actually, the above code is a simplified version of auto-generated code when you used “Worker Role with Service Queue” template to add a new Worker Role. This pattern works well in this case because you do need a loop or other blocking wait in your &lt;strong&gt;&lt;em&gt;Run()&lt;/em&gt;&lt;/strong&gt; method to keep your role instances running. However, there are a couple of problems with this pattern. First, the &lt;strong&gt;&lt;em&gt;Thread.Sleep()&lt;/em&gt;&lt;/strong&gt; calls cause unnecessary delays in the system – the above code can only respond to at most one message every ten seconds. This kind of throughputs is unacceptable to many systems. Of course we can reduce the sleep interval, let’s say to get it down to 1 second. This makes the system more responsive, but it creases number of service calls by 10 times. Polling at a 1 second interval generates 86,400 billable messages (60 * 60 * 24) per day, even if most of them are NULL messages. That doesn’t cost much – at the price of $0.01 per 10,000 billable messages it translates to 8.64 cents per day. However that IS a lot of service calls. Second, in some applications, especially client applications, event-driving programming model is often preferred.&amp;nbsp; &lt;a href="http://nuget.org/packages/ServiceBus.Preview"&gt;Service Bus preview features&lt;/a&gt; changes all these. Underneath it uses long-polling so that you don’t occur service transactions as often. And you get immediate feedbacks when a new message shows up in the pipeline. For instance, let’s say if default long-polling timeout is 1 minute, the number of billable messages reduces to 1,440 (60 * 24) per day. That’s quite a improvement in terms of reducing number of service calls. In addition, the preview library supports event-driven model instead of polling - you can simply wait for &lt;strong&gt;&lt;em&gt;OnMessage&lt;/em&gt;&lt;/strong&gt; events.&lt;/p&gt;
&lt;p&gt;The following is a walkthrough of using the preview library. The walkthrough uses a simple WPF application that allows you to send and receive messages.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a new WFP application. 
&lt;li&gt;Install the preview NuGet package: &lt;pre class="csharpcode"&gt;install-package &lt;strong&gt;ServiceBus.Preview&lt;/strong&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;li&gt;Get a minimum UI in place:&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Window&lt;/span&gt; &lt;span class="attr"&gt;x:Class&lt;/span&gt;&lt;span class="kwrd"&gt;="EventPumpWPF.MainWindow"&lt;/span&gt;
        &lt;span class="attr"&gt;xmlns&lt;/span&gt;&lt;span class="kwrd"&gt;="http://schemas.microsoft.com/winfx/2006/xaml/presentation"&lt;/span&gt;
        &lt;span class="attr"&gt;xmlns:x&lt;/span&gt;&lt;span class="kwrd"&gt;="http://schemas.microsoft.com/winfx/2006/xaml"&lt;/span&gt;
        &lt;span class="attr"&gt;Title&lt;/span&gt;&lt;span class="kwrd"&gt;="Message-Driven Messaging"&lt;/span&gt; &lt;span class="attr"&gt;Height&lt;/span&gt;&lt;span class="kwrd"&gt;="350"&lt;/span&gt; &lt;span class="attr"&gt;Width&lt;/span&gt;&lt;span class="kwrd"&gt;="525"&lt;/span&gt; &lt;span class="attr"&gt;FontSize&lt;/span&gt;&lt;span class="kwrd"&gt;="18"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;StackPanel&lt;/span&gt; &lt;span class="attr"&gt;Grid&lt;/span&gt;.&lt;span class="attr"&gt;Column&lt;/span&gt;&lt;span class="kwrd"&gt;="0"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;TextBox&lt;/span&gt; &lt;span class="attr"&gt;x:Name&lt;/span&gt;&lt;span class="kwrd"&gt;="messageText"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Button&lt;/span&gt; &lt;span class="attr"&gt;x:Name&lt;/span&gt;&lt;span class="kwrd"&gt;="sendMessage"&lt;/span&gt; &lt;span class="attr"&gt;Click&lt;/span&gt;&lt;span class="kwrd"&gt;="sendMessage_Click_1"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Send&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Button&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;ListBox&lt;/span&gt; &lt;span class="attr"&gt;x:Name&lt;/span&gt;&lt;span class="kwrd"&gt;="messageList"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;StackPanel&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Window&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;li&gt;Modify the code-behind:&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;partial&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; MainWindow : Window
    {
        &lt;span class="kwrd"&gt;const&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; conString = &lt;span class="str"&gt;"[SB connection string]"&lt;/span&gt;;
        &lt;span class="kwrd"&gt;const&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; queueName = &lt;span class="str"&gt;"workqueue"&lt;/span&gt;;
        QueueClient mSender, mReceiver; 
        
        &lt;span class="kwrd"&gt;public&lt;/span&gt; MainWindow()
        {
            InitializeComponent();
            mSender = QueueClient.CreateFromConnectionString(conString, queueName);
            mReceiver = QueueClient.CreateFromConnectionString(conString, queueName, ReceiveMode.ReceiveAndDelete);

            &lt;font style="background-color: #ffff00"&gt;mSender.OnMessage&lt;/font&gt;((m) =&amp;gt;
            {
                messageList.Dispatcher.Invoke(() =&amp;gt;
                    {
                        messageList.Items.Add(m.GetBody&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;());
                    });
            }, &lt;font style="background-color: #00ff00"&gt;1&lt;/font&gt;);
        }

        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; sendMessage_Click_1(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, RoutedEventArgs e)
        {
            mSender.Send(&lt;span class="kwrd"&gt;new&lt;/span&gt; BrokeredMessage(messageText.Text));
            messageText.Text = &lt;span class="str"&gt;""&lt;/span&gt;;
        }
    }&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;li&gt;And that’s all! The only line that is new is highlighted – very simple and very straightforward. &lt;br clear="all"&gt;&lt;a href="http://lh4.ggpht.com/-xWmm0pK0fRk/UQMVsZRLGrI/AAAAAAAAA8E/ZmNHrHix7UA/s1600-h/image2.png"&gt;&lt;img title="image" 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="image" src="http://lh6.ggpht.com/-9RCh_dDoM6Q/UQMVsgnE0bI/AAAAAAAAA8M/muIXUQJb_vo/image_thumb.png?imgmax=800" width="216" height="244"&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;If you’ve observed closely, you might notice there’s a second parameter (highlight in green) to OnMessage() method. This method controls how many concurrent calls to the callback (the first parameter) can occur. To illustrate the effect of this parameter, let’s modify the code a little.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;First, we add a randomizer to MainWindow class: &lt;pre class="csharpcode"&gt;Random rand = &lt;span class="kwrd"&gt;new&lt;/span&gt; Random();&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;li&gt;And we’ll update or message handler to add a random sleep. This is to simulate fluctuations in processing time:&lt;pre class="csharpcode"&gt;mSender.OnMessage((m) =&amp;gt;
{
    &lt;font style="background-color: #ffff00"&gt;Thread.Sleep(rand.Next(1000, 3000));&lt;/font&gt;
    messageList.Dispatcher.Invoke(() =&amp;gt;
    {
        messageList.Items.Add(m.GetBody&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;());
    });
}, &lt;font style="background-color: #00ff00"&gt;1&lt;/font&gt;);&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;li&gt;Finally, we change the sending code to send 10 messages instead of 1:&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; i = 0; i &amp;lt; 10; i++)
{
    mSender.Send(&lt;span class="kwrd"&gt;new&lt;/span&gt; BrokeredMessage(messageText.Text + i.ToString()));
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;li&gt;Now launch the program and send a message “m”, which morphs into ten messages. The code takes a while to execute because of the random sleeps and there’s only a single entry is allowed to the callback. But because the single-entrance limit, you eventually get all messages back in-order.&lt;br clear="all"&gt;&lt;a href="http://lh6.ggpht.com/-cfA0QO-JFWY/UQMVtj9gVzI/AAAAAAAAA8Q/yhqM46i5eYQ/s1600-h/image5.png"&gt;&lt;img title="image" 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="image" src="http://lh3.ggpht.com/-6hIArsbdNSY/UQMVtz0Ih2I/AAAAAAAAA8Y/piKduRxBRac/image_thumb1.png?imgmax=800" width="158" height="244"&gt;&lt;/a&gt; 
&lt;li&gt;Now modify the second parameter (highlighted in green) to 10. Run the app again. Now the code takes shorter time to execute because the callback can be invoked multiple times at the same time. But the message display may be out-of-order:&lt;br clear="all"&gt;&lt;a href="http://lh5.ggpht.com/-NESuJU0TWtk/UQMVuawofvI/AAAAAAAAA8k/RKN47mlaLdU/s1600-h/image9.png"&gt;&lt;img title="image" 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="image" src="http://lh4.ggpht.com/-xbhNrP09NA0/UQMVu7NBf8I/AAAAAAAAA8o/SO5w5D3JkE0/image_thumb3.png?imgmax=800" width="158" height="224"&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;There you go. A very cool addition to Service Bus provided by&amp;nbsp; &lt;a href="http://nuget.org/packages/ServiceBus.Preview"&gt;Service Bus preview features&lt;/a&gt;. The feature is very useful when you want to use event-driven programming. I hope this helps. Thank you for reading!&lt;/p&gt;  &lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/fxip8QnDbqM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/3889656944412860870/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2013/01/new-features-in-service-bus-preview.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/3889656944412860870?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/3889656944412860870?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/fxip8QnDbqM/new-features-in-service-bus-preview.html" title="New features in Service Bus Preview Library (January 2013) - 1: Message Pump" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/-9RCh_dDoM6Q/UQMVsgnE0bI/AAAAAAAAA8M/muIXUQJb_vo/s72-c/image_thumb.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2013/01/new-features-in-service-bus-preview.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkUDSH44fSp7ImA9WhNbFUs.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-5421749273287518577</id><published>2012-12-21T18:04:00.001-08:00</published><updated>2013-01-18T17:51:19.035-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-18T17:51:19.035-08:00</app:edited><title>Dealing with long-running jobs</title><content type="html">&lt;p&gt;&lt;font color="#000000"&gt;Many systems need to deal with long-running jobs. Long-running jobs are slow, and they often take up lots of system resources. In addition, long-running jobs raise additional requirements such as progress report/monitoring, cancellation, failover, and prioritization, etc. For such systems, it’s very important to use a scalable, efficient and reliable architecture to ensure system performance. This blog article explores some of the common patterns of such a system and provides some guidance on implementing a Request-Acknowledge-Push pattern using Windows Azure Cloud Services.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;[Now this article has a corresponding Channel 9 episode. Check it out at: &lt;a title="http://channel9.msdn.com/Series/Cloud-Patterns/Episode-1-Long-running-tasks-Request-Acknowledge-Push-pattern" href="http://channel9.msdn.com/Series/Cloud-Patterns/Episode-1-Long-running-tasks-Request-Acknowledge-Push-pattern"&gt;http://channel9.msdn.com/Series/Cloud-Patterns/Episode-1-Long-running-tasks-Request-Acknowledge-Push-pattern&lt;/a&gt;]&lt;/p&gt; &lt;h2&gt;Patterns&lt;/h2&gt; &lt;p&gt;There are several patterns that can be used by clients to submit long-running jobs to server. However the idea behind these patterns is the same, which is to avoid temporal coupling between the client and the actual executors.  &lt;h3&gt;Request-Acknowledge&lt;/h3&gt; &lt;p&gt;This is probably the simplest pattern, in which a client sends a job to a server, and the server acknowledges the submission. Then, the client and the server move on with their own businesses. If we map this pattern to a Windows Azure Cloud Service, we get the following diagram. As a matter of fact, if you create a new Cloud Service using a Web Role and a Worker Role with Service Bus Queue template, this is (almost) exactly what you get – the only missing part you need to add is the web role submitting a job to the Service Bus queue.  &lt;p&gt;Let’s imagine a user submits an order to a e-commerce site. From the perspective of the end user, the process (or the workflow) of ordering an item completes when the order has been successfully submitted. Although the new order triggers a long process on the service side, the user doesn’t have to wait for that process to complete. With the expectation that an order often takes days (or even longer) to process, the user will leave with the expectation that his/her order will be eventually processed at a later time. Note that in this case the Web Role made the promise based on its faith in Service Bus, which guarantees delivery of the job when there’s an appropriate recipient asking for it. This recipient can be a Worker Role in the same Cloud Service, or it can be any legitimate Service Bus queue client running at anywhere – on cloud or on-premises, it doesn’t matter.  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-hEOLH_BBheE/UNUVCkLSqiI/AAAAAAAAA60/9bjDZgkSXbA/s1600-h/image7.png"&gt;&lt;img title="image" 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="image" src="http://lh5.ggpht.com/-hwic7zfef1w/UNUVDpdVGAI/AAAAAAAAA68/LFHUW1jiSvA/image_thumb5.png?imgmax=800" width="470" height="178"&gt;&lt;/a&gt;&lt;/p&gt; &lt;h3&gt;Request-Acknowledge-Poll&lt;/h3&gt; &lt;p&gt;In many cases a client does care the progress of a submitted job and wants to get immediate feedbacks on job progress – how many times have you been impatiently watching the file upload/download bars? However, with HTTP protocol, the server sending acknowledgement completes the HTTP request. To get progress updates, the client will need to send additional requests to poll for updates. To achieve this we need two additional pieces – one additional service for clients to query for updates, and a job status repository so that the service can query for job statuses.&amp;nbsp; The following diagram should be self-explanatory – the Web Role provides an additional method for clients to query for job status updates, and an extra repository is added to save job statuses.&amp;nbsp; Note that because submitting a job and polling for progress are two separate HTTP requests, you’ll need to provide some mechanism, such as a GUID job id, to correlate polling requests with corresponding submissions.&amp;nbsp; This id, sometimes referred as a (job) token, is usually generated on the server and is provided to the client when server sends the job submission acknowledgement. &lt;/p&gt; &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-XbYgAuHtsNk/UNUVEDF9plI/AAAAAAAAA7E/crDTseRsgzI/s1600-h/image13.png"&gt;&lt;img title="image" 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="image" src="http://lh5.ggpht.com/-bxXGPd_-qNE/UNUVF_dwERI/AAAAAAAAA7M/oD6vLzHJwXw/image_thumb9.png?imgmax=800" width="548" height="248"&gt;&lt;/a&gt;&lt;/p&gt; &lt;h3&gt;Request-Acknowledge-Push&lt;/h3&gt; &lt;p&gt;Can we eliminate the need for an extra database?&amp;nbsp; Wouldn’t it be nice if we can directly push the job statues back to the client? We can use Request-Acknowledge-Push pattern for this purpose. This pattern is a variation of Request-Acknowledge-Callback, where the job executor (the Worker Role) proactively calls into a callback service, such as a SMTP service, to report job statuses. However, as it’s hard for a web client to host a callback service, I adapted the pattern to allow job executors to push job statuses to an arbitrary recipient, including the client.&amp;nbsp; Particularly, the following diagram shows such an implementation using SignalR to push job statuses back to the web client. In this implementation, the Web Role hosts a SignalR hub, which the Worker Role connects to (via a hub proxy) and reports job updates. And then, the hub pushes the updates to attached client(s).&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-nKDL7tvfGXI/UNUVGoQ3kwI/AAAAAAAAA7U/1Po_iCM8mfM/s1600-h/image18.png"&gt;&lt;img title="image" 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="image" src="http://lh5.ggpht.com/-CtNKDNFHoHQ/UNUVHZMy9bI/AAAAAAAAA7c/tCsIB_xzYZk/image_thumb12.png?imgmax=800" width="486" height="220"&gt;&lt;/a&gt;&lt;/p&gt; &lt;h2&gt;Implementation of the Request-Acknowledge-Push Pattern&lt;/h2&gt; &lt;p&gt;&lt;font color="#000000"&gt;In this part I’ll briefly go through an implementation of Request-Acknowledge-Push pattern using SignalR.&amp;nbsp; Instead of a complete walkthrough, I’ll just mention some key pieces of the code. If you are interested in getting the complete code, please contact me and I’ll put the code somewhere. &lt;/font&gt;&lt;/p&gt; &lt;p&gt;The first thing we need is a type that represents a job: &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Job
{
  &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ClientId { get; set; }
  &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; JobId { get; set; }
  &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Content { get; set; }
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
In above definition I embedded the client id into the &lt;strong&gt;&lt;em&gt;Job&lt;/em&gt;&lt;/strong&gt; type itself. This might raise some eyebrows as it’s debatable if the originating client logically belongs to the &lt;strong&gt;&lt;em&gt;Job&lt;/em&gt;&lt;/strong&gt; type. I chose to do this because in a push scenario, we need to be able to associate a job with originating client so that we know which client to send updates to. We can do this using a separate lookup, of course. But that requires some extra work as we need to make sure the reliability and availability of this lookup mechanism – that’s too much trouble.

&lt;p&gt;The Worker Role creates a SignalR proxy and sends progress updates back to the Web Role, as depicted in above diagram: &lt;/p&gt;&lt;pre class="csharpcode"&gt;HubConnection connection = &lt;span class="kwrd"&gt;new&lt;/span&gt; HubConnection(&lt;span class="str"&gt;"http://127.0.0.1:81"&lt;/span&gt;);
IHubProxy proxy = connection.CreateHubProxy(&lt;span class="str"&gt;"ProgressNotifier"&lt;/span&gt;);
connection.Start().Wait();

...

&lt;span class="kwrd"&gt;while&lt;/span&gt; (!IsStopped)
{
   BrokeredMessage receivedMessage = &lt;span class="kwrd"&gt;null&lt;/span&gt;;
   receivedMessage = Client.Receive();

  &lt;span class="kwrd"&gt;if&lt;/span&gt; (receivedMessage != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
  {
     Job job = receivedMessage.GetBody&amp;lt;Job&amp;gt;();
     ...
     proxy.Invoke(&lt;span class="str"&gt;"ProgressUpdated"&lt;/span&gt;, job.ClientId, job.JobId, 35);
     ...
     proxy.Invoke(&lt;span class="str"&gt;"ProgressUpdated"&lt;/span&gt;, job.ClientId, job.JobId, 100);
     receivedMessage.Complete();
  }
...&lt;/pre&gt;
&lt;p&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
The Web Role provides implementation of the SignalR hub (note how we identify which client to talk to using client id embedded in Job type):&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ProgressNotifier : Hub
{
   &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ProgressUpdated(&lt;span class="kwrd"&gt;string&lt;/span&gt; clientId, &lt;span class="kwrd"&gt;string&lt;/span&gt; jobId, &lt;span class="kwrd"&gt;int&lt;/span&gt; progress)
   {
      Clients.Client(clientId).progressUpdated(jobId, progress);
   }
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;


&lt;p&gt;And the method to submit a Job:&lt;pre class="csharpcode"&gt;[HttpGet]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ReqAck(&lt;span class="kwrd"&gt;string&lt;/span&gt; clientId)
{
   ...
   &lt;span class="kwrd"&gt;string&lt;/span&gt; jobId = Guid.NewGuid().ToString();
   client.Send(&lt;span class="kwrd"&gt;new&lt;/span&gt; BrokeredMessage(&lt;span class="kwrd"&gt;new&lt;/span&gt; Job
            {
                ClientId = clientId,
                JobId = jobId,
                Content = &lt;span class="str"&gt;"some workload"&lt;/span&gt;
            }));
    &lt;span class="kwrd"&gt;return&lt;/span&gt; jobId;
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;


&lt;p&gt;On client side, SignalR connection Id is recorded when a connection is established:&lt;pre class="csharpcode"&gt;var clientId;

$(function () {
        hub = $.signalR.progressNotifier;
        hub.on(&lt;span class="str"&gt;"progressUpdated"&lt;/span&gt;, function (jobId, progress) {
           ...
        });
        $.signalR.hub.start().done(function () {
            &lt;font style="background-color: #ffff00"&gt;clientId = $.connection.hub.id&lt;/font&gt;;
        });
        ...
});&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;


&lt;p&gt;And it’s sent to the server when the client submits a job:&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;var&lt;/span&gt; viewModel = {
  reqAck: &lt;span class="kwrd"&gt;function&lt;/span&gt; () {
    $.getJSON(&lt;span class="str"&gt;'/api/Job/ReqAck?type=a&amp;amp;&lt;font style="background-color: #ffff00"&gt;clientId='&lt;/font&gt;&lt;/span&gt;&lt;font style="background-color: #ffff00"&gt; + clientId&lt;/font&gt;, &lt;span class="kwrd"&gt;function&lt;/span&gt; (json) {
      ...
    });
  },
  ...&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;


&lt;h2&gt;Dealing with Cancelation&lt;/h2&gt;
&lt;p&gt;It’s often a good idea to support job cancellation for long-running jobs. Some systems support only explicit cancelation, which means user has to explicitly cancel a job. Some other systems automatically cancel a job when the client that has submitted the job disconnects. There’s also a third type of cancellation where a user re-submits a job (possibly with modifications) that causes previously submitted jobs cancelled. When cancellation happens, the job to be cancelled can be any of the following states: waiting in queue, being executed, and completed or faulted. There’s nothing much we can do for the last case – the job has been completed before we can cancel it. Depends on your system requirements, you can allow user to undo a job, which is just another job to be pumped into the system. &lt;/p&gt;
&lt;h3&gt;Stop list&lt;/h3&gt;
&lt;p&gt;When a job is waiting in the queue, we can simply remove it from the queue. However, most queue services only allow sequential access of items, which means you’ll have to scan the queue to find and remove the job. This scanning process competes with job executors who also poll the same queue, hence it may briefly block all the executors as it locks the queue items for examination. Moreover, removing a job from waiting queue doesn’t handle the case that the job is already being processed. You’ll also need to locate and inform the executor who’s running the job to stop processing.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;A better method is to create a separate &lt;strong&gt;stop list&lt;/strong&gt;, which holds indexes to the jobs to be cancelled. To cancel a job, you simply add the job id into this list. The executors will check to see if a job is in this list before running it. The executors are also free to check this list whenever a job can be safely cancelled. So the stop list handles both waiting jobs and active jobs. Obviously, the stop list has to be scalable and available to all running executors, and it should be cleaned once a job is successfully cancelled. &lt;/p&gt;
&lt;h3&gt;Disconnected Client&lt;/h3&gt;
&lt;p&gt;With ASP.Net, you can use &lt;strong&gt;&lt;em&gt;System.Web.HttpResponse.IsClientConnected&lt;/em&gt;&lt;/strong&gt; to check if the client who initiated the request is still connected. Note this method only works when you use IIS instead of development web server. If you are using SignalR, you can also respond to &lt;strong&gt;&lt;em&gt;OnDisconnected&lt;/em&gt;&lt;/strong&gt; event on your hub and add the job originated from the client into the stop list.&lt;/p&gt;
&lt;h2&gt;Other Concerns&lt;/h2&gt;
&lt;p&gt;To avoid this post getting too long, here I’ll just briefly mention some of other concerns you’ll need to address – they are also important, I’m simply running out of time here. If you are interested in any of the following topics, please comment and I’ll try to expand the post later.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dealing with Failures&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;There are three main types of failures: executor failing to process a job, timeout, and system-wide failure. Workflow Foundation provides many powerful features such as failover, recovery from system failure, workflow cancellation, etc. If the demand of fault tolerance is high, you may consider using Workflow Foundation to take advantage of these features. &lt;/p&gt;&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dealing with Duplicated Requests&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;There are two strategies of handling duplicated requests. One is to discard duplicated requests, the other is to process only the newest requests. Choosing which strategy depends on your system requirements. Windows Azure Service Bus supports detection of duplicated messages. You may want to leverage the feature when dealing with duplicated requests.&lt;/p&gt;&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dealing with Priorities&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;It’s very common that jobs come with associated priorities. Intuitively, if the waiting queue is a &lt;strong&gt;priority queue&lt;/strong&gt;, handling job priority is relatively easy – when an executor is free to get a new job it will get a job with highest priority. At the time when this post is written, there’s no built-in support of priority queue in Windows Azure Service Bus yet, but there are several implementations from the community. An alternative way is to have multiple queues, each associated with&amp;nbsp; different priority levels such as “high”, “medium”, and “low”. A free executor will always try to get job from the queue with highest priority before it moves on to the next queue. &lt;/p&gt;&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dealing with Heavy Loads&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;In above patterns we use separate Worker Roles as job executors. Because you can scale different roles independently, you can easily have multiple Worker Roles to act as &lt;strong&gt;competing consumers&lt;/strong&gt; of the job queue to load balance the jobs, or to handle unexpected spikes in workloads. A work role places a temporary lock on the queued item it works on using &lt;strong&gt;&lt;em&gt;PeekLock&lt;/em&gt;&lt;/strong&gt;, and it removes the item from the queue by marking the item &lt;strong&gt;&lt;em&gt;Complete&lt;/em&gt;&lt;/strong&gt; (or &lt;strong&gt;&lt;em&gt;Abandon&lt;/em&gt;&lt;/strong&gt; in case of errors). Read &lt;a href="http://msdn.microsoft.com/en-us/library/windowsazure/hh851750.aspx"&gt;this windowsazure.com article&lt;/a&gt; for more details. &lt;/p&gt;
&lt;p&gt;Depends on the loads of your site, you may also consider leveraging ASP.NET MVC4 asynchronous methods to achieve high concurrency using a single Web Role. One common problem for ASP.NET to support high concurrency is &lt;strong&gt;thread starvation&lt;/strong&gt;. With asynchronous methods, you can achieve much higher concurrency because the thread pool is not exhausted as quickly as when synchronous methods are used. Read reference material #4 at the end of this post for more details.&lt;/p&gt;
&lt;p&gt;Last but not least, many long-running processes are I/O-bound. I/O operations may become a bottleneck of the system when workload increases. And when you use an additional repository for job statuses, the repository itself may become a bottleneck as well.&amp;nbsp; Caching is often an effective way to reduce I/O operations. You should consider caching when possible.&lt;/p&gt;&lt;/blockquote&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;In summary:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Consider Request-Acknowledge-Push pattern using SignalR 
&lt;li&gt;Consider ASP.NET asynchronous methods for higher throughputs 
&lt;li&gt;Consider Stop List for job cancelation 
&lt;li&gt;Consider Workflow Foundation if you need advanced features such as failover&lt;/li&gt;&lt;/ul&gt;
&lt;h2&gt;References &amp;amp; extended readings&lt;/h2&gt;
&lt;p&gt;Some concepts, patterns, code snippets, and diagrams in this article are derived from the following resources:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Service Design Patterns: Fundamental Design Solutions for SOAP/WSDL and RESTful Web Services, Robert Daigeneau et. al., 2011 
&lt;li&gt;&lt;a href="http://channel9.msdn.com/Events/Build/2012/1-002"&gt;BUILD 2012 Day 2 Keynote&lt;/a&gt; demonstrations 
&lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/windowsazure/hh851750.aspx"&gt;windowazure.com: Implementing Reliable Message Receive Loops&lt;/a&gt; 
&lt;li&gt;&lt;a href="http://www.asp.net/mvc/tutorials/mvc-4/using-asynchronous-methods-in-aspnet-mvc-4"&gt;asp.net: Using Asynchronous Methods in ASP.NET MVC 4&lt;/a&gt; 
&lt;li&gt;Enterprise Integration Patterns: Designing, Building and Deploying Messaging Solutions, Gregor Hohpe et. al., 2003&lt;/li&gt;&lt;/ol&gt;  &lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/ofZx1LC8yoI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/5421749273287518577/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2012/12/dealing-with-long-running-jobs.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/5421749273287518577?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/5421749273287518577?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/ofZx1LC8yoI/dealing-with-long-running-jobs.html" title="Dealing with long-running jobs" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/-hwic7zfef1w/UNUVDpdVGAI/AAAAAAAAA68/LFHUW1jiSvA/s72-c/image_thumb5.png?imgmax=800" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2012/12/dealing-with-long-running-jobs.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEACSX04fyp7ImA9WhNVF08.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-8768130304324198622</id><published>2012-11-20T20:51:00.001-08:00</published><updated>2012-12-28T12:32:48.337-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-12-28T12:32:48.337-08:00</app:edited><title>Complete walkthrough: Setting up a ADFS 2.0 Server on Windows Azure IaaS and Configuring it as an Identity Provider in Windows Azure ACS</title><content type="html">&lt;p&gt;I’ve done this several times but never got a chance to document all the steps. Since now I’ve got another opportunity to do this yet again, I’ll document all the steps necessary, starting from scratch, to configure an ADFS 2.0 server on Windows Azure IaaS, and to configure it as an Identity Provider in Windows Azure ACS. Then we’ll use ACS to protect our web application that uses role-based security. Although I’m stripping down the steps to the bare minimum and cutting some corners , this will still be a long post, so please bear with me. Hopeful this could be your one-stop reference if you have such a task at hand. Here we go:&lt;/p&gt; &lt;h3&gt;Create a Virtual Network&lt;/h3&gt; &lt;p&gt;Since we are starting from scratch, we’ll start from a Virtual Network. Then, on this Virtual Network, we’ll set up our all-in-one AD forest with a single server what is both a Domain Controller (DC) and an ADFS 2.0 server. The reason we put this server on a Virtual Network is to ensure the server get a local static IP (or an ever-lasting dynamic) address.&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Log on to Windows Azure Management Portal.  &lt;li&gt;Add a new Virtual Network. In the following sample, I named my Virtual Network &lt;strong&gt;haishivn&lt;/strong&gt;, with address space &lt;strong&gt;192.168.0.0 – 192.168.15.255&lt;/strong&gt;.&lt;br clear="all"&gt;&lt;a href="http://lh4.ggpht.com/-NWYluTA5BS0/UKxdI_gwiAI/AAAAAAAAAyU/o_wg0_wV8YQ/s1600-h/image%25255B7%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh4.ggpht.com/-64zywEqsdNI/UKxdJTTSWPI/AAAAAAAAAyY/0ipOKq2xTvI/image_thumb%25255B3%25255D.png?imgmax=800" width="758" height="316"&gt;&lt;/a&gt;  &lt;li&gt;Click &lt;strong&gt;CREATE A VIRTUAL NETWORK&lt;/strong&gt; link to create the network.&lt;/li&gt;&lt;/ol&gt; &lt;h3&gt;Provision the Virtual Machine&lt;/h3&gt; &lt;ol&gt; &lt;li&gt;In Windows Azure Management Portal, select &lt;strong&gt;NEW&lt;/strong&gt;-&amp;gt;&lt;strong&gt;COMPUTE&lt;/strong&gt;-&amp;gt;&lt;strong&gt;VIRTUAL MACHINE&lt;/strong&gt;-&amp;gt;&lt;strong&gt;FROM GALLERY&lt;/strong&gt;.  &lt;li&gt;Select &lt;strong&gt;Windows Server 2012, October 2012&lt;/strong&gt;, and then click &lt;strong&gt;Next arrow&lt;/strong&gt;.  &lt;li&gt;On next screen, enter the name of your virtual machine, enter administrator passport, pick the size you want to use, and then click &lt;strong&gt;Next arrow&lt;/strong&gt;.  &lt;li&gt;On next screen, enter a DNS name for your server, and make sure to put your server on the Virtual Network you just created. &lt;br clear="all"&gt;(Note in the following screenshot I’m using &lt;strong&gt;&lt;em&gt;haishidc&lt;/em&gt;&lt;/strong&gt;, while in later steps I’m using &lt;strong&gt;&lt;em&gt;haishidc2&lt;/em&gt; &lt;/strong&gt;as I messed up something in the first run and had to start over. So, please consider &lt;strong&gt;&lt;em&gt;haishidc&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;haishidc2&lt;/em&gt;&lt;/strong&gt; the same)&lt;br clear="all"&gt;&lt;a href="http://lh5.ggpht.com/-74yJEcvPbHk/UKxdJshaIYI/AAAAAAAAAyk/q5-NW3G_gQM/s1600-h/image%25255B11%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh5.ggpht.com/-R_nulSZMYu0/UKxdKf6L9ZI/AAAAAAAAAyo/yKpQimvQiNU/image_thumb%25255B5%25255D.png?imgmax=800" width="272" height="274"&gt;&lt;/a&gt;  &lt;li&gt;On last screen, leave availability set empty for now. Complete the wizard.  &lt;li&gt;Once the virtual machine is created, click on the name of the machine and select &lt;strong&gt;ENDPOINT&lt;/strong&gt; tab.  &lt;li&gt;Click &lt;strong&gt;ADD ENDPOINT&lt;/strong&gt; icon on the bottom toolbar.  &lt;li&gt;In &lt;strong&gt;ADD ENDPOINT&lt;/strong&gt; dialog, click &lt;strong&gt;next arrow&lt;/strong&gt; to continue.  &lt;li&gt;Add port &lt;strong&gt;443&lt;/strong&gt; as shown in the following screenshot:&lt;br clear="all"&gt;&lt;a href="http://lh5.ggpht.com/-X0EcqcrC1S0/UKxdKxElIyI/AAAAAAAAAyw/-MK5TA8-oPw/s1600-h/image%25255B138%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh3.ggpht.com/-zyD9ySJ52lE/UKxdLsr8aBI/AAAAAAAAAy4/lT2rC1EcrXw/image_thumb%25255B67%25255D.png?imgmax=800" width="354" height="249"&gt;&lt;/a&gt;  &lt;li&gt;Similarly, add port &lt;strong&gt;80&lt;/strong&gt;.&lt;/li&gt;&lt;/ol&gt; &lt;h3&gt;Set up The Virtual Machine&lt;/h3&gt; &lt;p&gt;Once the virtual machine is provisioned, we are ready to set up our cozy Active Directory with one member, which will be the Domain Controller as well as the ADFS 2.0 Server.&lt;/p&gt; &lt;ol&gt; &lt;li&gt;RDP into the virtual machine you just created. Wait patiently till &lt;strong&gt;Server Manager&lt;/strong&gt; shows up.  &lt;li&gt;Go to &lt;strong&gt;Local Server&lt;/strong&gt; tab, scroll down to the&lt;strong&gt; ROLES AND FEATURES&lt;/strong&gt; section, then click &lt;strong&gt;TASKS&lt;/strong&gt;-&amp;gt;&lt;strong&gt;Add Roles and Features&lt;/strong&gt;.&lt;br clear="all"&gt;&lt;a href="http://lh4.ggpht.com/-UmuhmsvFhk0/UKxdMP3fv6I/AAAAAAAAAzA/W0SEaB4jTPs/s1600-h/image%25255B16%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh5.ggpht.com/-wKJV9dbnjbs/UKxdMiCShsI/AAAAAAAAAzM/93F2cTIxJtg/image_thumb%25255B8%25255D.png?imgmax=800" width="547" height="300"&gt;&lt;/a&gt;  &lt;li&gt;In &lt;strong&gt;Add Roles and Features Wizard&lt;/strong&gt;, click &lt;strong&gt;Next&lt;/strong&gt; to continue.  &lt;li&gt;On next screen, keep &lt;strong&gt;Role-based or feature-based installation&lt;/strong&gt; checked, click &lt;strong&gt;Next&lt;/strong&gt; to continue.  &lt;li&gt;On &lt;strong&gt;Server selection&lt;/strong&gt; screen, accept default settings and click &lt;strong&gt;Next&lt;/strong&gt;.  &lt;li&gt;On &lt;strong&gt;Server Roles&lt;/strong&gt; screen, check &lt;strong&gt;Active Directory Domain Service&lt;/strong&gt;. This will pop up a dialog prompting to enable required features. Click &lt;strong&gt;Add Features&lt;/strong&gt; to continue.  &lt;li&gt;Check &lt;strong&gt;Active Directory Federation Services&lt;/strong&gt;. Again, click &lt;strong&gt;Add Features&lt;/strong&gt; in the pop-up to add required features.  &lt;li&gt;Click &lt;strong&gt;Next &lt;/strong&gt;all the way till the end of the wizard workflow, accepting all default settings.  &lt;li&gt;Click &lt;strong&gt;Install&lt;/strong&gt; to continue. Once installation completes, click &lt;strong&gt;Close&lt;/strong&gt; to close the wizard.&lt;/li&gt;&lt;/ol&gt; &lt;h3&gt;Configure AD and Domain controller&lt;/h3&gt; &lt;ol&gt; &lt;li&gt;Now you’ll see a warning icon reminding you some additional configurations are needed&lt;br clear="all"&gt;&lt;a href="http://lh5.ggpht.com/-VsrxJLcbCcs/UKxdNIhMBGI/AAAAAAAAAzU/v8rq1W-es_0/s1600-h/image%25255B20%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh5.ggpht.com/-FfBm0UxDVEU/UKxdNpmmaGI/AAAAAAAAAzc/BgJogqxL6y4/image_thumb%25255B10%25255D.png?imgmax=800" width="546" height="298"&gt;&lt;/a&gt;  &lt;li&gt;Click on the icon and click on the &lt;strong&gt;second&lt;/strong&gt; item, which is &lt;strong&gt;Promote this server to a domain controller&lt;/strong&gt;.  &lt;li&gt;In &lt;strong&gt;Active Directory Domain Services Configuration Wizard&lt;/strong&gt;, select &lt;strong&gt;Add a new forest&lt;/strong&gt;, enter &lt;strong&gt;cloudapp.net&lt;/strong&gt; as &lt;strong&gt;Root domain name&lt;/strong&gt;, and then click &lt;strong&gt;Next&lt;/strong&gt; to continue. Wait, what? How come our root domain name is &lt;strong&gt;cloudapp.net&lt;/strong&gt;?&amp;nbsp; Actually it doesn’t matter that much – you can call it microsoft.com if you want. However, using &lt;strong&gt;cloudapp.net&lt;/strong&gt; saves us a little trouble when we try to use self-issued certificates in later steps. From the perspective of outside word, the ADFS server who issues the token will be &lt;strong&gt;&lt;em&gt;[your virtual machine name].&lt;/em&gt;cloudapp.net&lt;/strong&gt;.&lt;strong&gt; &lt;/strong&gt;In the following steps, we’ll use IIS to generate a self-issued cert that matches with this DNS name. The goal of this post is to get the infrastructure up and running with minimum efforts. Proper configuration and usage of various certificates deserves another post by itself.&lt;br clear="all"&gt;&amp;nbsp;&lt;a href="http://lh5.ggpht.com/-jpuyZp-AOOw/UKxdOFT4WRI/AAAAAAAAAzg/Ztq4VPwWPNQ/s1600-h/image%25255B46%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh5.ggpht.com/-9CWJ58tsk2Q/UKxdOuGa_II/AAAAAAAAAzo/vRZwW5WcEio/image_thumb%25255B24%25255D.png?imgmax=800" width="474" height="349"&gt;&lt;/a&gt;  &lt;li&gt;On next screen, provide a DSRM password. Uncheck &lt;strong&gt;Domain Name System (DNS) server&lt;/strong&gt; as we don’t need this capability in our scenario (this is an all-in-one forest anyway). Click &lt;strong&gt;Next&lt;/strong&gt; to continue.  &lt;li&gt;Keep clicking &lt;strong&gt;Next&lt;/strong&gt; till &lt;strong&gt;Install&lt;/strong&gt; button is enabled. Then click &lt;strong&gt;Install&lt;/strong&gt;.  &lt;li&gt;The machine reboots and you loose your RDP connection. &lt;/li&gt;&lt;/ol&gt; &lt;p&gt;(optional: grab a soda and some snacks. This will take a while)&lt;/p&gt; &lt;h3&gt;Create Some Test Accounts&lt;/h3&gt; &lt;p&gt;Before we move forward, let’s create a couple of user groups and a couple of test accounts.&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Launch &lt;strong&gt;Active Directory Users and Computers&lt;/strong&gt; (Window + Q, then search for “users”).  &lt;li&gt;Right-click on &lt;strong&gt;Users&lt;/strong&gt; node, then select &lt;strong&gt;New&lt;/strong&gt;-&amp;gt;&lt;strong&gt;Group&lt;/strong&gt;:&lt;br clear="all"&gt;&lt;a href="http://lh4.ggpht.com/-GTd0lRU4LYE/UKxdPNG3Z3I/AAAAAAAAAz0/-ac9nAQXJVQ/s1600-h/image%25255B86%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh3.ggpht.com/-9RjjK-7KzV4/UKxdPUOtU3I/AAAAAAAAAz8/bl0HNxAWAqA/image_thumb%25255B42%25255D.png?imgmax=800" width="244" height="151"&gt;&lt;/a&gt;  &lt;li&gt;In New Object window, enter Manager as group name, and change Group scope to Domain local:&lt;br clear="all"&gt;&lt;a href="http://lh3.ggpht.com/-Lly_njMK94Y/UKxdP5xTBZI/AAAAAAAAA0E/kCYKz1KEkRM/s1600-h/image%25255B94%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh6.ggpht.com/-fcIT1x2vgC8/UKxdQnZjnDI/AAAAAAAAA0M/zPilWHz3uzE/image_thumb%25255B45%25255D.png?imgmax=800" width="285" height="244"&gt;&lt;/a&gt;  &lt;li&gt;Follow the same step, create a &lt;strong&gt;Staff&lt;/strong&gt; group.  &lt;li&gt;Right-click on &lt;strong&gt;Users&lt;/strong&gt; node, then select &lt;strong&gt;New&lt;/strong&gt;-&amp;gt;&lt;strong&gt;User&lt;/strong&gt; to create a new user:&lt;br clear="all"&gt;&lt;a href="http://lh5.ggpht.com/-IIN0ew_fZGk/UKxdRTBv1RI/AAAAAAAAA0U/72BfbYVsRHY/s1600-h/image%25255B98%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh3.ggpht.com/-W22vPebSgPo/UKxdSLdW3-I/AAAAAAAAA0c/bO3BIOU6RLE/image_thumb%25255B47%25255D.png?imgmax=800" width="286" height="245"&gt;&lt;/a&gt;  &lt;li&gt;Set up a password for the user, then finish the wizard. On a test environment, you can disallow password change and make the the password never expire to simplify password management:&lt;br clear="all"&gt;&lt;a href="http://lh3.ggpht.com/-hZYqu_hnWHU/UKxdSobwLnI/AAAAAAAAA0k/9ZEqYl1Pwk0/s1600-h/image%25255B109%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh4.ggpht.com/-_iX3wbmheXg/UKxdTTS2VnI/AAAAAAAAA0s/tH6jo7SIMa4/image_thumb%25255B52%25255D.png?imgmax=800" width="285" height="244"&gt;&lt;/a&gt;  &lt;li&gt;Double-click on the user name, and add the user to Manager group:&lt;br clear="all"&gt;&lt;a href="http://lh5.ggpht.com/-XvO26W-xxrI/UKxdUWyDyxI/AAAAAAAAA00/J90nOGeMs84/s1600-h/image%25255B105%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh6.ggpht.com/-EmWCiW5gf6A/UKxdUxWSCjI/AAAAAAAAA08/d1gz4GBRBEs/image_thumb%25255B50%25255D.png?imgmax=800" width="254" height="325"&gt;&lt;/a&gt;  &lt;li&gt;Create another user, and add the user to &lt;strong&gt;Staff&lt;/strong&gt; group.&lt;/li&gt;&lt;/ol&gt; &lt;h3&gt;Configure SSL Certificate&lt;/h3&gt; &lt;p&gt;Now it’s the fun part – to configure ADFS. &lt;/p&gt; &lt;ol&gt; &lt;li&gt;Reconnect to the Virtual Machine.  &lt;li&gt;Launch &lt;strong&gt;Internet Information Services Manager&lt;/strong&gt; (Window + Q, then search for “iis”).  &lt;li&gt;Select the server node, and then double-click Server Certificates icon in the center pane.&lt;br clear="all"&gt;&lt;a href="http://lh4.ggpht.com/-tSXWi_g2KWA/UKxdVcj-IaI/AAAAAAAAA1E/vzJfj4gvdu4/s1600-h/image%25255B42%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh3.ggpht.com/-axBsT5O0i-U/UKxdV_AfMKI/AAAAAAAAA1M/aVREXzs-LCk/image_thumb%25255B22%25255D.png?imgmax=800" width="558" height="309"&gt;&lt;/a&gt;  &lt;li&gt;In the right pane, click on &lt;strong&gt;Create Self-Signed Certificate…&lt;/strong&gt; link. Give a friendly name to the cert, for example &lt;strong&gt;&lt;em&gt;haishidc2.cloudapp.net&lt;/em&gt;&lt;/strong&gt;. Click &lt;strong&gt;OK&lt;/strong&gt;. If you open the cert, you can see the cert is issued to &lt;strong&gt;&lt;em&gt;[your virtual machine name].cloudapp.net&lt;/em&gt;&lt;/strong&gt;. This is the reason why we used &lt;strong&gt;&lt;em&gt;cloudapp.net&lt;/em&gt;&lt;/strong&gt; domain name.&lt;/li&gt;&lt;/ol&gt; &lt;h3&gt;Configure ADFS Server&lt;/h3&gt; &lt;ol&gt; &lt;li&gt;Go back to &lt;strong&gt;Server Manager&lt;/strong&gt;. Click on the warning icon and select &lt;strong&gt;Run the AD FS Management snap-in.&lt;/strong&gt;&lt;br clear="all"&gt;&lt;a href="http://lh4.ggpht.com/-rb6ElkJZ-o0/UKxdWDJrAII/AAAAAAAAA1U/n3m_owumRng/s1600-h/image%25255B37%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh6.ggpht.com/-Id8JZD89HU8/UKxdWpMXrDI/AAAAAAAAA1c/CIuTQOwPF_0/image_thumb%25255B19%25255D.png?imgmax=800" width="398" height="232"&gt;&lt;/a&gt;  &lt;li&gt;Click on &lt;strong&gt;AD FS Federation Server Configuration Wizard&lt;/strong&gt; link in the center pane.  &lt;li&gt;In &lt;strong&gt;AD FS Federation Server Configuration Wizard&lt;/strong&gt;, leave &lt;strong&gt;Create a new Federation Service &lt;/strong&gt;checked, click &lt;strong&gt;Next&lt;/strong&gt; to continue.  &lt;li&gt;On next screen, keep &lt;strong&gt;New federation server farm&lt;/strong&gt; checked, click &lt;strong&gt;Next&lt;/strong&gt; to continue.  &lt;li&gt;On next screen, You’ll see our self-issued certificate is automatically chosen. Click &lt;strong&gt;Next&lt;/strong&gt; to continue.  &lt;li&gt;On next screen, setup Administrator as the service account. Click &lt;strong&gt;Next&lt;/strong&gt;.  &lt;li&gt;Click Next to complete the wizard.&lt;/li&gt;&lt;/ol&gt; &lt;h3&gt;Provision ACS namespace&lt;/h3&gt; &lt;p&gt;If you haven’t done so, you can follow these steps to provision a Windows Azure ACS namespace:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Log on to Windows Azure Management Portal.  &lt;li&gt;At upper-right corner, click on your user name, and then click Previous portal:&lt;br clear="all"&gt;&lt;a href="http://lh4.ggpht.com/-C8pog0IaJB0/UKxdXWSi69I/AAAAAAAAA1k/3staxpDX0_w/s1600-h/image%25255B52%25255D.png"&gt;&lt;img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://lh3.ggpht.com/-HJe9ZGa_t88/UKxdXqT4i7I/AAAAAAAAA1s/5bBXagXl838/image_thumb%25255B26%25255D.png?imgmax=800" width="244" height="220"&gt;&lt;/a&gt;  &lt;li&gt;This redirects to the old Silverlight portal. Click on Service Bus, Access Control &amp;amp; Caching in the left pane:&lt;br clear="all"&gt;&lt;a href="http://lh5.ggpht.com/-6SXkmoW08jI/UKxdYCvAOkI/AAAAAAAAA1w/uHU7Nzkz688/s1600-h/image%25255B55%25255D.png"&gt;&lt;img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://lh4.ggpht.com/-LW30MwNu_mE/UKxdYfA2EkI/AAAAAAAAA14/YmMOLS94FLQ/image_thumb%25255B27%25255D.png?imgmax=800" width="184" height="244"&gt;&lt;/a&gt;  &lt;li&gt;Click New icon in the top tool bar to create a new ACS namespace:&lt;br clear="all"&gt;&lt;a href="http://lh4.ggpht.com/-CCH4uuu-UmQ/UKxdZMWXvRI/AAAAAAAAA2E/hoWte5lNqzw/s1600-h/image%25255B58%25255D.png"&gt;&lt;img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://lh5.ggpht.com/-IGCyAUpNUJc/UKxdZ1vJw5I/AAAAAAAAA2M/m06mVUUQu4c/image_thumb%25255B28%25255D.png?imgmax=800" width="244" height="91"&gt;&lt;/a&gt;  &lt;li&gt;Enter a unique ACS namespace name, and click Create Namespace:&lt;br clear="all"&gt;&lt;a href="http://lh6.ggpht.com/-jWsRCGesUB4/UKxdam8fqzI/AAAAAAAAA2U/FlEZtngCDd4/s1600-h/image%25255B62%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh3.ggpht.com/-xWFN7lxIhUc/UKxdbFUqzBI/AAAAAAAAA2c/Y2GxKFdnFBc/image_thumb%25255B30%25255D.png?imgmax=800" width="396" height="166"&gt;&lt;/a&gt;  &lt;li&gt;Once the namespace is activated. Click on Access Control Service in the top tool bar to manage the ACS namespace.&lt;br clear="all"&gt;&lt;a href="http://lh4.ggpht.com/-UKzCpeGjzis/UKxdbVD-hBI/AAAAAAAAA2k/x7pV5ji3E_c/s1600-h/image%25255B69%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh3.ggpht.com/-DJ-HkpWl9Q0/UKxdbz1jJ-I/AAAAAAAAA2s/5MOlh41orJk/image_thumb%25255B33%25255D.png?imgmax=800" width="104" height="74"&gt;&lt;/a&gt;  &lt;li&gt;Click on &lt;strong&gt;Application integration&lt;/strong&gt; link in the left pane. Then copy the URL to &lt;strong&gt;ws-Federation metadata&lt;/strong&gt;. You’ll need the URL in next section.&lt;br clear="all"&gt;&lt;a href="http://lh6.ggpht.com/-la8zPlvrCRc/UKxdcRx4IEI/AAAAAAAAA20/PlIqY8WnPdI/s1600-h/image%25255B74%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh6.ggpht.com/-MM--9D2Wlug/UKxdcyfebdI/AAAAAAAAA28/OafXyFoiGcQ/image_thumb%25255B36%25255D.png?imgmax=800" width="664" height="227"&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt; &lt;h3&gt;Configure Trust Relationship with ACS – ADFS Configuration&lt;/h3&gt; &lt;p&gt;Now it’s the fun part! Let’s configure ADFS as a trusted Identity Provider of your ACS namespace. The trust relationship is mutual, which means it needs to be configured on both ADFS side and ACS side. From ADFS side, we’ll configure ACS as a trusted relying party. And from ACS side, we’ll configure ADFS as a trusted identity provider. Let’s start with ADFS configuration.&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Back in &lt;strong&gt;AD FS Management snap-in&lt;/strong&gt;, click on &lt;strong&gt;Required: Add a trusted relying party&lt;/strong&gt; in the center pane.  &lt;li&gt;In &lt;strong&gt;Add Relying Party Trust Wizard&lt;/strong&gt;, click &lt;strong&gt;Start&lt;/strong&gt; to continue.  &lt;li&gt;Paste in the ACS ws-Federation metadata URL you got from your ACS namespace (see above steps), and click &lt;strong&gt;Next&lt;/strong&gt; to continue:&lt;br clear="all"&gt;&lt;a href="http://lh6.ggpht.com/-nwCPik3nCQQ/UKxdd5Ze6PI/AAAAAAAAA3E/YZt8Aj_lDZE/s1600-h/image%25255B80%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh6.ggpht.com/-2i7gRZl4vOQ/UKxdegs_8eI/AAAAAAAAA3M/TGVR15QVLYA/image_thumb%25255B40%25255D.png?imgmax=800" width="450" height="361"&gt;&lt;/a&gt;  &lt;li&gt;Keep clicking &lt;strong&gt;Next&lt;/strong&gt;, then finally &lt;strong&gt;Close&lt;/strong&gt; to complete the wizard.  &lt;li&gt;This brings up the claim rules window. Close it for now.  &lt;li&gt;Back in the main window, click on &lt;strong&gt;Trust Relationships&lt;/strong&gt;-&amp;gt;&lt;strong&gt;Claims Provider Trust&lt;/strong&gt; node. You’ll see &lt;strong&gt;Active Directory&lt;/strong&gt; listed in the center pane. Right-click and select &lt;strong&gt;Edit Claim Rules…&lt;/strong&gt;  &lt;li&gt;In the &lt;strong&gt;Edit Claim Rules for Active Directory&lt;/strong&gt; dialog, click &lt;strong&gt;Add Rule…&lt;/strong&gt; button.  &lt;li&gt;Select &lt;strong&gt;Send Group Membership as a Claim&lt;/strong&gt; template. Click &lt;strong&gt;Next&lt;/strong&gt;.  &lt;li&gt;On next screen, set the rule name as &lt;strong&gt;Role claim&lt;/strong&gt;. Pick the &lt;strong&gt;Manager&lt;/strong&gt; group using the &lt;strong&gt;Browse…&lt;/strong&gt; button. Pick &lt;strong&gt;Role&lt;/strong&gt; as output claim type. And set claim value to be &lt;strong&gt;Manager&lt;/strong&gt;. Then click &lt;strong&gt;Finish. &lt;/strong&gt;What we are doing here is to generate a &lt;strong&gt;&lt;em&gt;Role&lt;/em&gt;&lt;/strong&gt; claim with value &lt;strong&gt;&lt;em&gt;Manager&lt;/em&gt;&lt;/strong&gt; for all users in the &lt;strong&gt;&lt;em&gt;Manager&lt;/em&gt;&lt;/strong&gt; group in our AD.&lt;br clear="all"&gt;&lt;a href="http://lh6.ggpht.com/-UfdTQb0KI5A/UKxdfENFneI/AAAAAAAAA3Q/7M4OU7UDxWQ/s1600-h/image%25255B119%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh3.ggpht.com/-DrBTF0SpobU/UKxdfoF4iUI/AAAAAAAAA3Y/KSlt_2NCEww/image_thumb%25255B58%25255D.png?imgmax=800" width="411" height="333"&gt;&lt;/a&gt;  &lt;li&gt;Add another rule, and this time select &lt;strong&gt;Send LDAP Attribute as Claims&lt;/strong&gt; template.  &lt;li&gt;Set rule name as Name claim. Pick Active Directory as attribute store, and set up the rule to map Given-Name attribute to Name claim:&lt;br clear="all"&gt;&lt;a href="http://lh5.ggpht.com/-WEZWXfyiktU/UKxdgEYcjOI/AAAAAAAAA3k/8ddfpzYCyd8/s1600-h/image%25255B126%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh4.ggpht.com/-L4l0JNzS6cA/UKxdhA7Lg3I/AAAAAAAAA3s/r91z1ykHqrA/image_thumb%25255B61%25255D.png?imgmax=800" width="412" height="334"&gt;&lt;/a&gt;  &lt;li&gt;Back in the main window, click on &lt;strong&gt;Trust Relationships&lt;/strong&gt;-&amp;gt;&lt;strong&gt;Relying Party Trusts&lt;/strong&gt; node. You’ll see your ACS namespace listed in the center pane. Right-click on it and select &lt;strong&gt;Edit Claim Rules…&lt;/strong&gt;  &lt;li&gt;Add a new rule using &lt;strong&gt;Pass Through or Filter an Incoming Claim&lt;/strong&gt; template.  &lt;li&gt;Pass through all Role claims:&lt;br clear="all"&gt;&lt;a href="http://lh6.ggpht.com/-OxfQry_6WMA/UKxdhj1vv0I/AAAAAAAAA30/2RFuaN9S6Xo/s1600-h/image%25255B166%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh4.ggpht.com/-3bWu4QKYvok/UKxdiDC7s5I/AAAAAAAAA38/6etwgYbjn-8/image_thumb%25255B81%25255D.png?imgmax=800" width="396" height="321"&gt;&lt;/a&gt;  &lt;li&gt;Similarly, add another pass-through rule for &lt;strong&gt;&lt;em&gt;Name&lt;/em&gt;&lt;/strong&gt; claim.&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;Now our ADFS server is configured to trust our ACS namespace, and it will issue a &lt;strong&gt;&lt;em&gt;Name&lt;/em&gt;&lt;/strong&gt; claim and a &lt;strong&gt;&lt;em&gt;Role&lt;/em&gt;&lt;/strong&gt; claim for authenticated users.&lt;/p&gt; &lt;h3&gt;Configure Trust Relationship with ACS – ACS Configuration&lt;/h3&gt; &lt;p&gt;Now let’s configure the second part of the trust relationship.&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Download your ADFS metadata from &lt;strong&gt;https://&lt;em&gt;[your virtual machine name].&lt;/em&gt;cloudapp.net/FederationMetadata/2007-06/FederationMetadata.xml &lt;/strong&gt;(hint: use Chrome or Firefox to make download easier – ignore the certificate warnings).  &lt;li&gt;In ACS management portal, click on Identity providers link in the left pane. Then click on Add link:&lt;br clear="all"&gt;&lt;a href="http://lh4.ggpht.com/-fk3L_cg_iys/UKxdi-EYRtI/AAAAAAAAA4A/g1JYdgx6nBM/s1600-h/image%25255B130%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh6.ggpht.com/-z-wUpQhf2hc/UKxdjVj0aEI/AAAAAAAAA4M/UbbhE-dTJzA/image_thumb%25255B63%25255D.png?imgmax=800" width="414" height="206"&gt;&lt;/a&gt;  &lt;li&gt;On next screen, select &lt;strong&gt;WS-Federation identity provider&lt;/strong&gt;, then click &lt;strong&gt;Next:&lt;br clear="all"&gt;&lt;a href="http://lh3.ggpht.com/-WxcaEXjWxf0/UKxdj-SPYUI/AAAAAAAAA4U/yMby53KLCrg/s1600-h/image%25255B134%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh3.ggpht.com/-doReqfl_G7E/UKxdkXldiiI/AAAAAAAAA4c/H8loF6ynRtw/image_thumb%25255B65%25255D.png?imgmax=800" width="343" height="212"&gt;&lt;/a&gt;&lt;/strong&gt;  &lt;li&gt;On the next screen, enter a display name for the identity provider. Browse to the metadata file you’ve downloaded in step 1. Finally, set up a login link text, and click &lt;strong&gt;Save&lt;/strong&gt; to finish.&lt;br clear="all"&gt;&lt;a href="http://lh5.ggpht.com/-J1QBLFe5FKw/UKxdk80pmGI/AAAAAAAAA4g/XXX6zoW-vc4/s1600-h/image%25255B146%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh3.ggpht.com/-UUFYSHjexEc/UKxdlcbVvJI/AAAAAAAAA4o/eszGFSZLcF8/image_thumb%25255B71%25255D.png?imgmax=800" width="416" height="225"&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt; &lt;h3&gt;Test with a web site&lt;/h3&gt; &lt;p&gt;Now everything is up and running, let’s put them into work.&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Launch Visual Studio 2012.  &lt;li&gt;Create a new Web application using&lt;strong&gt; ASP.NET MVC 4 Web Application&lt;/strong&gt; – Internet Application template.  &lt;li&gt;Open _LoginPartial.cshtml and remove the following part. We don’t have required claims (name identifier and provider) to make this part work. For simplicity let’s just remove it&lt;pre class="csharpcode"&gt; @using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm" })) {
     @Html.AntiForgeryToken()
     &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;a&lt;/span&gt; &lt;span class="attr"&gt;href&lt;/span&gt;&lt;span class="kwrd"&gt;="javascript:document.getElementById('logoutForm').submit()"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Log off&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;a&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;li&gt;Right-click on the project and select &lt;strong&gt;Access and Identity…&lt;/strong&gt; menu. Not seeing the menu? Probably you don’t have the awesome extension installed yet. You can download it &lt;a href="http://visualstudiogallery.msdn.microsoft.com/e21bf653-dfe1-4d81-b3d3-795cb104066e"&gt;here&lt;/a&gt;. 
&lt;li&gt;In the &lt;strong&gt;Identity and Access&lt;/strong&gt; wizard, select Use the &lt;strong&gt;Windows Azure Access Control Service&lt;/strong&gt; option. If you haven’t used the wizard before, you’ll need to enter your ACS namespace name and management key. You can also click on the (Change…) link to switch to a different namespace if needed:&lt;br clear="all"&gt;&lt;a href="http://lh5.ggpht.com/-lLt3CRrk0SQ/UKxdl60t8PI/AAAAAAAAA4w/DoO87gsAFE8/s1600-h/image%25255B150%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh4.ggpht.com/-scIswyOC2D4/UKxdmYt6nQI/AAAAAAAAA44/_nwhVzWdJSs/image_thumb%25255B73%25255D.png?imgmax=800" width="357" height="325"&gt;&lt;/a&gt; 
&lt;li&gt;Where to get the ACS namespace management key, you ask? In ACS namespace management portal, click on the Management service link in the left pane, then click on ManagementClient link in the center pane:&lt;br clear="all"&gt;&lt;a href="http://lh6.ggpht.com/-7jXZrYH49AA/UKxdm6sSTeI/AAAAAAAAA5E/LvOZ-cy9t88/s1600-h/image%25255B154%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh4.ggpht.com/-ND6mTz0Qtx8/UKxdnh79qMI/AAAAAAAAA5I/-QTtiG3zfeQ/image_thumb%25255B75%25255D.png?imgmax=800" width="384" height="251"&gt;&lt;/a&gt; 
&lt;li&gt;On next screen, click on&lt;strong&gt; Symmetric Key&lt;/strong&gt; link, and finally in the next screen, copy the &lt;strong&gt;Key&lt;/strong&gt; field. 
&lt;li&gt;Where were we… right, the &lt;strong&gt;Identity and Access&lt;/strong&gt; wizard. Once you’ve entered your ACS information correctly, you’ll see the list of trusted identity providers populated. Select identity provider(s) you want to use. In this case we’ll select the single ADFS provider:&lt;br clear="all"&gt;&lt;a href="http://lh4.ggpht.com/-EvkdnWA8aM4/UKxdoE-vaFI/AAAAAAAAA5Q/GyRY6NOZTTk/s1600-h/image%25255B158%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh3.ggpht.com/-3xYI8O_Qocg/UKxdo4K3yyI/AAAAAAAAA5c/k1_tUIirKeA/image_thumb%25255B77%25255D.png?imgmax=800" width="446" height="50"&gt;&lt;/a&gt; 
&lt;li&gt;Click &lt;strong&gt;OK&lt;/strong&gt; to complete the wizard – that was easy, wasn’t it? 
&lt;li&gt;Now launch the application by pressing &lt;strong&gt;F5&lt;/strong&gt;. 
&lt;li&gt;You’ll see a certificate warning – that’s a good sign! This means the redirection to ADFS is working and the browser is complaining about our self-issued cert. Click &lt;strong&gt;Continue to this website&lt;/strong&gt; to continue. 
&lt;li&gt;You’ll be asked to log on to your domain. Type in your credential to log in (make sure you are using the right domain name). You can also use&lt;strong&gt;&lt;em&gt; [user]@[domain&lt;/em&gt;&lt;/strong&gt;] format, for example &lt;strong&gt;&lt;em&gt;joe@cloudapp.net&lt;/em&gt;&lt;/strong&gt;:&lt;br clear="all"&gt;&lt;a href="http://lh4.ggpht.com/-4PbA6rQNLF0/UKxdp2hQeyI/AAAAAAAAA5g/9ivbcyr830E/s1600-h/image%25255B170%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh3.ggpht.com/-WTtvpQGJv6s/UKxdqLfCutI/AAAAAAAAA5s/tC0zgYCF_P8/image_thumb%25255B83%25255D.png?imgmax=800" width="303" height="267"&gt;&lt;/a&gt; 
&lt;li&gt;And it works just as designed:&lt;br clear="all"&gt;&lt;a href="http://lh6.ggpht.com/-xFQaOUOrqz8/UKxdqnfz51I/AAAAAAAAA50/h3iD3csJW4g/s1600-h/image%25255B161%25255D.png"&gt;&lt;img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://lh6.ggpht.com/-q4QyxLvA-8I/UKxdrg4bd4I/AAAAAAAAA58/A4ZJmCAfRiM/image_thumb%25255B78%25255D.png?imgmax=800" width="244" height="77"&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;h3&gt;Role-based security&lt;/h3&gt;
&lt;p&gt;That was exciting, wasn’t it? Now let’s have more fun. In this part we’ll restrict access to the &lt;strong&gt;&lt;em&gt;About()&lt;/em&gt;&lt;/strong&gt; method of home controller to &lt;strong&gt;&lt;em&gt;Manager&lt;/em&gt;&lt;/strong&gt; role only.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open &lt;strong&gt;&lt;em&gt;HomeController.cs&lt;/em&gt;&lt;/strong&gt; and decorate the &lt;strong&gt;&lt;em&gt;About()&lt;/em&gt;&lt;/strong&gt; method:&lt;pre class="csharpcode"&gt;&lt;font style="background-color: #ffff00"&gt;[Authorize(Roles=&lt;span class="str"&gt;"Manager"&lt;/span&gt;)]
&lt;/font&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; ActionResult About()
{
    ViewBag.Message = &lt;span class="str"&gt;"Your app description page."&lt;/span&gt;;
    &lt;span class="kwrd"&gt;return&lt;/span&gt; View();
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;li&gt;Launch the app, log in as joe, who’s a Manager. Click on &lt;strong&gt;About&lt;/strong&gt; link. Everything is good. 
&lt;li&gt;Now restart the app, log in as a Staff user – access denied! A-xcellent.&lt;br clear="all"&gt;&lt;a href="http://lh6.ggpht.com/-jfOWZV-JwRc/UKxdsU8sEQI/AAAAAAAAA6E/DkNhy9edH3w/s1600-h/image%25255B173%25255D.png"&gt;&lt;img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://lh4.ggpht.com/-blkEPoIKWVM/UKxdtC_bapI/AAAAAAAAA6M/ahEk5dKLiNk/image_thumb%25255B84%25255D.png?imgmax=800" width="244" height="90"&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;There you go! An Active Directory, a Domain Controller, an ADFS server, all on Windows Azure IaaS. And the ADFS server is configured as a trusted identity provider to our ACS namespace, which in turn provides claim-based authentication to our web application who uses role-based security! That’s really fun!&lt;/p&gt;
&lt;h3&gt;Bonus Item&lt;/h3&gt;
&lt;p&gt;Still reading? Thank you! Now you deserve a little bonus. Remember the log on dialog in above test? That’s not very nice looking. Follow &lt;a href="http://haishibai.blogspot.com/2012/05/configure-adfs-to-show-login-page.html"&gt;this link&lt;/a&gt; to learn a little trick to bring up a login form instead.&lt;/p&gt;  &lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/jEGxC0D4F40" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/8768130304324198622/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2012/11/complete-walkthrough-setting-up-adfs-20.html#comment-form" title="11 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/8768130304324198622?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/8768130304324198622?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/jEGxC0D4F40/complete-walkthrough-setting-up-adfs-20.html" title="Complete walkthrough: Setting up a ADFS 2.0 Server on Windows Azure IaaS and Configuring it as an Identity Provider in Windows Azure ACS" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/-64zywEqsdNI/UKxdJTTSWPI/AAAAAAAAAyY/0ipOKq2xTvI/s72-c/image_thumb%25255B3%25255D.png?imgmax=800" height="72" width="72" /><thr:total>11</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2012/11/complete-walkthrough-setting-up-adfs-20.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUMMQXkyeip7ImA9WhNQE0s.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-4690167337855336632</id><published>2012-11-19T14:18:00.001-08:00</published><updated>2012-11-19T14:18:00.792-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-11-19T14:18:00.792-08:00</app:edited><title>Walkthrough: Using New Relic to monitor your Windows Azure Cloud Services</title><content type="html">&lt;p&gt;With the release of &lt;a href="http://www.windowsazure.com/en-us/store/overview/"&gt;Windows Azure Store&lt;/a&gt;, more and more powerful SaaS solutions can be easily incorporated into Windows Azure’s ecosystem, providing tremendous opportunities for service providers to utilize these new capabilities in their services and applications. In &lt;a href="http://channel9.msdn.com/Events/Build/2012/1-002"&gt;BUILD 2012 Azure keynote&lt;/a&gt; we demonstrated how you can use &lt;a href="http://newrelic.com/"&gt;New Relic&lt;/a&gt; to instrument and monitor your Cloud Services. In this post I’ll walk you through the configuration steps behind the science that made the demo possible. &lt;/p&gt; &lt;h3&gt;Setting up the Cloud Service&lt;/h3&gt; &lt;p&gt;In this part we’ll create a brand-new Cloud Service that contains some pages and a couple of Web API methods. Of course you can start with you own service, but if you are trying this for the first time, using a dummy service is probably a better idea. &lt;/p&gt; &lt;ol&gt; &lt;li&gt;Create a new Cloud Service with a ASP.Net MVC 4 Web Role (using Internet Application template).&lt;/li&gt; &lt;li&gt;Add a new Web API controller to the Web Role using &lt;strong&gt;API controller with empty read/write actions&lt;/strong&gt;.&lt;/li&gt;&lt;/ol&gt; &lt;h3&gt;Provisioning New Relic service&lt;/h3&gt; &lt;p&gt;In this part we’ll provision a new New Relic account using &lt;a href="http://manage.windowsazure.com/"&gt;Windows Azure Management Portal&lt;/a&gt;. &lt;/p&gt; &lt;ol&gt; &lt;li&gt;Log on to &lt;a href="http://manage.windowsazure.com/"&gt;Windows Azure Management Portal&lt;/a&gt;. &lt;/li&gt; &lt;li&gt;Use NEW-&amp;gt;Store to launch Windows Azure Store wizard.&lt;/li&gt; &lt;li&gt;Select New Relic, then click right arrow to continue&lt;br clear="all"&gt;&lt;a href="http://lh4.ggpht.com/-wzoM6wRHSpA/UKqv7k-3NPI/AAAAAAAAAvg/pPTGw1swNaU/s1600-h/image%25255B5%25255D.png"&gt;&lt;img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://lh5.ggpht.com/-QjRUi6Lx8JU/UKqv7_c7PHI/AAAAAAAAAvo/oOGeGkYiMDc/image_thumb%25255B3%25255D.png?imgmax=800" width="413" height="272"&gt;&lt;/a&gt;&lt;/li&gt; &lt;li&gt;Select a package you want to use (you can start with the free package). Pick a name for your subscription, and then click right arrow to continue&lt;br clear="all"&gt;&lt;a href="http://lh4.ggpht.com/-NiFBL_cmfu8/UKqv8cCkTZI/AAAAAAAAAvw/ML6z5Qs7hQA/s1600-h/image%25255B9%25255D.png"&gt;&lt;img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://lh6.ggpht.com/-LjyyJ4opGM0/UKqv8z-sWvI/AAAAAAAAAv4/GNOsTooHk74/image_thumb%25255B5%25255D.png?imgmax=800" width="419" height="277"&gt;&lt;/a&gt;&lt;/li&gt; &lt;li&gt;After reviewing summary, click Purchase to complete the wizard&lt;br clear="all"&gt;&lt;a href="http://lh6.ggpht.com/-V3TeF8WeRnY/UKqv9x5QmiI/AAAAAAAAAwA/IrR8FqJOr5M/s1600-h/image%25255B13%25255D.png"&gt;&lt;img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://lh4.ggpht.com/-tTIRlhrA_AY/UKqv-FhFNHI/AAAAAAAAAwI/pg9a_tfg78E/image_thumb%25255B7%25255D.png?imgmax=800" width="423" height="278"&gt;&lt;/a&gt;&lt;/li&gt; &lt;li&gt;After the service is provisioned, you can get your &lt;strong&gt;API KEY&lt;/strong&gt; and &lt;strong&gt;APPLICATION KEY&lt;/strong&gt; by click on &lt;strong&gt;CONNECTION INFO&lt;/strong&gt; icon.&lt;/li&gt;&lt;/ol&gt; &lt;h3&gt;Configuring New Relic Agent&lt;/h3&gt; &lt;p&gt;To allow New Relic to collect performance metrics, you’ll need to deploy a New Relic agent along with your service. Fortunately this is very easy using New Relic NuGet package.&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Add NewRelicWindowsAzure (New Relic x64 for Windows Azure) NuGet package to the Web Role.&lt;/li&gt; &lt;li&gt;The install wizard will ask for your license key. Paste in the license key you get in step 6 of above section&lt;br clear="all"&gt;&lt;a href="http://lh4.ggpht.com/-mRR9ZbzOhxk/UKqv--jucKI/AAAAAAAAAwQ/dOSdWGZ1qpw/s1600-h/image%25255B16%25255D.png"&gt;&lt;img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://lh4.ggpht.com/-sGXzybdToEI/UKqv_lXvOWI/AAAAAAAAAwY/E0Jh2gNdrrk/image_thumb%25255B8%25255D.png?imgmax=800" width="244" height="164"&gt;&lt;/a&gt;&lt;/li&gt; &lt;li&gt;Then the wizard will ask you for an application name. This name will be used in your New Relic portal to visually identify your application. &lt;br clear="all"&gt;&lt;a href="http://lh3.ggpht.com/-D8agxIaRqCI/UKqv_9q1CRI/AAAAAAAAAwg/ZdWk_SK0E0A/s1600-h/image%25255B19%25255D.png"&gt;&lt;img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://lh3.ggpht.com/-P370FlnkDis/UKqwAfx7BAI/AAAAAAAAAwo/Rh31tgYgadY/image_thumb%25255B9%25255D.png?imgmax=800" width="244" height="164"&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;After the wizard completes you can see a &lt;strong&gt;newrelic.cmd&lt;/strong&gt; file, which is registered as a startup task that installs &lt;strong&gt;NewRelicAgent_x64_&lt;em&gt;{version}&lt;/em&gt;.msi&lt;/strong&gt; to your host machine. &lt;/p&gt; &lt;h3&gt;Give it a try!&lt;/h3&gt; &lt;p&gt;That’s all you need to do to get started! Now &lt;strong&gt;publish your Cloud Service to Windows Azure&lt;/strong&gt;, click around to generate some requests, and wait for a couple of minutes for your application to show up in New Relic portal. To access the New Relic portal from Windows Azure Management Portal, click on &lt;strong&gt;MANAGE &lt;/strong&gt;icon of your New Relic subscription:&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-EmM-ZnSBWaA/UKqwAha0OUI/AAAAAAAAAww/nlZWClRzMu0/s1600-h/image%25255B23%25255D.png"&gt;&lt;img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://lh4.ggpht.com/-1acOo09SFQc/UKqwBIv5xPI/AAAAAAAAAw4/-YbieGMhFtg/image_thumb%25255B11%25255D.png?imgmax=800" width="351" height="235"&gt;&lt;/a&gt;&lt;/p&gt; &lt;h3&gt;Adding Browser Tracing&lt;/h3&gt;      &lt;p&gt;New Relic agent reports server-side metrics such as app server response time and throughputs etc. To measure client-side metrics such as client perceived response time, you’ll need to enable browser tracing, which will inject some JavaScript snippets to your web page to report performance data back to New Relic. You can use New Relic API methods, NewRelic.Api.Agent.NewRelic.GetBrowserTimingHeader() and NewRelic.Api.Agent.NewRelic.GetBrowserTimingFooter() to generate these snippets. For example, in my ASP.NET MVC 4 &lt;strong&gt;_layout.cshtml&lt;/strong&gt; page, I added the following calls:&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;!&lt;/span&gt;&lt;span class="html"&gt;DOCTYPE&lt;/span&gt; &lt;span class="attr"&gt;html&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;html&lt;/span&gt; &lt;span class="attr"&gt;lang&lt;/span&gt;&lt;span class="kwrd"&gt;="en"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    @Html.Raw(NewRelic.Api.Agent.NewRelic.GetBrowserTimingHeader())
    ...
    @Html.Raw(NewRelic.Api.Agent.NewRelic.GetBrowserTimingFooter())
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;html&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/p&gt;
&lt;p&gt;Because the layout page is shared among all pages, I can trace into all page requests in this way.&lt;/p&gt;
&lt;h3&gt;Trace Web API&lt;/h3&gt;
&lt;p&gt;The above method for browser tracing only works for web pages that use &lt;strong&gt;_layout.cshtml&lt;/strong&gt; page. What about API controllers, or WCF services that don’t have a frontend? You can define custom instrumentations easily with New Relic as well. The following is an example to trace &lt;strong&gt;Get()&lt;/strong&gt; method of my API controller:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Add a new file, named &lt;strong&gt;CustomInstrumentation.xml&lt;/strong&gt;, to the root folder of your Web Role project. In the following file, I’m instructing New Relic instrumentation to trace Get method of my &lt;strong&gt;APIController&lt;/strong&gt; defined in my web project&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="html"&gt;xml&lt;/span&gt; &lt;span class="attr"&gt;version&lt;/span&gt;&lt;span class="kwrd"&gt;="1.0"&lt;/span&gt; &lt;span class="attr"&gt;encoding&lt;/span&gt;&lt;span class="kwrd"&gt;="utf-8"&lt;/span&gt; ?&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;extension&lt;/span&gt; &lt;span class="attr"&gt;xmlns&lt;/span&gt;&lt;span class="kwrd"&gt;="urn:newrelic-extension"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;instrumentation&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;tracerFactory&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;match&lt;/span&gt; &lt;span class="attr"&gt;assemblyName&lt;/span&gt;&lt;span class="kwrd"&gt;="NewRelicSample.Web"&lt;/span&gt; &lt;span class="attr"&gt;className&lt;/span&gt;&lt;span class="kwrd"&gt;="NewRelicSample.Web.Controllers.APIController"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;exactMethodMatcher&lt;/span&gt; &lt;span class="attr"&gt;methodName&lt;/span&gt;&lt;span class="kwrd"&gt;="Get"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;match&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;tracerFactory&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;instrumentation&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;extension&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/li&gt;
&lt;li&gt;Uncomment the following line from newrelic.cmd, and redeploy your service&lt;pre class="csharpcode"&gt;copy /y CustomInstrumentation.xml %NR_HOME%\extensions &amp;gt;&amp;gt; d:\nr.log&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;You can also directly call into New Relic API from any classes, such as a WCF service implementation, to trance performance data, as shown in the following example:&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; async Task&amp;lt;HttpResponseMessage&amp;gt; Post()
{
    &lt;font style="background-color: #ffff00"&gt;NewRelic.Api.Agent.NewRelic.SetTransactionName(&lt;span class="str"&gt;"API"&lt;/span&gt;, &lt;span class="str"&gt;"Video Creation"&lt;/span&gt;);&lt;/font&gt;

    Stopwatch watch = Stopwatch.StartNew();
     … doing stuff …
     watch.Stop();

    &lt;font style="background-color: #ffff00"&gt;NewRelic.Api.Agent.NewRelic.RecordResponseTimeMetric(&lt;span class="str"&gt;"Video Creation"&lt;/span&gt;, watch.ElapsedMilliseconds);&lt;/font&gt;
     &lt;span class="kwrd"&gt;return&lt;/span&gt; Request.CreateResponse(HttpStatusCode.Created, video);
}&lt;/pre&gt;
&lt;h3&gt;Screenshots&lt;/h3&gt;
&lt;p&gt;Here are some screenshots highlighting just a few interesting features of New Relic.&lt;/p&gt;
&lt;p&gt;&lt;u&gt;Map view&lt;/u&gt; gives you a visual presentation of external service dependencies. In the following sample you can see my service depends on Twitter, Windows Azure Table Storage, as well as Windows Azure ACS. You can drill into each service to get more details as well. &lt;/p&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/p&gt;
&lt;p&gt;&lt;a href="http://lh6.ggpht.com/-0agMM7ZQxTc/UKqwBkc9n-I/AAAAAAAAAxA/3_1AhI_GFnc/s1600-h/image%25255B27%25255D.png"&gt;&lt;img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://lh5.ggpht.com/-7F56dBXpzII/UKqwCNLCj6I/AAAAAAAAAxI/n7F7_HCluEA/image_thumb%25255B13%25255D.png?imgmax=800" width="472" height="236"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;u&gt;Geographic view&lt;/u&gt; gives you an intuitive representation of client perceived response times across the states or around the globe. &lt;/p&gt;
&lt;p&gt;&lt;a href="http://lh6.ggpht.com/-ITCiMDRioKE/UKqwCo3dRLI/AAAAAAAAAxQ/xYO1LXqEYmY/s1600-h/image%25255B31%25255D.png"&gt;&lt;img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://lh3.ggpht.com/-v-SQoA24Q-I/UKqwDVvPzcI/AAAAAAAAAxY/6iGgKm8P17Q/image_thumb%25255B15%25255D.png?imgmax=800" width="473" height="258"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;u&gt;Detailed transaction view&lt;/u&gt; allows you to drill down all the way to call stacks and even SQL statements so you can easily identify bottlenecks across different application layers. &lt;/p&gt;
&lt;p&gt;&lt;a href="http://lh6.ggpht.com/-FTBggY54sBg/UKqwDzXYnQI/AAAAAAAAAxg/gYT_fdkEs2o/s1600-h/image%25255B35%25255D.png"&gt;&lt;img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://lh4.ggpht.com/-1sD94ZAY62g/UKqwEUdAmsI/AAAAAAAAAxo/RjpnDYuBDHo/image_thumb%25255B17%25255D.png?imgmax=800" width="479" height="325"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Have a large system? Trace your &lt;u&gt;Key Transactions&lt;/u&gt; in a separate view to keep a close eye on key components of your system.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://lh5.ggpht.com/-Gwg7AiGNdcA/UKqwFJJGcsI/AAAAAAAAAxw/z47TQ7Sr-Is/s1600-h/image%25255B39%25255D.png"&gt;&lt;img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://lh6.ggpht.com/-Ko3v6mJJuM4/UKqwFt1tY3I/AAAAAAAAAx4/N6Jrn-tuoBg/image_thumb%25255B19%25255D.png?imgmax=800" width="486" height="255"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;In this walkthrough we went through all the steps necessary to utilize New Relic to monitor your Cloud Service performance from both server side and client side. Ready to get started? &lt;a href="http://www.windowsazure.com/en-us/pricing/free-trial/?WT.mc_id=A6D9C2617"&gt;&lt;strong&gt;&lt;font size="4"&gt;Follow this link&lt;/font&gt;&lt;/strong&gt;&lt;/a&gt; to receive your &lt;strong&gt;&lt;font color="#008080" size="4"&gt;free&lt;/font&gt;&lt;/strong&gt; Windows Azure trail subscription with &lt;strong&gt;&lt;font color="#008080" size="4"&gt;free&lt;/font&gt;&lt;/strong&gt; New Relic service offering!&lt;/p&gt;  &lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/ktKowyIPxb4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/4690167337855336632/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2012/11/walkthrough-using-new-relic-to-monitor.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/4690167337855336632?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/4690167337855336632?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/ktKowyIPxb4/walkthrough-using-new-relic-to-monitor.html" title="Walkthrough: Using New Relic to monitor your Windows Azure Cloud Services" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/-QjRUi6Lx8JU/UKqv7_c7PHI/AAAAAAAAAvo/oOGeGkYiMDc/s72-c/image_thumb%25255B3%25255D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2012/11/walkthrough-using-new-relic-to-monitor.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUYHQHY5cCp7ImA9WhNRE04.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-8273610295109239309</id><published>2012-11-06T16:47:00.001-08:00</published><updated>2012-11-07T17:12:11.828-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-11-07T17:12:11.828-08:00</app:edited><title>Play fireworks together! Process of building a SignalR sample</title><content type="html">&lt;p&gt;In my &lt;a href="http://channel9.msdn.com/Events/Build/2012/3-025"&gt;BUILD 2012 session&lt;/a&gt; on Cloud Services, I mentioned a fireworks sample but didn’t get time to show it. It is an end-to-end sample showcasing how to use SignalR to build massive interactive web applications. As promised, I’m sharing the source, as well as some of “Performance by Design” thinking that I went through building the sample. I hope you can pick up some practical SignalR tricks and tips here as well as some hints on designing an application with performance considerations. I have a version deployed at &lt;a href="http://firework.cloudapp.net"&gt;http://firework.cloudapp.net&lt;/a&gt;. This is a two-instance deployment with a Service Bus backplane, so it should hold up for hundreds of concurrent fireworks. The application works on your PCs, Macs (with HTML 5 enabled browsers) as well as mobile devices such as Surface, WP, iPhone and iPad. I haven’t tested on Android devices, though. Note that because the code does intense graphics, your mobile devices may have a hard time keep up with rendering, especially when there are lots of fireworks. My Windows Phone 7&amp;nbsp; could handle about 500 concurrent fireworks.&lt;/p&gt; &lt;h3&gt;&lt;font style="font-weight: bold"&gt;The Application&lt;/font&gt;&lt;/h3&gt; &lt;p&gt;The idea is simple – to allow many users to play virtual fireworks together over the Internet. It’s a single page web application written in JavaScript and HTML 5. The application supports two firework types – simple and complex, but it can be extended by providing additional subclasses of &lt;strong&gt;Firework&lt;/strong&gt; class. In addition, you can pick from several different colors (include a random multi-color option) as well as how trails of sparks are rendered. &lt;/p&gt; &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-LjuUxSmnUBg/UJmvo0FfTrI/AAAAAAAAAus/O7egdClOmMY/s1600-h/image%25255B3%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh4.ggpht.com/-cPFN57qic8M/UJmvpuK49dI/AAAAAAAAAu0/HT4rNOLGBfE/image_thumb%25255B1%25255D.png?imgmax=800" width="519" height="313"&gt;&lt;/a&gt;&lt;/p&gt; &lt;h3&gt;&lt;/h3&gt; &lt;h3&gt;&lt;font style="font-weight: bold"&gt;The Code&lt;/font&gt;&lt;/h3&gt; &lt;p&gt;Complete code of the application can be found at &lt;a href="https://github.com/WindowsAzure-Samples/Fireworks"&gt;GitHub&lt;/a&gt;. Here are some brief descriptions that may help you to understand the code. There are comments inline with the code as well.&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Everything interesting is in the default Home view (Views/Home/Index.cshtml).  &lt;li&gt;&lt;strong&gt;Firework&lt;/strong&gt; is the base class that implement basic behaviors of a firework. It defines a series of &lt;strong&gt;Spark&lt;/strong&gt;s, which in turn contain a list of &lt;strong&gt;Trail&lt;/strong&gt; points.  &lt;li&gt;&lt;strong&gt;FireworkPatternFactory&lt;/strong&gt; is a class that helps to reduce amount of calculations. See the last section for more details.  &lt;li&gt;&lt;strong&gt;SimpleFirework&lt;/strong&gt; and &lt;strong&gt;ComplexFirework&lt;/strong&gt; are two subclasses of &lt;strong&gt;Firework&lt;/strong&gt;. If you want to implement additional firework types, you’ll need to initialize the &lt;strong&gt;Spark&lt;/strong&gt;s in your constructor and implement &lt;strong&gt;updateSparks()&lt;/strong&gt; to update the sparks. &lt;strong&gt;Trail&lt;/strong&gt;s are automatically maintained by the base class.  &lt;li&gt;Rendering routine is the &lt;strong&gt;updateCanvas()&lt;/strong&gt; method, which is set on a timer with 50ms intervals.&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;&lt;font style="font-weight: bold"&gt;SignalR Tricks &amp;amp; Tips&lt;/font&gt;&lt;/h3&gt; &lt;p&gt;This post is not an introduction to SignalR. Instead, I’ll provide a couple of quick tricks &amp;amp; tips that you can use when implementing your own SignalR application on Windows Azure.&lt;/p&gt; &lt;h4&gt;&lt;u&gt;&lt;font style="font-weight: bold"&gt;Enable Service Bus backplane&lt;/font&gt;&lt;/u&gt;&lt;/h4&gt; &lt;p&gt;SignalR Service Bus backplane allows you to scale SignalR hubs to multiple instances. You’ll need to enable the backplane if your Cloud Service will have multiple instances.&lt;/p&gt; &lt;ol&gt; &lt;li&gt;You’ll need to add a reference to &lt;strong&gt;Microsoft ASP.NET SignalR ServiceBus Libraries&lt;/strong&gt; NuGet package.  &lt;li&gt;Initialize the backplane in Global.asax.cs&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; topicPathPrefix = &lt;span class="str"&gt;"firework"&lt;/span&gt;;

&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Application_Start()
{
    ...
    GlobalHost.DependencyResolver.UseServiceBus(
                    ConfigurationManager.AppSettings[&lt;span class="str"&gt;"Microsoft.ServiceBus.ConnectionString"&lt;/span&gt;], 
                          partitionCount: 5, 
                          nodeCount: getRoleInstanceCount(), 
                          nodeId: getRoleInstanceNumber(), topicPrefix: topicPathPrefix);
}

&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; getRoleInstanceCount()
{
    &lt;span class="kwrd"&gt;return&lt;/span&gt; RoleEnvironment.CurrentRoleInstance.Role.Instances.Count;
}
&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; getRoleInstanceNumber()
{            
    var roleInstanceId = RoleEnvironment.CurrentRoleInstance.Id;
    var li1 = roleInstanceId.LastIndexOf(&lt;span class="str"&gt;"."&lt;/span&gt;);
    var li2 = roleInstanceId.LastIndexOf(&lt;span class="str"&gt;"_"&lt;/span&gt;);
    var roleInstanceNo = roleInstanceId.Substring(Math.Max(li1, li2) + 1);
    &lt;span class="kwrd"&gt;return&lt;/span&gt; Int32.Parse(roleInstanceNo);
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;Note the &lt;strong&gt;nodeCount&lt;/strong&gt; should be consistent with number of your role instances, and &lt;strong&gt;nodeId&lt;/strong&gt; should be unique within the cluster.&lt;/p&gt;
&lt;h4&gt;&lt;u&gt;&lt;font style="font-weight: bold"&gt;Enable WebSockets &lt;/font&gt;&lt;/u&gt;&lt;/h4&gt;
&lt;p&gt;At the time when this post is written, WebSockets is not enabled by default on osFamily 3. However you can easily do this via a startup script: &lt;pre class="csharpcode"&gt;%SystemRoot%\system32\dism.exe /online /enable-feature /featurename:IIS-WebSockets&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;


&lt;p&gt;You don’t have to do this – SignalR will fall back to other means of establishing connections. But WebSockets is preferred. In addition, you need to set runtime context to &lt;strong&gt;elevated&lt;/strong&gt; to make this work. The operation may takes a long time. I’d suggest to make it a background task so that your deployments can go through faster (and continue to work even if the command fails).&lt;/p&gt;
&lt;h4&gt;&lt;font style="font-weight: bold"&gt;&lt;u&gt;Service Bus Connection String&lt;/u&gt;&lt;/font&gt;&lt;/h4&gt;
&lt;p&gt;At the time when this post is written, you need to make sure your service bus connection string contains token provider type:&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;key&lt;/span&gt;&lt;span class="kwrd"&gt;="Microsoft.ServiceBus.ConnectionString"&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="Endpoint=sb://[your namespace].servicebus.&lt;/span&gt;&lt;/pre&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;         windows.net/;SharedSecretIssuer=owner;SharedSecretValue=[your secret key]&lt;font style="background-color: #ffff00"&gt;;provider=SharedSecret&lt;/font&gt;"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;


&lt;h3&gt;Performance by Design&lt;/h3&gt;
&lt;p&gt;This is a very “busy” application – on one hand it needs to sync its states with hundreds of other clients; and on the other hand it needs to render thousands of elements on the screen at a very fast pace. To ensure performance, during the designing phase I paid extra attention to these two elements: Reduce amount of information that needs to be synced; Reduce amount of calculation. Here are processes of some design decisions I made along the way. I hope this can provide some ideas to help you to design your first interactive web application.&lt;/p&gt;
&lt;h4&gt;&lt;/h4&gt;
&lt;h4&gt;&lt;font style="font-weight: bold"&gt;What to sync&lt;/font&gt;&lt;/h4&gt;
&lt;p&gt;&lt;u&gt;iteration 1&lt;/u&gt;&lt;/p&gt;
&lt;p&gt;When you render a beautiful firework, you need to know the positions of every single spark as well as its trail. If you want to directly sync all the information the amount of traffic will be considerable – each complex firework contains 48 sparks with 240 trail points – that’s near 300 coordinates, along with color of each spark, to be synced. Now multiply that by 100 users, at every 50 milliseconds. That’s craziness.&amp;nbsp; We need a much simpler representation of a firework. And here’s the abstraction I use – a firework is described by a base position (where user has clicked), a base color, a type (simple or complex), a trail type (dot, line, or none), and a phase. Note I’m cheating a little here – for multi-color fireworks I’m not going to sync color of each spark. No one would care about (or event notice) they have different colors - knowing when and how to cheat is important ;). The phase is an interesting concept – basically when a firework is ignited it’s at phase 0, and it goes through all the phases till it burns out. The program is designed in the way that you can paint a firework of any phase at any time – you don’t have to start with phase 0. This allows me to sync firework states at any time.&lt;/p&gt;
&lt;p&gt;&lt;u&gt;iteration 2&lt;/u&gt;&lt;/p&gt;
&lt;p&gt;That’s much better, but can we do even better? Obviously we can compress the data, such as encoding color, type, and trail to a single byte. But there will still be a lot of data to sync. Eventually, I decided to &lt;u&gt;sync the actions&lt;/u&gt; instead of &lt;u&gt;sync the states&lt;/u&gt;. Generally speaking, when you sync among distributed systems, syncing the states is much more reliable than syncing the actions, because with a single action missing, duplicated, or out of place, the whole synchronization is messed up. However, for this particular application, missing some of the actions – and there’s only one “add” action – is not that terrible. So some clients may miss a firework or two -- not a big deal. And it’s also not critical to make sure all pixels on the screens are in sync either. Hence syncing the actions is a very reasonable choice in this case, and it dramatically reduces the amount of data to be transferred. All clients maintain their states separately, and they try to perform the same actions by best attempts. For a firework application that’s acceptable.&lt;/p&gt;
&lt;h4&gt;&lt;font style="font-weight: bold"&gt;Reduce calculation&lt;/font&gt;&lt;/h4&gt;
&lt;p&gt;&lt;u&gt;trajectory&lt;/u&gt;&lt;/p&gt;
&lt;p&gt;When fireworks explode we need to calculate trajectories of the sparks. In order to avoid&amp;nbsp; repetitive SIN/COS calculations, I pre-calculated points of an expanding circle and saved all the points in memory. Then, when I need to plot a spark (or its trail) on screen, I simply lookup corresponding values by phases. Acceleration of gravity is kept to a separate pre-calculated array so I can adjust and apply gravity effects independently from the perfect explosion circle.&lt;/p&gt;
&lt;p&gt;&lt;u&gt;trail&lt;/u&gt;&lt;/p&gt;
&lt;p&gt;Drawing a perfect trail of expanding circle (the spark) takes some non-trivial calculations, which is not the price I want to pay. Instead of calculating perfect polygons to compose the trail, I chose to use approximate bands that connect centers of the trail points. This is a much simpler calculation and the result is very reasonable. In the following diagram, the red area shows approximation bands, while the yellow area shows perfect trail polygons. You can see the algorithm is biased vertically so when the sparks fall the trails look more spectacular (again, knowing when and how to cheat is important).&lt;/p&gt;
&lt;p&gt;&lt;a href="http://lh4.ggpht.com/-zu_MqbIo48E/UJmvqhQwLTI/AAAAAAAAAu8/5ARm_DLE0Kg/s1600-h/image%25255B8%25255D.png"&gt;&lt;img title="image" 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="image" src="http://lh4.ggpht.com/-6WsEmQWAKbQ/UJmvrYSp7II/AAAAAAAAAvE/ML8VOvwfv8g/image_thumb%25255B4%25255D.png?imgmax=800" width="307" height="180"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;What’s left&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;A better, stretchable UI. 
&lt;li&gt;Explosion effect for complex firework isn’t that nice. Because of the 3D perspective in real life, the center should not be hollow but filled with sparks that are coming toward you. A pre-calculated 3D projection is needed, as well as the spark coordinates to be extended to 3 dimensions. It’s not a terribly hard change but needs a little 3D geometry. &lt;/li&gt;&lt;/ul&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Here you go, a SingalR firework program that I coded up in about 3 days. I hope you can get some useful tips setting up the Service Bus backplane. If you had some fun playing with the sample that’s even better! And if you are inspired to build much, much better interactive web applications, my goal here is achieved :).&lt;/p&gt;  &lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/6FmWXaCXpG8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/8273610295109239309/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2012/11/play-fireworks-together-process-of.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/8273610295109239309?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/8273610295109239309?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/6FmWXaCXpG8/play-fireworks-together-process-of.html" title="Play fireworks together! Process of building a SignalR sample" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/-cPFN57qic8M/UJmvpuK49dI/AAAAAAAAAu0/HT4rNOLGBfE/s72-c/image_thumb%25255B1%25255D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2012/11/play-fireworks-together-process-of.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DE8MSX84eCp7ImA9WhJaF0k.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-1027834520962924091</id><published>2012-10-08T18:41:00.001-07:00</published><updated>2012-10-08T18:41:28.130-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-10-08T18:41:28.130-07:00</app:edited><title>Recipes for Multi-tenant Cloud Service Design – Recipe 2: Centralized SSL Certificate Management</title><content type="html">&lt;p&gt;This is the second part of my blog series on multi-tenant Cloud service design. Each of the posts has two parts – discussions on Multi-tenancy and&amp;nbsp; recipes to address specific challenges. When I first planned for the series the discussion parts were merely around particular problems, but somehow they grew into full-sized beasts by themselves.&amp;nbsp; So, if you want to get to the recipes directly, you can safely do so. And if you just want to read higher-level discussions, you can skip the recipe parts without getting disconnected from post to post. On the other hand, if you want to get both the big picture as well as practical tactics to make the picture reality along the way, read through all texts :).&amp;nbsp; Here’s the first part:&lt;/p&gt; &lt;p&gt;&lt;a href="http://haishibai.blogspot.com/2012/10/recipes-for-multi-tenant-cloud-service.html"&gt;Recipe 1: Throttling by Tenants Using Multi-site Cloud Services and IIS 8 CPU Throttling&lt;/a&gt;&lt;/p&gt; &lt;h3&gt;More about Multi-tenancy&lt;/h3&gt; &lt;p&gt;In the previous article I listed some of the challenges an ISV has to face when designing for multi-tenant Cloud Services. Before we jump into any specifics again, I’d like to share some thoughts on different strategies of getting customers to the cloud. Many ISVs realize the benefits of IaaS and want to migrate their customers to the low cost, highly reliable hosting environment. One intuitive strategy to do so is to have dedicated resource(s) for each customer. This design is also referred as single-tenant, multi-instance architecture.&amp;nbsp; At the surface this strategy has some very tempting benefits, among which code reuse is probably the dominating one. Because customers are still isolated to dedicated resources, the existing software should work as-it-is, shouldn’t it? Well, the bad news is, it’s rarely the case. As I mentioned in the last post, moving to the cloud is a major shift in business model and should not been taken lightly.&amp;nbsp; Business aspects aside, such strategy is not immune to many of the technical challenges I mentioned in previous post such as authentication, authorization and performance. Managing a multi-instance environment can be challenging as well. Because the instances are independent from each other, chances are software updates and database patches need to be applied individually. This increased complexity makes service management and upgrades difficult. In addition, isolated resources make re-purposing of resources harder, causing unnecessary waste of capacities. For example, an ISV have to anticipate and allocate sufficient disk space for each customer. On one hand, the unused disk space is wasted (or&amp;nbsp; could have been at least utilized better – remember resources are not free). On the other hand, when the customer exceeds allocated resources, addition resources have to be provisioned. Again this increases management complexity. &lt;/p&gt; &lt;p&gt;What becomes more interesting is when centralized features, such as administrative features and BI capabilities, are developed.&amp;nbsp; Some annoying problems may jump out on you here and here. For instance, how a new feature reliably identifies individual tenants when the tenants don’t have such identifiers built in themselves? This sounds like a very small problem and there seems to be a very easy solution – a global lookup table. Technically a lookup table would have worked fine, but throughout my previous projects I’ve observed such lookup tables going out of sync pretty easily. One major reason is that the operation teams who stand up new tenants consider maintaining this global table as an additional burden – this is something they didn’t have to do and doing so doesn’t contribute or affect their deliverables. Of course in an ideal world everybody will do the right thing, but in reality the new features are often victims of such neglects and behave miserably - they try to query a system that don’t exist, they miss new systems that are coming online, and so on and so forth.&amp;nbsp; Another similar problem is to open up effective communication channels to existing systems while owner of existing systems are not willing to cooperate. Such resistance is actually not that surprising - after all the initial motivation of using multi-instance architecture is to reuse existing code! The point is, again, going to multi-tenancy is a business model shift and need company-wide commitments. Many of such projects failed not merely because of technical reasons. As the discussion here is already going out of the technical scope, I shall stop here.&lt;/p&gt; &lt;p&gt;The multi-instance architecture is not all bad. In addition to reuse of existing implementations, it provides very good tenant isolation across all system layers; It allows uneven topologies – meaning it allows different customers to run different versions of software on different hardware. I know I just mentioned such things as downsides, but in some particular situations they are actually desirable. For example, I used to have a customer who made a major update to the software and wanted its customers to pay to upgrade. However at the same time it would like existing customers to keep using the older versions as long as they renew maintenance contracts. In another example, an ISV would like to allocated a small number of servers that were dedicated to student users while keep other paid users on the main cluster. &lt;/p&gt; &lt;p&gt;Enough said on multi-instance architecture for now. The other architecture choice is actually also obvious – to refactor the single-tenant system into a multi-tenant system. There’s no way to sugarcoat it – the refactoring will be a big project. And without doubts some system are harder to be refactored than others. Here are several characteristics that I’ve observed make such refactoring harder:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Stateful services. It’s not unusual to see long-living components who assume they have global knowledge of the system, or have global control over the system. Such components are often named as “managers”, “dispatchers”, “schedulers” and such. These components are dangerous because they often maintain heavy states, and they often assume they live throughout the lifetime of the service. In a multi-tenant environment, especially a&amp;nbsp; cloud-hosted multi-tenant environment, no components live forever. For example, an server instance may be brought down by the hosting environment for maintenance at certain intervals (such as quarterly). Will these components be ready to persist and rehydrate their states? What happens when this happens? Those are the exact hard questions that lead people to stateless services.&amp;nbsp; The greater danger, however, is the temptation to promote such components to the global level. And you might be surprised by how often that happens! Prompting such components creates single points of failures (SPOF), and failures of such components are often catastrophic. &lt;/li&gt; &lt;li&gt;Resources hogs. In the previous post we examined how to guard one type of resource hogs by throttling CPU usage. There are several other resources at play, such as storage, memory, and bandwidth. Because resource pressures build up much quicker on a multi-tenant system than on a single-tenant system,&amp;nbsp; excessive resource consumption can easily create bottlenecks here and there. And if such problems are not corrected early, you may find yourself in a very unpleasant position of redesigning in very late phases of the project. &lt;/li&gt; &lt;li&gt;Tightly-coupled components. The single-tenant to multi-tenant migration is mostly a long process for any sizable projects. Chances are you’ll need to swap out old parts piece by piece. Tightly-coupled components make such swapping very hard – I guess I don’t need to say more on that.&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;&lt;/h3&gt; &lt;h3&gt;Recipe 2: Centralized SSL management&lt;/h3&gt; &lt;h4&gt;&lt;font style="font-weight: bold" color="#4f81bd"&gt;Problem&lt;/font&gt;&lt;/h4&gt; &lt;p&gt;When an ISV needs to host a large number of secured sites that use SSL certificates, certificate management may become problematic in terms of increasing site density, ensuring manageability, as well as improving performance. If you have a large number of SSL certificates on an IIS server, you may run into serious performance issues when you handle HTTPS traffics. This is because ALL certificates are loaded in memory when HTTPS traffics come in. This not only consumes memory, but also slows down the response time. In addition, it’s often desirable to remove certificate management tasks from developers’ responsibilities.&amp;nbsp; For Cloud Services running on Windows Azure, certificate management is mostly separated from service management. However, there are three small catches:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;The certificate thumbprints are included in .cscfg file. Although this file can be uploaded and modified without redeploying the service, changes in this file may cause the service to be redeployed anyway. For instance, when you renew a certificate with a new thumbprint, IIS configurations on the instance virtual machines have to be updated, causing service interruptions. This is a big problem when you have many certificates to renew.  &lt;li&gt;There could be a disconnection between the system administrator and the developers – the administrator may have updated the .cscfg file while the developers are still building/deploying services with older .cscfg file, causing more fictions.  &lt;li&gt;Cloud Service .csdef file doesn’t allow you to specify multiple certificates for HTTPS endpoints on the same port. The workarounds include using different ports, which is usually very undesirable, or use wildcard certificate or a SAN certificate.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;What I’d like to achieve here are the following:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Complete separation of concern. The developers should not care about what certificates are used and when they are changed or renewed. I don’t want any references to certificate thumbprints anywhere in the code, including .cscfg file.  &lt;li&gt;I want to enable IIS 8 centralized certificate management so certificate management can be greatly simplified.  &lt;li&gt;I can use other certificates other than wildcard certs and SAN certs to secure my web sites.&lt;/li&gt;&lt;/ul&gt; &lt;h4&gt;&lt;font style="font-weight: bold" color="#4f81bd"&gt;Solution&lt;/font&gt;&lt;/h4&gt; &lt;p&gt;In a nutshell, the idea of centralized SSL certificate management is simple – instead of installing certificates on each individual machines, certificates are kept on a network share as (.pfx) files. When IIS is configured to use centralized certificate management, it will look up in this location to find correctly certificate to resolve binding by matching host headers with certificate file names. When a system administrator needs to renew a certificate, all he needs to do is to xcopy the renewed certificate over the old one and the job is done. In addition to significant improvement in manageability, centralized SSL certificates also provide a very noticeable performance boost especially when you have many certificates. When IIS is configured to use SSL certificates, ALL certificates are loaded into memory when it handles a HTTPS request. The CPU and memory cost is ignorable when you have only a few certificates, but it becomes huge when you have hundreds and thousands of certificates to load.&amp;nbsp; With centralized SSL certificates, certificates are loaded on-demand, which greatly reduces the processing time and memory consumption.&lt;/p&gt; &lt;h4&gt;&lt;font color="#4f81bd"&gt;&lt;font style="font-weight: bold"&gt;Sample walkthrough&lt;/font&gt;&lt;/font&gt;&lt;/h4&gt; &lt;p&gt;As usual, the following is a walkthrough of creating the sample scenario from scratch. I do assume you are familiar with Windows Azure Cloud Service, IIS manager and ASP.NET MVC in general, so some of the steps won’t be as details as for beginners. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Visual Studio 2012  &lt;li&gt;Windows 8 with IIS 8.0  &lt;li&gt;Windows Azure SDK&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;strong&gt;Step 1: Enable secured connection for a Cloud Service with multiple sites&lt;/strong&gt;&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Follow Step 1 of &lt;a href="http://haishibai.blogspot.com/2012/10/recipes-for-multi-tenant-cloud-service.html"&gt;recipe 1&lt;/a&gt; to create the baseline application. You can skip step 3 to 5 because you won’t need the CPUThrottleController in this case. You can also directly use the result solution of previous exercise as well. &lt;li&gt;Make a wildcard self-issued cert for testing: &lt;pre class="csharpcode"&gt;makecert.exe -r -pe -n &lt;span class="str"&gt;"CN=&lt;font style="background-color: #ffff00"&gt;*.haishibai.com&lt;/font&gt;"&lt;/span&gt; -b 01/01/2010 -e 01/01/2050 -eku 1.3.6.1.5.5.7.3.1 -ss my -sr localMachine -sky exchange -sp &lt;span class="str"&gt;"Microsoft RSA SChannel Cryptographic Provider"&lt;/span&gt; -sy 12&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
The above command installs a wildcard certificate to Local Computer personal store. 
&lt;li&gt;Open the certificate in mmc, export the certificate to a .pfx file. Name the file as &lt;font style="background-color: #ffff00"&gt;_.haishibai.com.pfx&lt;/font&gt;. When you deploy the Cloud Service to Azure, this is the certificate you, or your system administrator, needs to upload. 
&lt;li&gt;Copy the thumbprint of the certificate. This is the thumbprint (with spaces removed) you need to enter to .cscfg file. 
&lt;li&gt;Import the .pfx file to Trusted Root Certification Authorities of Local Computer store. This is to avoid certificate warnings during our tests. 
&lt;li&gt;Go back to Visual Studio. Double-click the Web Role in the Cloud Service project to bring up property page. 
&lt;li&gt;Go to &lt;strong&gt;Certificates&lt;/strong&gt; tab. Click on &lt;strong&gt;Add Certificate&lt;/strong&gt; link. 
&lt;li&gt;Set the name of the certificate to WildcardCert, and pick the certificate from Local Computer store:&lt;br clear="all"&gt;&lt;a href="http://lh3.ggpht.com/-QVMx_LrBlwA/UHOAtkjxoiI/AAAAAAAAAs0/XiDdYn4o_EM/s1600-h/image4.png"&gt;&lt;img title="image" 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="image" src="http://lh4.ggpht.com/-vk2CxP9p8xk/UHOAt-7Z_PI/AAAAAAAAAs8/MVUEgMllbW8/image_thumb1.png?imgmax=800" width="623" height="117"&gt;&lt;/a&gt; 
&lt;li&gt;Go to &lt;strong&gt;Endpoints&lt;/strong&gt; tab. Add an endpoint with &lt;strong&gt;https&lt;/strong&gt; protocol. Pick the SSL certificate we just added:&lt;br clear="all"&gt;&lt;a href="http://lh4.ggpht.com/-q4IsJnEBzZw/UHOAuXZ_0GI/AAAAAAAAAtE/qf51IoZzWGE/s1600-h/image9.png"&gt;&lt;img title="image" 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="image" src="http://lh5.ggpht.com/-N5nQujZRCMA/UHOAuntnqRI/AAAAAAAAAtM/ZVjvCB-kl14/image_thumb4.png?imgmax=800" width="620" height="145"&gt;&lt;/a&gt; 
&lt;li&gt;Make sure all sites in the .csdef file refer to the new endpoint:&lt;pre class="csharpcode"&gt;...
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Sites&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Site&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="gold"&lt;/span&gt; &lt;span class="attr"&gt;physicalDirectory&lt;/span&gt;&lt;span class="kwrd"&gt;="..\..\..\IIS8Features.Web"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Bindings&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Binding&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="Endpoint1"&lt;/span&gt; &lt;span class="attr"&gt;endpointName&lt;/span&gt;&lt;span class="kwrd"&gt;="Endpoint1"&lt;/span&gt; &lt;span class="attr"&gt;hostHeader&lt;/span&gt;&lt;span class="kwrd"&gt;="gold.haishibai.com"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
      &lt;font style="background-color: #ffff00"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Binding&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="Https"&lt;/span&gt; &lt;span class="attr"&gt;endpointName&lt;/span&gt;&lt;span class="kwrd"&gt;="HttpsIn"&lt;/span&gt; &lt;span class="attr"&gt;hostHeader&lt;/span&gt;&lt;span class="kwrd"&gt;="gold.haishibai.com"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/font&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Bindings&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Site&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Site&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="silver"&lt;/span&gt; &lt;span class="attr"&gt;physicalDirectory&lt;/span&gt;&lt;span class="kwrd"&gt;="..\..\..\IIS8Features.Web"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Bindings&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Binding&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="Endpoint1"&lt;/span&gt; &lt;span class="attr"&gt;endpointName&lt;/span&gt;&lt;span class="kwrd"&gt;="Endpoint1"&lt;/span&gt; &lt;span class="attr"&gt;hostHeader&lt;/span&gt;&lt;span class="kwrd"&gt;="silver.haishibai.com"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
      &lt;font style="background-color: #ffff00"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Binding&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="Https"&lt;/span&gt; &lt;span class="attr"&gt;endpointName&lt;/span&gt;&lt;span class="kwrd"&gt;="HttpsIn"&lt;/span&gt; &lt;span class="attr"&gt;hostHeader&lt;/span&gt;&lt;span class="kwrd"&gt;="silver.haishibai.com"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/font&gt;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Bindings&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Site&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Sites&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
...&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;li&gt;Press &lt;strong&gt;F5&lt;/strong&gt; to run the application. Ignore the errors and certificate warnings you see in the browser. Type in https://gold.haishibai.com:444 or https://silver.haishibai.com:444 in address bar. The site should be loaded correctly without certificate warnings. Note on your machine you may have to use a different port – see &lt;a href="http://haishibai.blogspot.com/2012/10/recipes-for-multi-tenant-cloud-service.html"&gt;recipe 1&lt;/a&gt; part 1 for details on how to get the correct port number.&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;There’s nothing new so far – this is what you typically do when you enable SSL for multi-site Cloud Service. Note that there’s no reference to actual certificate in the .csdef file. However, you can see the thumbprint in .cscfg file:&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Role&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="IIS8Features.Web"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  ...
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Certificates&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Certificate&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="WildcardCert"&lt;/span&gt; &lt;span class="attr"&gt;thumbprint&lt;/span&gt;&lt;span class="kwrd"&gt;="&lt;font style="background-color: #ffff00"&gt;55B5D291B7B56BDD4C6C38CE93CA3E3DCD49E7BD&lt;/font&gt;"&lt;/span&gt; &lt;span class="attr"&gt;thumbprintAlgorithm&lt;/span&gt;&lt;span class="kwrd"&gt;="sha1"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Certificates&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  ...
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Role&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Enable centralized SSL certificate management&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a new network share, and copy the _.haishibai.com.pfx file into the folder. This shared folder will be the centralized certificate store. 
&lt;li&gt;Make sure&lt;strong&gt; Centralized SSL Certificate Support&lt;/strong&gt; has been enabled. If not, enable the feature from Control Panel –&amp;gt; Turn Windows Features On or Off: 
&lt;p&gt;&lt;a href="http://lh4.ggpht.com/-MdtIfQlf2pc/UHOAuzRZUvI/AAAAAAAAAtU/P5JLpLb6QTI/s1600-h/image13.png"&gt;&lt;img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://lh3.ggpht.com/--22g-bJT8sc/UHOAve72HLI/AAAAAAAAAtc/UiaquOjLhzg/image_thumb5.png?imgmax=800" width="366" height="321"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;li&gt;Open IIS manager. Select the server node. You’ll see the new Centralized Certificates icon. Double-click the icon to open the feature:&lt;br clear="all"&gt;&lt;a href="http://lh6.ggpht.com/-dQdd8M24VPM/UHOAv8Xb7PI/AAAAAAAAAtk/4PfpwBCleJ4/s1600-h/image18.png"&gt;&lt;img title="image" 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="image" src="http://lh5.ggpht.com/-J_KDTbvgRaM/UHOAwbxMd3I/AAAAAAAAAts/ExAOuGD62mQ/image_thumb8.png?imgmax=800" width="637" height="337"&gt;&lt;/a&gt; 
&lt;li&gt;In action pane, click &lt;strong&gt;Edit Feature Settings…&lt;/strong&gt; 
&lt;li&gt;In Edit Centralized Certificates Settings dialog, enter credential to the network share. Note that in current version, all certificates under the folder have to have the same private key password:&lt;br clear="all"&gt;&lt;a href="http://lh5.ggpht.com/-2uFctsPl4RQ/UHOAwv0TdRI/AAAAAAAAAtw/XkNx81IikLo/s1600-h/image23.png"&gt;&lt;img title="image" 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="image" src="http://lh5.ggpht.com/-981yQ7ckEPs/UHOAxA-1mqI/AAAAAAAAAt8/sxd_znK6lRQ/image_thumb11.png?imgmax=800" width="396" height="391"&gt;&lt;/a&gt; 
&lt;li&gt;Click &lt;strong&gt;OK&lt;/strong&gt; to update the settings. 
&lt;li&gt;Now we can remove references to certificates in our code. First, remove &lt;strong&gt;&amp;lt;Certificates&amp;gt;&lt;/strong&gt; element from both .cscfg and .csdef. 
&lt;li&gt;Then, remove the certificate attribute from &lt;strong&gt;&amp;lt;InputEndpoint&amp;gt;&lt;/strong&gt; element as well: &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Endpoints&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;InputEndpoint&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="Endpoint1"&lt;/span&gt; &lt;span class="attr"&gt;protocol&lt;/span&gt;&lt;span class="kwrd"&gt;="http"&lt;/span&gt; &lt;span class="attr"&gt;port&lt;/span&gt;&lt;span class="kwrd"&gt;="80"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;InputEndpoint&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="HttpsIn"&lt;/span&gt; &lt;span class="attr"&gt;protocol&lt;/span&gt;&lt;span class="kwrd"&gt;="https"&lt;/span&gt; &lt;span class="attr"&gt;port&lt;/span&gt;&lt;span class="kwrd"&gt;="443"&lt;/span&gt; &lt;strike&gt;&lt;font style="background-color: #cccccc"&gt;&lt;span class="attr"&gt;certificate&lt;/span&gt;&lt;span class="kwrd"&gt;="WildcardCert"&lt;/span&gt;&lt;/font&gt;&lt;/strike&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Endpoints&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;li&gt;Press &lt;strong&gt;F5&lt;/strong&gt; to launch the application. 
&lt;li&gt;Open IIS manager. Select the gold site. Then click &lt;strong&gt;Bindings…&lt;/strong&gt; link in action pane. 
&lt;li&gt;In &lt;strong&gt;Site Bindings&lt;/strong&gt; dialog, select the &lt;strong&gt;https&lt;/strong&gt; binding, and then click &lt;strong&gt;Edit…&lt;/strong&gt; button. 
&lt;li&gt;In &lt;strong&gt;Edit Site Binding&lt;/strong&gt; dialog, check &lt;strong&gt;Use Centralized Certificate&lt;/strong&gt; Store, then click &lt;strong&gt;OK&lt;/strong&gt;.&lt;br clear="all"&gt;&lt;a href="http://lh3.ggpht.com/-1V9TlLR4LQE/UHOAxbz28OI/AAAAAAAAAuE/Z6rbzHwgzsM/s1600-h/image27.png"&gt;&lt;img title="image" 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="image" src="http://lh6.ggpht.com/-FBn5D1Gj-p0/UHOAx-LbndI/AAAAAAAAAuM/wxvHgW5mcwc/image_thumb13.png?imgmax=800" width="403" height="242"&gt;&lt;/a&gt;&amp;nbsp; &lt;li&gt;Repeat step 10 to 12 for silver.haishibai.com. 
&lt;li&gt;Now navigate to https://gold.haishibai.com or https://silver.haishibai.com. The sites should load without certificate warnings. IIS looks under the shared folder for matching certificate. Because wildcard certificate is supported, IIS picks up _.haishibai.com (we use _ instead of * because * is an invalid character for file names) in this case. Of course, now you are free to use any number of domain specific certificates as well – simply copy the certs to the shared folder following the naming convention, for example &lt;strong&gt;gold.haishibai.com.pfx&lt;/strong&gt; for &lt;strong&gt;gold.haishibai.com&lt;/strong&gt; domain and so on. &lt;/li&gt;&lt;/ol&gt;
&lt;h3&gt;Some additional notes&lt;/h3&gt;
&lt;p&gt;At this point I don’t have everything automated. The major problem I’m facing is to auto-configure the centralized certificate store. This configuration is (rightfully) not saved in any configuration files, so digging that up is kind of hard. However, the following are some of the other pieces of puzzle that may become useful when you try to automate the process:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use &lt;a href="http://go.microsoft.com/fwlink/?LinkId=233753"&gt;WebPI command line tool (v4 preview)&lt;/a&gt; in a startup task to install required IIS components. For example, to enable Centralized SSL Certificate Support, use command:&lt;pre class="csharpcode"&gt;webpicmdline /Install /Products:CertProvider&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;li&gt;Here are some of the other IIS components you can install by WebPI (to get a complete list, use webpicmdline /List /ListOption:Available): 
&lt;table cellspacing="0" cellpadding="2" width="400" border="1"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign="top" width="200"&gt;&lt;strong&gt;ID&lt;/strong&gt;&lt;/td&gt;
&lt;td valign="top" width="198"&gt;&lt;strong&gt;Title&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="200"&gt;AppWarmUp&lt;/td&gt;
&lt;td valign="top" width="198"&gt;IIS: Application Initialization&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="200"&gt;IPSecurity&lt;/td&gt;
&lt;td valign="top" width="198"&gt;IIS: IP and Domain Restrictions&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="200"&gt;RequestMonitor&lt;/td&gt;
&lt;td valign="top" width="198"&gt;IIS: Request Monitor&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;li&gt;I *think*you should be able to use appcmd to change default site settings to enable centralized SSL certificate for newly created sites. However I haven’t tried it myself.&lt;/li&gt;&lt;/ul&gt;
&lt;h3&gt;Recipe 2 Summary&lt;/h3&gt;
&lt;p&gt;In this post we enabled IIS8 Centralized SSL Certificate Support and configured our web site to use HTTPS endpoints without having any references to any certificates in our .csdef or .cscfg files.&lt;/p&gt;  &lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/t1fuxI2nqjw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/1027834520962924091/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2012/10/recipes-for-multi-tenant-cloud-service_8.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/1027834520962924091?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/1027834520962924091?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/t1fuxI2nqjw/recipes-for-multi-tenant-cloud-service_8.html" title="Recipes for Multi-tenant Cloud Service Design – Recipe 2: Centralized SSL Certificate Management" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/-vk2CxP9p8xk/UHOAt-7Z_PI/AAAAAAAAAs8/MVUEgMllbW8/s72-c/image_thumb1.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2012/10/recipes-for-multi-tenant-cloud-service_8.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ck4HQ344fCp7ImA9WhJaFEU.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-3283813771866681054</id><published>2012-10-05T16:48:00.001-07:00</published><updated>2012-10-05T16:48:52.034-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-10-05T16:48:52.034-07:00</app:edited><title>Cross-role Events using Windows Azure Caching (Preview)</title><content type="html">&lt;h3&gt;&lt;font style="font-weight: bold"&gt;Problem&lt;/font&gt;&lt;/h3&gt; &lt;p&gt;There are several different options for Web Roles and Worker Roles to communicate with each other within the boundary of a Cloud Service:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Use Service Bus Queues or Windows Azure Queue Storage (async communication, not constrained by service boundary)&lt;/li&gt; &lt;li&gt;Use Internal Endpoints to directly dispatch workloads (direct communication, within service boundary)&lt;/li&gt; &lt;li&gt;Use standard cross-machine communications such as WCF (depends on WCF configuration)&lt;/li&gt; &lt;li&gt;Use a common storage such as Windows Azure Table Storage (shared-storage integration pattern, not constrained by service boundary)&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Other than the WCF option, which is more complex comparing to other options, none of above options provides nice support for event-driven pattern. It would be nice if we can implement some simple cross-role eventing mechanism so that we can raise events across role boundaries.&lt;/p&gt; &lt;h3&gt;&lt;font style="font-weight: bold"&gt; Solution&lt;/font&gt;&lt;/h3&gt; &lt;p&gt;Windows Azure Caching (Preview) provides some built-in notification capabilities. You can subscribe to notifications at cluster, region, as well as item level. Because the cache cluster is accessible to all configured roles, we can easily tap into this notification mechanism and gain some simple eventing capabilities without much effort. Of course, to implement a robust event system requires much more than what’s presented here. This post is merely to provide some foods for thoughts.&lt;/p&gt; &lt;p&gt;The first thing is to enable notification on your cache cluster. This is a simple configuration change:&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-8v6-kXwtl6w/UG9x39R-WlI/AAAAAAAAAsM/Pk6xCumvNLQ/s1600-h/image%25255B3%25255D.png"&gt;&lt;img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://lh3.ggpht.com/-giNx_0YZ7Yo/UG9x4AcjDWI/AAAAAAAAAsU/LHJNPWITlic/image_thumb%25255B1%25255D.png?imgmax=800" width="653" height="120"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Then, create a DataCache client with change-polling interval reduced. By default the interval is 5 minutes. In the following code I set the interval to 5 seconds instead. Note that in the code I’m looking for a specific cache named “role_events”. I think it’s a good idea to have named cache used for events separate from other caches&amp;nbsp; - but of course you can use default cache if you want to.&lt;pre class="csharpcode"&gt;DataCacheFactoryConfiguration configuration = &lt;span class="kwrd"&gt;new&lt;/span&gt; DataCacheFactoryConfiguration();
configuration.NotificationProperties = &lt;span class="kwrd"&gt;new&lt;/span&gt; DataCacheNotificationProperties(1000, &lt;span class="kwrd"&gt;new&lt;/span&gt; TimeSpan(0, 0, 5));
DataCacheFactory factory = &lt;span class="kwrd"&gt;new&lt;/span&gt; DataCacheFactory(configuration);
DataCache cache = factory.GetCache(&lt;span class="str"&gt;"role_events"&lt;/span&gt;);&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/p&gt;
&lt;p&gt;Once we have the cache client, we can subscribe to different cache notifications. In the following code I register for cluster-level add and replace events – depends on your design, you may want to use different events.&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;if&lt;/span&gt; (cache != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
{
  cache.AddCacheLevelCallback(DataCacheOperations.AddItem | DataCacheOperations.ReplaceItem,
    (namedCache, regionName, key, version, cacheOperation, nd) =&amp;gt;
    {
          &lt;span class="rem"&gt;//CALL CALLBACKS&lt;/span&gt;
     });
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/p&gt;
&lt;p&gt;Now the callbacks will be called whenever an item is added or updated in “role_events” cache. To make things even a little nicer, I wrote a simple wrapper to enable .Net style events. Again, this is an over-simplified sample. Don’t use it in your production code &lt;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://lh4.ggpht.com/-IsZGctoHMtQ/UG9x4orqw-I/AAAAAAAAAsc/GE0gkq4Sh44/wlEmoticon-smile%25255B2%25255D.png?imgmax=800"&gt;. &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; EventBus
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;event&lt;/span&gt; EventHandler&amp;lt;BrokeredEventArgs&amp;gt; EventReceived;
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; DataCache mCache;
    &lt;span class="kwrd"&gt;private&lt;/span&gt; EventBus() { }
        
    &lt;span class="kwrd"&gt;static&lt;/span&gt; EventBus()
    {
        DataCacheFactoryConfiguration configuration = &lt;span class="kwrd"&gt;new&lt;/span&gt; DataCacheFactoryConfiguration();
        configuration.NotificationProperties = &lt;span class="kwrd"&gt;new&lt;/span&gt; DataCacheNotificationProperties(1000, &lt;span class="kwrd"&gt;new&lt;/span&gt; TimeSpan(0, 0, 5));
        DataCacheFactory factory = &lt;span class="kwrd"&gt;new&lt;/span&gt; DataCacheFactory(configuration);
        DataCache cache = factory.GetCache(&lt;span class="str"&gt;"role_events"&lt;/span&gt;);
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (mCache != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
        {
            mCache.AddCacheLevelCallback(DataCacheOperations.AddItem | DataCacheOperations.ReplaceItem,
            (namedCache, regionName, key, version, cacheOperation, nd) =&amp;gt;
            {
                &lt;span class="kwrd"&gt;if&lt;/span&gt; (EventReceived != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
                    EventReceived(mCache, &lt;span class="kwrd"&gt;new&lt;/span&gt; BrokeredEventArgs(key, mCache.Get(key)));
            });
        }
    }
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/p&gt;
&lt;p&gt;Sending event is easy – simply add or update an item in the cache. Note that here I’m not using any custom classes. It’s all standard caching operation. On the other hand, it doesn’t hurt to add a Send() method on EventBus class to provide some additional abstraction. Note that on the sender’s side we don’t need aggressive notification polling as it is on the receiver’s side. Keep that in mind when you implement such as method.&lt;pre class="csharpcode"&gt;DataCache cache = &lt;span class="kwrd"&gt;new&lt;/span&gt; DataCache();
cache.put(&lt;span class="str"&gt;"JobCreated"&lt;/span&gt;, job);&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/p&gt;
&lt;p&gt;Receiving events is easy as well: &lt;pre class="csharpcode"&gt;EventBus.EventReceived += (o, e) =&amp;gt;
  {
     var name = e.EventName;
     var payload = e.Payload;
  };&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/p&gt;
&lt;p&gt;And BrokeredEventArgs is a simple class with a name and a payload: &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; BrokeredEventArgs:EventArgs
{
  &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; EventName { get; &lt;span class="kwrd"&gt;private&lt;/span&gt; set; }
  &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt; Payload { get; &lt;span class="kwrd"&gt;private&lt;/span&gt; set; }
  &lt;span class="kwrd"&gt;public&lt;/span&gt; BrokeredEventArgs(&lt;span class="kwrd"&gt;string&lt;/span&gt; name, &lt;span class="kwrd"&gt;object&lt;/span&gt; payload)
  {
    EventName = name;
    Payload = payload;
  }
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/p&gt;
&lt;p&gt;That’s it! One last thing I want to mention is that, for simplicity (yeah, right), above code doesn’t prepare for any transient errors. However in reality you need to prepare for such errors especially when the caching cluster is hosted on a dedicated role. In this case the cluster role instances and other web/worker role instances are initialized independently. Chances are when you make your first caching call the cluster is not ready yet. Although DataCache has some built-in retries when it connects to a cluster, you’d better still prepare for such errors.&lt;/p&gt;  &lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/uSslAI9WDDU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/3283813771866681054/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2012/10/cross-role-events-using-windows-azure.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/3283813771866681054?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/3283813771866681054?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/uSslAI9WDDU/cross-role-events-using-windows-azure.html" title="Cross-role Events using Windows Azure Caching (Preview)" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/-giNx_0YZ7Yo/UG9x4AcjDWI/AAAAAAAAAsU/LHJNPWITlic/s72-c/image_thumb%25255B1%25255D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2012/10/cross-role-events-using-windows-azure.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A04GRnY5eip7ImA9WhJaE0U.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-6833271788343991188</id><published>2012-10-03T17:22:00.001-07:00</published><updated>2012-10-04T15:32:07.822-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-10-04T15:32:07.822-07:00</app:edited><title>Recipes for Multi-tenant Cloud Service Design – Recipe 1: Throttling by Tenants Using Multi-site Cloud Services and IIS 8 CPU Throttling</title><content type="html">&lt;h3&gt;About Multi-tenancy&lt;/h3&gt; &lt;p&gt;One of the major mind shifts an ISV needs to go through when it migrates on-premises systems to cloud-based systems is the shift from multi-instance (or single-tenant) architecture to multi-tenant architecture. Instead of deploying separate service instances for individual customers, an ISV can serve all its customers from the cloud. During this migration, however, some problems, which may not be so critical in a multi-instance system, will surface and cause troubles if the ISV doesn’t plan ahead. So, migrating an existing service to cloud is not just a simple matter of switching host environments. There are several new challenges the ISV has to face: &lt;/p&gt; &lt;ul&gt; &lt;li&gt;Tenant isolation. An ISV needs to ensure customers are isolated from each other – one customer should not gain access to other customers’ data, either accidentally or intentionally; workflows from different customers should not interfere with each other; provisioning or deprovisioning a customer should have zero impact on other customers; customer-level configuration changes should have no global impacts… In other words, a customer should feel (and be assured) that the service is logically dedicated to him, regardless the fact that it’s hosted on a shared infrastructure.  &lt;li&gt;Problem containment. A multi-tenant system comes with many benefits such as dramatic reduction in TCO, agility in reacting to market changes, and high-availability based on robust, fault-tolerance hosting environment such as Windows Azure.&amp;nbsp; However, it also brings additional risks to an ISV. For example, a successful DoC attack on a on-premises system brings down only one customer, while the same attack may cause a system-wide failure across all customers. That’s a much higher risk to deal with. An ISV needs ways to closely monitor system health and to constraint the impacts to the smallest scope when problems do occur.  &lt;li&gt;Security and compliance. This is a broad problem that contains several aspects across a wide spectrum. First, authentication and authorization may become challenging for systems that have been relying on Active Directory. How do you leverage Active Directory on the cloud?&amp;nbsp; Second, many industries and countries have strict compliance requirements such as where the data can be stored and who can execute a particular workflow. How does an ISV satisfy the compliance requirements while it runs the service on Cloud? Third, on a hosted environment, services clients communicate with the services over the public Internet. This requires precautions against attacks such as phishing and eavesdropping, etc. Fourth, on a multi-instance (or a single-tenant) system, the system contains a single security boundary, while in a multi-tenant system, the system contains multiple security boundaries isolating different customers. An ISV has to make sure such finer security boundaries are reinforced to guard against attacks such as spoofing and impersonation, etc.  &lt;li&gt;Data migration and transformation. Is the ISV’s database schema designed to hold data for multiple customers? Should the ISV consider using separate database for different customers? What are the needs to migrate existing customer data? Will the database layer scale? Should the data be synced among different sources? All these questions require serious consideration and careful planning.  &lt;li&gt;Transient errors. Service calls fail. Maybe the connection is dropped. Maybe the service is down. Maybe the server is throttling your requests. Maybe your requests timed out due to heavy workloads… Transient errors are the type of errors that are temporary and automatically resolved – if you try the same operation again later the call is likely to succeed. However, if an ISV’s code is not prepared for transient errors and takes granted that certain calls will complete, it will probably be surprised by strange behaviors that are hard to reproduce and very difficult to fix. And I can almost guarantee you when that happens, it ALWAYS happens at the worst possible time.  &lt;li&gt;Performance, performance, performance. I can’t emphasize enough on the importance of performance because now the ISV’s services and clients are communicating over a long wire. Is added latency acceptable? How to reduce it? In addition, transferring large amount of data on corporate network might work fine, but is it still feasible to transfer the same amount of data over the Internet?&amp;nbsp; Can we keep the same level of caching per customer without exhausting server resources? How to maintain performance level when number of requests spikes? How to handle long-running third-party service calls? How to identify and resolve performance bottlenecks across application layers? Remember, in the world of Internet, a slow service equals to a broken service – and you can quote me on that.  &lt;li&gt;BI opportunities. It’s much easier for a multi-tenancy system to gain a holistic view of all customers because the system is directly connected with all customer activities. Very few ISVs can resist (nor should they) the tremendous business value such insights can bring them. And many more innovative scenarios become possible when deeper BI are acquired. However, BI doesn’t come for free. It’s by itself a sizable project. What I’ve observed is that without proper planning, some initial data-mining capabilities are sprinkled here and there and people LOVE them. And more and more demands come in (often from “the top”) as the project goes along, until the system starts to suffer from lacking of proper BI architecture. In one particular case, because the OLAP queries were locking up transactional data, they had to be pulled out from the system in a very late stage so that the service was not interrupted. And I can tell you the situation wasn’t pretty. &lt;li&gt;Multi-tenancy administration. Managing a multi-tenant system introduces new requirements on administrative capabilities. The existing, single-tenant management API and UI are very unlikely to suffice for the requirements of a multi-tenant environment.&amp;nbsp; Here’s a non-exhaustive list of such requirements I’ve seen in my previous projects – (dynamic) customer provisioning/deprovisioning, centralized user management, centralized system monitoring and billing. Among these requirements, centralized user management, service usage monitoring and billing are particularly interesting – we’ll go into more details on those in later articles.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;As you can see, there are LOTS to consider when implementing a multi-tenant system. For many ISVs, this is a big leap – it’s a leap from being a software vendor to a service vendor. What I’ve listed about are mostly on the technical side. There are also many changes on the business side as this is essentially a different business model. I shall not discuss more on the business and marketing side as I’m not an expert, but an ISV should be aware what it’s taking on when embarking such a journey. Said that, I don’t want you to get discouraged. Instead, you should be excited as MANY people have worked hard to provides all kinds of guidance, services and tools to help building multi-tenant systems. And many companies have implemented cloud-based, multi-tenant systems with great success. As a world leader of services, Microsoft is no exception. If you looked closely to the new features provided by Windows Server 2012, IIS 8, and Windows Azure, you can see multi-tenancy written everywhere. There are good chemical reactions happening between Windows Azure and Windows Servers – they leverage each other and pull each other forward. The interaction creates not only a better and better cloud platform, but also stronger, more scalable on-premises servers.&amp;nbsp; &lt;/p&gt; &lt;p&gt;For the rest of the series, I’ll go through several recipes that provide potential solutions to many of above problems and challenges. Each recipe is presented in a problem-solution format, with tags on problems indicating to which areas the problems are related. I’ll be using features and capabilities of Windows Server 2012, IIS 8, Windows Azure, Windows Azure SDK, as well as .Net 4.5. However, you should be able to try out most of the samples with a Windows 8 + IIS 8 + Visual Studio 2012 + Windows Azure SDK machine. Now let’s jump in!&lt;/p&gt; &lt;h3&gt;Recipe 1: Throttling by Tenants Using Multi-site Cloud Services and IIS 8 CPU Throttling&lt;/h3&gt; &lt;h4&gt;&lt;font style="font-weight: bold" color="#4f81bd"&gt;Problem [Tenant isolation][Problem containment][Performance]&lt;/font&gt;&lt;/h4&gt; &lt;p&gt;It’s very common for an ISV to provide different sites for its SaaS subscribers. The approach creates not only a sense of ownership, but also security boundaries and management boundaries to manage the customers more effectively. Because customers from all sites compete for the same pool of precious resources the ISV can provide – CPU, storage, bandwidth, etc., the ISV has to make sure excessive workload from one customer&amp;nbsp; has minimum impacts on other customers. In addition, the ISV may have signed different SLAs with different customers, it has to ensure the prime subscribers granted with sufficient resources to keep the SLA promises. &lt;/p&gt; &lt;p&gt;In summary, our requirements are:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Be able to throttle users based on their service subscriptions.  &lt;li&gt;Heavy workloads should not jeopardize the overall system performance.&lt;/li&gt;&lt;/ul&gt; &lt;h4&gt;&lt;font style="font-weight: bold" color="#4f81bd"&gt;Solution&lt;/font&gt;&lt;/h4&gt; &lt;p&gt;With IIS 8 on Windows Server 2012, IIS application pools are isolated into sand-boxes. The sand-boxes provide not only the security boundaries, but also the resource management boundaries. With sand-boxed application pools, an ISV can truly limit how much CPU each tenant can use (read more about sand-boxing on &lt;a href="http://www.iis.net"&gt;www.iis.net&lt;/a&gt;). In this sample solution, I’ll assume the ISV has two levels of subscriptions: gold and silver. To ensure SLA, the ISV allows gold subscribers to consume more CPU than the silver subscribers can ever request. In addition, the CPU throttling also makes sure the system is not saturated by unexpected surge of workloads. The solution is simple - I’ll use Web Role multi-site capability to create two separate sites, one for each level of subscription. And then, I’ll configure the corresponding application pools according to predefined throttling policy. &lt;/p&gt; &lt;h4&gt;&lt;font color="#4f81bd"&gt;&lt;font style="font-weight: bold"&gt;Sample walkthrough&lt;/font&gt;&lt;/font&gt;&lt;/h4&gt; &lt;p&gt;The following is a walkthrough of creating the sample scenario from scratch. I do assume you are familiar with Windows Azure Cloud Service, IIS manager and ASP.NET MVC in general, so some of the steps won’t be as details as for beginners.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Visual Studio 2012  &lt;li&gt;Windows 8 with IIS 8.0  &lt;li&gt;Windows Azure SDK&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;strong&gt;Step 1: Create a simple multi-site Web Role with a heavy workload simulator.&lt;/strong&gt;&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Create a new Cloud Service with a ASP.NET MVC4 Web Role.  &lt;li&gt;In &lt;strong&gt;Solution Explorer&lt;/strong&gt;, right-click on the Cloud Service project and select &lt;strong&gt;Properties….&lt;/strong&gt; Then, in &lt;strong&gt;Web&lt;/strong&gt; tab, change &lt;strong&gt;Local Development Server&lt;/strong&gt; to &lt;strong&gt;Use IIS Web Server&lt;/strong&gt;.  &lt;li&gt;Add a new &lt;strong&gt;CPUThrottleController&lt;/strong&gt; Controller with an empty &lt;strong&gt;Index&lt;/strong&gt; view.  &lt;li&gt;CPUThrottleController contains two methods: &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; ActionResult Index()
{
  &lt;span class="kwrd"&gt;return&lt;/span&gt; View();
}
&lt;span class="kwrd"&gt;public&lt;/span&gt; ActionResult HeavyLoad()
{
  &lt;span class="kwrd"&gt;int&lt;/span&gt; count = 4;
  &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; i = 0; i &amp;lt; count; i++)
  {
    ThreadPool.QueueUserWorkItem((obj) =&amp;gt;
    {
      Random rand = &lt;span class="kwrd"&gt;new&lt;/span&gt; Random();
      &lt;span class="kwrd"&gt;while&lt;/span&gt; (&lt;span class="kwrd"&gt;true&lt;/span&gt;) { rand.Next(); }
    });
  }
  &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; HttpStatusCodeResult(200);
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
The Index() method returns the Index view, which we’ll implement in a moment. The HeavyLoad() method simulates a CPU intensive work by creating a tight loop. Because my test machine has four logical processors, I used count 4 to make sure all of them are saturated. You can adjust this value according to your machine’s configuration. 
&lt;li&gt;Modify the Index view for &lt;strong&gt;CPUThrottleController&lt;/strong&gt; and add a Kill CPU link:&lt;pre class="csharpcode"&gt;@Html.ActionLink(&lt;span class="str"&gt;"Kill CPU"&lt;/span&gt;, &lt;span class="str"&gt;"HeavyLoad"&lt;/span&gt;);&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;li&gt;Now define the sites in Cloud Service project’s .csdef file: &lt;pre class="csharpcode"&gt;...
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Runtime&lt;/span&gt; &lt;span class="attr"&gt;executionContext&lt;/span&gt;&lt;span class="kwrd"&gt;="&lt;font style="background-color: #ffff00"&gt;elevated&lt;/font&gt;"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Sites&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Site&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="gold"&lt;/span&gt; &lt;span class="attr"&gt;physicalDirectory&lt;/span&gt;&lt;span class="kwrd"&gt;="&lt;font style="background-color: #00ff00"&gt;..\..\..\IIS8Features.Web&lt;/font&gt;"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Bindings&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Binding&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="Endpoint1"&lt;/span&gt; &lt;span class="attr"&gt;endpointName&lt;/span&gt;&lt;span class="kwrd"&gt;="Endpoint1"&lt;/span&gt;  &lt;span class="attr"&gt;hostHeader&lt;/span&gt;&lt;span class="kwrd"&gt;="&lt;font style="background-color: #ffc000"&gt;gold.haishibai.com&lt;/font&gt;"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Bindings&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Site&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Site&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="silver"&lt;/span&gt; &lt;span class="attr"&gt;physicalDirectory&lt;/span&gt;&lt;span class="kwrd"&gt;="&lt;font style="background-color: #00ff00"&gt;..\..\..\IIS8Features.Web&lt;/font&gt;"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Bindings&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Binding&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="Endpoint1"&lt;/span&gt; &lt;span class="attr"&gt;endpointName&lt;/span&gt;&lt;span class="kwrd"&gt;="Endpoint1"&lt;/span&gt;  &lt;span class="attr"&gt;hostHeader&lt;/span&gt;&lt;span class="kwrd"&gt;="&lt;font style="background-color: #ffc000"&gt;silver.haishibai.com&lt;/font&gt;"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
     &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Bindings&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Site&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Sites&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
...&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
Note: you’ll need to update &lt;span class="attr"&gt;&lt;font style="background-color: #00ff00"&gt;physicalDirectory values&lt;/font&gt; &lt;/span&gt;to reflect your own solution folder structure and Web Role project name. Also, I included instruction to run &lt;strong&gt;RoleEntry&lt;/strong&gt; with &lt;font style="background-color: #ffff00"&gt;elevated&lt;/font&gt; privilege, because we’ll need to reconfigure application pools, which needs administrative accesses. You can also update the &lt;font style="background-color: #ffc000"&gt;hostHeader values&lt;/font&gt; to use the values of your choice. 
&lt;li&gt;Edit your &lt;strong&gt;hosts&lt;/strong&gt; file under %sysemroot%\System32\Drivers\etc folder to include two lookup entries for above two &lt;font style="background-color: #ffc000"&gt;host names&lt;/font&gt;:&lt;pre class="csharpcode"&gt;127.255.0.0 gold.haishibai.com
127.255.0.0 silver.haishibai.com&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Step 2: Test the application without throttling&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Press &lt;strong&gt;F5&lt;/strong&gt; to start the application. You’ll see a browser with a 400 error – that’s expected. 
&lt;li&gt;Launch another browser and go to either &lt;a href="http://gold.haishibai.com:82"&gt;http://gold.haishibai.com:82&lt;/a&gt;&amp;nbsp; or &lt;a href="http://silver.haishibai.com:82"&gt;http://silver.haishibai.com:82&lt;/a&gt;. Note that on your system you may get a different port number. The way to get this port number is to open IIS manager and examine the binding of deployed sites:&lt;br clear="all"&gt;&lt;a href="http://lh4.ggpht.com/-fHFfqWer9zY/UGuPVtsyncI/AAAAAAAAAqc/7t0ZOeuYMys/s1600-h/image5.png"&gt;&lt;img title="image" 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="image" src="http://lh4.ggpht.com/-QqLkxIa7vxc/UGuPWKyElDI/AAAAAAAAAqk/OZ4LGh2Xu6w/image_thumb3.png?imgmax=800" width="711" height="377"&gt;&lt;/a&gt; 
&lt;li&gt;Start the &lt;strong&gt;Task Manager&lt;/strong&gt;. Arrange the browser window and Task Manager window side-by-side:&lt;br clear="all"&gt;&lt;a href="http://lh4.ggpht.com/-P5BLPKKD3U0/UGuPWpQWwjI/AAAAAAAAAqs/OOBuJcRls4g/s1600-h/image10.png"&gt;&lt;img title="image" 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="image" src="http://lh3.ggpht.com/-9jUGo0S7Q_E/UGuPXDefmZI/AAAAAAAAAq0/MR9EO-bilSA/image_thumb6.png?imgmax=800" width="712" height="384"&gt;&lt;/a&gt; 
&lt;li&gt;Now in the browser address, add /CPUThrottle then press enter. Then, click on the&lt;strong&gt; Kill CPU&lt;/strong&gt; link on the page. Watch CPUs go nuts:&lt;br clear="all"&gt;&lt;a href="http://lh6.ggpht.com/-AOJ-nxC9j2g/UGuPXQAhmSI/AAAAAAAAAq8/-BmmxXwuBWA/s1600-h/image15.png"&gt;&lt;img title="image" 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="image" src="http://lh5.ggpht.com/-Uu0jKnVteUg/UGuPYI_pggI/AAAAAAAAArE/Zhl2GvXlqfk/image_thumb9.png?imgmax=800" width="710" height="386"&gt;&lt;/a&gt; 
&lt;li&gt;Close BOTH browser window. Visual studio will clear up the web sites and corresponding application pools it created for you. And your CPU usage should drop back to normal.&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Step 3: Enable Throttling&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Add a reference to &lt;strong&gt;Microsoft.Web.Administration.dll&lt;/strong&gt; to your Web Role project (browse to %systemroot%\System32\inetsrv folder to find the assembly). 
&lt;li&gt;Modify the WebRole class to reconfigure application pools to enable CPU throttling: &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; WebRole : RoleEntryPoint
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; OnStart()
    {
        CustomerProfile[] profiles = 
        { &lt;span class="kwrd"&gt;new&lt;/span&gt; CustomerProfile{Name =&lt;span class="str"&gt;"gold"&lt;/span&gt;, CPUThrottle = 40000},
            &lt;span class="kwrd"&gt;new&lt;/span&gt; CustomerProfile{Name =&lt;span class="str"&gt;"silver"&lt;/span&gt;, CPUThrottle = 30000}};
        &lt;span class="kwrd"&gt;using&lt;/span&gt; (ServerManager serverManager = &lt;span class="kwrd"&gt;new&lt;/span&gt; ServerManager())
        {
            var applicationPools = serverManager.ApplicationPools;
            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (var profile &lt;span class="kwrd"&gt;in&lt;/span&gt; profiles)
            {
                var appPoolName = serverManager.Sites[RoleEnvironment.CurrentRoleInstance.Id + &lt;span class="str"&gt;"_"&lt;/span&gt; + profile.Name].Applications.First().ApplicationPoolName;
                var appPool = applicationPools[appPoolName];
                &lt;font style="background-color: #ffff00"&gt;appPool.Cpu.Limit = profile.CPUThrottle;
&lt;/font&gt;                &lt;font style="background-color: #ffff00"&gt;appPool.Cpu.Action = ProcessorAction.Throttle;
&lt;/font&gt;            }
            serverManager.CommitChanges();
        }
        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;base&lt;/span&gt;.OnStart();
    }
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;struct&lt;/span&gt; CustomerProfile
    {
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Name;
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; CPUThrottle;
    }
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
In above implementation, the OnStart() method finds the application pool each site is using, and then applies CPU throttling to each pool according to CustomerProfile settings. &lt;strong&gt;CPUThrottle&lt;/strong&gt; is the value of 1/1000 of CPU percentage (so, 10 percent is 10,000). This sets the upper limit of CPU power the application pool is allowed to use. You can see for “gold” users we are allowing up to 40%, while for silver users we are allowing up to 30%. &lt;strong&gt;ProcessorAction.Throttle&lt;/strong&gt; specifies when the throttling limit is hit, user requests should be throttled. There are other options such as KillW3wp (similar to what you get in IIS 7) and ThrottleUnderLoad. You can read more about these options on &lt;a href="http://www.iis.net"&gt;www.iis.net&lt;/a&gt;. 
&lt;li&gt;That’s all we have to do! Now launch the application again and try the Kill CPU link. You can see CPU consumption is well under control. If you want, you can launch another browser and navigate to the other site and do the same Kill CPU operation. Because collectively the applications are allowed to use up to 70% percent of CPU, the CPUs are not saturated in either case:&lt;br clear="all"&gt;&lt;a href="http://lh5.ggpht.com/-pLCXEvvTzh8/UGuPY8UGyTI/AAAAAAAAArM/gL_cJIm5kRg/s1600-h/image20.png"&gt;&lt;img title="image" 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="image" src="http://lh4.ggpht.com/-3dJ8tAiFZBo/UGzW0pddqpI/AAAAAAAAArk/DwAB6yJVLyQ/image_thumb12.png?imgmax=800" width="256" height="254"&gt;&lt;/a&gt;.&lt;/li&gt;&lt;/ol&gt;
&lt;h3&gt;Some additional notes&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;You can also configure the throttling settings via &lt;strong&gt;AppCmd&lt;/strong&gt;. For example, this command limits CPU consumption of DefaultAppPool to 30%:&lt;pre class="csharpcode"&gt;%systemroot%\system32\inetsrv\appcmd set apppool DefaultAppPool /cpu.limit:30000 /cpu.action:Throttle&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;li&gt;If you want to use appcmd in a startup task to configure the application pools, be aware that by the time the startup task runs, the application pools have not been created. As a workaround, you can use appcmd to change the default application pool settings so that all application pools created hereafter will be affected. However it’s not possible to set up different settings for different application pools:&lt;pre class="csharpcode"&gt;%systemroot%\system32\inetsrv\appcmd set config -section:system.applicationHost/applicationPools /applicationPoolDefaults.cpu.limit:90000 /commit:apphost&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;li&gt;After the sites are deployed, you can also change the setting in IIS manager UI – simply select the application pool you want to configure and bring up &lt;strong&gt;Advanced Settings&lt;/strong&gt;:&lt;br clear="all"&gt;&lt;a href="http://lh4.ggpht.com/-iS7S0lGVe3o/UGzW0-9QvUI/AAAAAAAAArs/L609f2pOB4M/s1600-h/image24.png"&gt;&lt;img title="image" 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="image" src="http://lh6.ggpht.com/-hqUG3wNqPcQ/UGzW1SLU1uI/AAAAAAAAAr0/agRTklgQDT8/image_thumb14.png?imgmax=800" width="349" height="426"&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;h3&gt;Part 1 Summary&lt;/h3&gt;
&lt;p&gt;In this post we created a multi-site Web Role for two levels of subscriptions – silver and gold. And then we configured corresponding application pools to ensure gold users have abundant CPU resources to use regardless the loads on the other group.&lt;/p&gt;  &lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/4AvWi0aVM_k" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/6833271788343991188/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2012/10/recipes-for-multi-tenant-cloud-service.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/6833271788343991188?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/6833271788343991188?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/4AvWi0aVM_k/recipes-for-multi-tenant-cloud-service.html" title="Recipes for Multi-tenant Cloud Service Design – Recipe 1: Throttling by Tenants Using Multi-site Cloud Services and IIS 8 CPU Throttling" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/-QqLkxIa7vxc/UGuPWKyElDI/AAAAAAAAAqk/OZ4LGh2Xu6w/s72-c/image_thumb3.png?imgmax=800" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2012/10/recipes-for-multi-tenant-cloud-service.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkAMRnk7cCp7ImA9WhJbEE4.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-728150960437690213</id><published>2012-09-18T23:06:00.001-07:00</published><updated>2012-09-18T23:06:27.708-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-09-18T23:06:27.708-07:00</app:edited><title>Claim-based access control for PHP running on IIS</title><content type="html">&lt;p&gt;The goal of this post is to introduce an easy way to enable claim-based access control on PHP applications running on an IIS server using WIF. Please note the specific requirement here – I want to utilize WIF as much as possible while keeping PHP side as simple as possible. The solution presented here is not necessarily the best choice when you want to enable claim-based access control on PHP applications. Probably a third-party PHP library or extension can serve the purpose better. On the other hand, if you are interested in reusing WIF FAM and SAM to protect a FastCGI application in general, this post may give you some ideas. In addition, the solution has an extra feature - It allows “SSO” between PHP pages and ASP.NET pages. Users only need to authenticate once and then will be able to access both types of pages freely with required claims available to them.&lt;/p&gt; &lt;p&gt;Because this is an advanced topic, I’ll assume you are familiar with the following concepts, Windows features and software:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Control panel (manage Windows features)  &lt;li&gt;Internet Information Service Manager  &lt;li&gt;Windows Azure ACS &lt;li&gt;WIF components such as FAM and SAM&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;However&amp;nbsp; I won’t assume you have much of PHP knowledge - the PHP codes we use are very basic and this is intentional. One key benefit of claim-based architecture is to allow application developers to focus on application logics instead of dealing with security details. In this example, the PHP code deals NOTHING related to security protocols or token processing. Although the final code is not quite satisfying, the spirit of claim-based architecture is kept true.&lt;/p&gt; &lt;p&gt;I’ll omit most of screenshots to make the post shorter because there are lots of steps here. However I’ll provide more details on key steps when necessary.&lt;/p&gt; &lt;h2&gt;Enable PHP on IIS&lt;/h2&gt; &lt;p&gt;First thing first, we need to install PHP on IIS. There are many articles on Internet talking about this topic. And the steps below are indeed abstracted from several of them.&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Before continue, you need to make sure you have IIS 7.0 installed with CGI feature enabled. This can be done via &lt;strong&gt;Turn Windows features on or off&lt;/strong&gt; dialog.  &lt;li&gt;Download PHP from &lt;a href="http://www.php.net/downloads.php"&gt;http://www.php.net/downloads.php&lt;/a&gt;. In this post I chose to use the &lt;a href="http://windows.php.net/downloads/releases/php-5.4.7-nts-Win32-VC9-x86.zip"&gt;PHP 5.4.7 VC9 x86 Non Thread Safe&lt;/a&gt; version. Unpack all files to a local folder, for example &lt;strong&gt;C:\PHP&lt;/strong&gt;.  &lt;li&gt;Open &lt;strong&gt;Internet Information Services Manager&lt;/strong&gt;.  &lt;li&gt;In &lt;strong&gt;Features&lt;/strong&gt; View at server level, double-click on &lt;strong&gt;Handler Mappings&lt;/strong&gt; icon.  &lt;li&gt;In &lt;strong&gt;Actions&lt;/strong&gt; pane, click &lt;strong&gt;Add Module Mapping…&lt;/strong&gt;  &lt;li&gt;Enter the following settings:  &lt;table cellspacing="0" cellpadding="2" width="252" border="1"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="top" width="104"&gt;Field&lt;/td&gt; &lt;td valign="top" width="146"&gt;Value&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="105"&gt;Request path&lt;/td&gt; &lt;td valign="top" width="146"&gt;*.php&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="105"&gt;Module&lt;/td&gt; &lt;td valign="top" width="146"&gt;FastCgiModule&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="105"&gt;Executable&lt;/td&gt; &lt;td valign="top" width="146"&gt;C:\PHP\PHP-CGI.EXE&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="105"&gt;Name&lt;/td&gt; &lt;td valign="top" width="146"&gt;PHP&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;li&gt;Click on &lt;strong&gt;Request Restrictions&lt;/strong&gt; button.  &lt;li&gt;On &lt;strong&gt;Mapping&lt;/strong&gt; tab, change mapping option to&lt;strong&gt; File or folder&lt;/strong&gt;.  &lt;li&gt;OK all the way back.  &lt;li&gt;Copy &lt;strong&gt;C:\PHP\php.ini-development&lt;/strong&gt; to &lt;strong&gt;C:\PHP\php.ini&lt;/strong&gt;.  &lt;li&gt;Find this line in &lt;strong&gt;php.ini&lt;/strong&gt;: &lt;pre class="csharpcode"&gt;&lt;font color="#ff0000"&gt;;&lt;/font&gt;fastcgi.impersonate = 1&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
remove the semi-colon to uncomment the setting. Save changes. 
&lt;li&gt;Back in &lt;strong&gt;Internet Information Service Manager&lt;/strong&gt;,&amp;nbsp; add a new &lt;strong&gt;Application&lt;/strong&gt; to &lt;strong&gt;Default Web Site&lt;/strong&gt;. Enter &lt;strong&gt;PHP&lt;/strong&gt; as &lt;strong&gt;Alias&lt;/strong&gt;, and pick a physical path, for example &lt;strong&gt;C:\PHP\Test&lt;/strong&gt;. Click &lt;strong&gt;OK&lt;/strong&gt; to create the application. 
&lt;li&gt;Create a &lt;strong&gt;index.php&lt;/strong&gt; under &lt;strong&gt;C:\PHP\Test &lt;/strong&gt;with a single line:&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="html"&gt;php&lt;/span&gt; &lt;span class="attr"&gt;echo&lt;/span&gt; &lt;span class="kwrd"&gt;'Hello PHP'&lt;/span&gt;; ?&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;li&gt;Save the file. 
&lt;li&gt;Navigate to http://localhost/PHP/index.php. You should see the Hello World page if everything works out.&lt;/li&gt;&lt;/ol&gt;
&lt;h2&gt;Enable FAM and SAM&lt;/h2&gt;
&lt;p&gt;Now we’ve have a PHP FastCGI module in our pipeline, let’s inject WIF modules on top of that so FAM can intercept incoming traffic and engage the ws-Federation dance as configured. Because this interception happens before the traffic reaches the FastCGI handler, it really doesn’t matter if the FastCGI module is for PHP or something else. It will work the same way.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Add a web.config file under C:\PHP\Test folder. The following is an example of such file:&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="html"&gt;xml&lt;/span&gt; &lt;span class="attr"&gt;version&lt;/span&gt;&lt;span class="kwrd"&gt;="1.0"&lt;/span&gt; &lt;span class="attr"&gt;encoding&lt;/span&gt;&lt;span class="kwrd"&gt;="UTF-8"&lt;/span&gt;?&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;configSections&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;section&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="system.identityModel"&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, &lt;br clear="all"&gt;             Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;section&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="system.identityModel.services"&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="System.IdentityModel.Services.Configuration.SystemIdentityModelServicesSection, &lt;br clear="all"&gt;             System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;configSections&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;system.webServer&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;validation&lt;/span&gt; &lt;span class="attr"&gt;validateIntegratedModeConfiguration&lt;/span&gt;&lt;span class="kwrd"&gt;="false"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;modules&lt;/span&gt; &lt;span class="attr"&gt;runAllManagedModulesForAllRequests&lt;/span&gt;&lt;span class="kwrd"&gt;="true"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="WSFederationAuthenticationModule"&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="System.IdentityModel.Services.WSFederationAuthenticationModule, &lt;br clear="all"&gt;           System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"&lt;/span&gt; &lt;span class="attr"&gt;preCondition&lt;/span&gt;&lt;span class="kwrd"&gt;="managedHandler"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="SessionAuthenticationModule"&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, &lt;br clear="all"&gt;           Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"&lt;/span&gt; &lt;span class="attr"&gt;preCondition&lt;/span&gt;&lt;span class="kwrd"&gt;="managedHandler"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;modules&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;system.webServer&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;system.web&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;httpRuntime&lt;/span&gt; &lt;span class="attr"&gt;requestValidationMode&lt;/span&gt;&lt;span class="kwrd"&gt;="2.0"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;pages&lt;/span&gt; &lt;span class="attr"&gt;validateRequest&lt;/span&gt;&lt;span class="kwrd"&gt;="false"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;authorization&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;deny&lt;/span&gt; &lt;span class="attr"&gt;users&lt;/span&gt;&lt;span class="kwrd"&gt;="?"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;authorization&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;authentication&lt;/span&gt; &lt;span class="attr"&gt;mode&lt;/span&gt;&lt;span class="kwrd"&gt;="None"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;compilation&lt;/span&gt; &lt;span class="attr"&gt;debug&lt;/span&gt;&lt;span class="kwrd"&gt;="true"&lt;/span&gt; &lt;span class="attr"&gt;targetFramework&lt;/span&gt;&lt;span class="kwrd"&gt;="4.5"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;system.web&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;system.identityModel&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;identityConfiguration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;audienceUris&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="http://localhost/PHP/"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;audienceUris&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;issuerNameRegistry&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="System.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, System.IdentityModel, &lt;br clear="all"&gt;                        Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;trustedIssuers&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;thumbprint&lt;/span&gt;&lt;span class="kwrd"&gt;="&lt;font style="background-color: #ffff00"&gt;{cert thumbprint}&lt;/font&gt;"&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="https://&lt;font style="background-color: #ffff00"&gt;{ACS namespace}&lt;/font&gt;.accesscontrol.windows.net/"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;trustedIssuers&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;issuerNameRegistry&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;certificateValidation&lt;/span&gt; &lt;span class="attr"&gt;certificateValidationMode&lt;/span&gt;&lt;span class="kwrd"&gt;="None"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;identityConfiguration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;system.identityModel&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;system.identityModel.services&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;federationConfiguration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;cookieHandler&lt;/span&gt; &lt;span class="attr"&gt;requireSsl&lt;/span&gt;&lt;span class="kwrd"&gt;="false"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;wsFederation&lt;/span&gt; &lt;span class="attr"&gt;passiveRedirectEnabled&lt;/span&gt;&lt;span class="kwrd"&gt;="true"&lt;/span&gt; &lt;span class="attr"&gt;issuer&lt;/span&gt;&lt;span class="kwrd"&gt;="https://&lt;font style="background-color: #ffff00"&gt;{ACS namespace}&lt;/font&gt;.accesscontrol.windows.net/v2/wsfederation"&lt;/span&gt; &lt;br clear="all"&gt;              &lt;span class="attr"&gt;realm&lt;/span&gt;&lt;span class="kwrd"&gt;="http://localhost/PHP/"&lt;/span&gt; &lt;span class="attr"&gt;reply&lt;/span&gt;&lt;span class="kwrd"&gt;="http://localhost/PHP/index.php"&lt;/span&gt; &lt;span class="attr"&gt;requireHttps&lt;/span&gt;&lt;span class="kwrd"&gt;="false"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;federationConfiguration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;system.identityModel.services&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;li&gt;Note you’ll need to update highlighted portions to match with your configurations.&lt;/li&gt;&lt;/ol&gt;
&lt;h2&gt;Configure ACS&lt;/h2&gt;
&lt;p&gt;Now our Relying Party is ready. We need to configure ACS to trust our RP. There’s nothing special here – just regular ACS configuration.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Log on to Windows Azure Management Portal. Don’t have an account yet? Sign up for &lt;strong&gt;&lt;font color="#ff0000"&gt;90 day trail &lt;/font&gt;&lt;/strong&gt;&lt;a href="http://www.windowsazure.com/en-us/pricing/free-trial/?WT.mc_id=A6D9C2617"&gt;here&lt;/a&gt;. 
&lt;li&gt;Navigate to the ACS namespace you want to manage. 
&lt;li&gt;Add a new Relying Party: 
&lt;table cellspacing="0" cellpadding="2" width="458" border="1"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign="top" width="181"&gt;&lt;strong&gt;Name&lt;/strong&gt;&lt;/td&gt;
&lt;td valign="top" width="275"&gt;&lt;strong&gt;PHP&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="181"&gt;&lt;strong&gt;Realm&lt;/strong&gt;&lt;/td&gt;
&lt;td valign="top" width="275"&gt;&lt;strong&gt;http://localhost/PHP/&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="181"&gt;&lt;strong&gt;Return URL&lt;/strong&gt;&lt;/td&gt;
&lt;td valign="top" width="275"&gt;&lt;strong&gt;http://localhost/PHP/index.php&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="181"&gt;Error URL (optional)&lt;/td&gt;
&lt;td valign="top" width="275"&gt;&amp;lt;leave empty&amp;gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="181"&gt;Token format&lt;/td&gt;
&lt;td valign="top" width="275"&gt;SMAL 2.0&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="181"&gt;Token encryption policy&lt;/td&gt;
&lt;td valign="top" width="275"&gt;None&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="181"&gt;Token lifetime (secs)&lt;/td&gt;
&lt;td valign="top" width="275"&gt;600&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="181"&gt;Identity providers&lt;/td&gt;
&lt;td valign="top" width="275"&gt;&amp;lt;identity provider(s) of your choice&amp;gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="181"&gt;Rule groups&lt;/td&gt;
&lt;td valign="top" width="275"&gt;&amp;lt;create new rule group, or reuse existing groups. Note when you sue a new group, you’ll need to go to the group and generate default rules&amp;gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;li&gt;Save changes&lt;/li&gt;&lt;/ol&gt;
&lt;h2&gt;Test&lt;/h2&gt;
&lt;p&gt;Now launch browser and navigate to http://localhost/PHP/index.php again. You’ll be redirected to IP login page, and you’ll gain access to &lt;strong&gt;index.php&lt;/strong&gt; after you log in. &lt;/p&gt;
&lt;h2&gt;Passing the Claims&lt;/h2&gt;
&lt;p&gt;So far so good! But we are far from finish yet. The biggest problem we are having now is that the PHP code doesn’t have access to the claims. It’s true that FedAuth cookies are available in request headers and I can simply ask PHP code to deal with them. However this will require the PHP code to understand security token handling, which is not as “claim-based”&amp;nbsp; as I wanted. I want to do something nicer – I’ll return the claims to PHP instead. Now how do I pass the claims? I can use session variables. However I need to remember that I’m talking about sharing session states between PHP and ASP.NET here. One possible solution is to use a common storage such as a database to share session data, and communicate session id between ASP.NET and PHP via a cookie so they can look up session data independently. In this example I’ll simply pass all claims via cookies. I don’t think DB access code is that exciting after all – the key is to extract the claims and pass them “somehow”.&lt;/p&gt;
&lt;p&gt; To do this, we need to customize SAM so that we can put the claims into cookies.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a new .Net class library targeting at .Net Framework 4.5. &lt;/li&gt;
&lt;li&gt;Add references to System.IdentityModel.dll and System.IdentityModel.Services.dll.&lt;/li&gt;
&lt;li&gt;Override SetPrincipalFromSessionToken of SessionAuthenticationModule class. This method is where WIF fill up IClaimsPrincipal for .Net thread. It seems like a natural place to make the claims available to PHP as well. Note the method calls into the base method first so that if there are ASP.NET pages in the same application they’d also work as normal:&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; PHPSample
{
  &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; MySessionAuthenticationModule : SessionAuthenticationModule
  {
    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; SetPrincipalFromSessionToken(System.IdentityModel.Tokens.SessionSecurityToken sessionSecurityToken)
    {
      &lt;span class="kwrd"&gt;base&lt;/span&gt;.SetPrincipalFromSessionToken(sessionSecurityToken);
      HttpContext.Current.Response.Cookies.Clear();
      &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (var claim &lt;span class="kwrd"&gt;in&lt;/span&gt; sessionSecurityToken.ClaimsPrincipal.Claims)
        HttpContext.Current.Response.Cookies.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; HttpCookie(claim.Type, claim.Value));
    }
  }
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/li&gt;
&lt;li&gt;Compile the assembly. Make a &lt;strong&gt;bin&lt;/strong&gt; folder under C&lt;strong&gt;:\PHP\Test &lt;/strong&gt;and copy the assembly under the &lt;strong&gt;bin&lt;/strong&gt; folder.&lt;/li&gt;
&lt;li&gt;Update web.config file to use the custom module: &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="SessionAuthenticationModule"&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="PHPSample.MySessionAuthenticationModule, PHPSample"&lt;/span&gt; &lt;span class="attr"&gt;preCondition&lt;/span&gt;&lt;span class="kwrd"&gt;="managedHandler"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/li&gt;
&lt;li&gt;To read the cookies on PHP side: &lt;pre class="csharpcode"&gt;&amp;lt;?php 
  echo &lt;span class="str"&gt;'Hello PHP!'&lt;/span&gt;; 
  $cookie=$_COOKIE;
  &lt;span class="kwrd"&gt;foreach&lt;/span&gt; ($cookie &lt;span class="kwrd"&gt;as&lt;/span&gt; $key=&amp;gt;$val)
    echo &lt;span class="str"&gt;"&amp;lt;br&amp;gt;$key--&amp;gt; $val"&lt;/span&gt;;
?&amp;gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/li&gt;
&lt;li&gt;Launch the application. This time you should see claims displayed on PHP page:&lt;br clear="all"&gt;&lt;a href="http://lh5.ggpht.com/-o2_TD18oF7k/UFlg4PAnqQI/AAAAAAAAAp4/rVc_n1mAf5o/s1600-h/image%25255B4%25255D.png"&gt;&lt;img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://lh3.ggpht.com/-xkBtI0WIRUI/UFlg4rFjxJI/AAAAAAAAAqA/V9Sne0OZIxY/image_thumb%25255B2%25255D.png?imgmax=800" width="714" height="336"&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;Of course there are much more can be done here – such as passing claims via sessions instead of cookies, wrapping up the claims to simulate similar behavior of IClaimsPrincipal, and implementing sign out, etc. But these are out of the scope of this post.&amp;nbsp; I wish you enjoyed reading the long post.&amp;nbsp; And now, I’ll go to watch some recorded Bing Bang Theory episodes. Good night.&lt;/p&gt;  &lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/abYnMXvHukw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/728150960437690213/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2012/09/claim-based-access-control-for-php.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/728150960437690213?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/728150960437690213?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/abYnMXvHukw/claim-based-access-control-for-php.html" title="Claim-based access control for PHP running on IIS" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/-xkBtI0WIRUI/UFlg4rFjxJI/AAAAAAAAAqA/V9Sne0OZIxY/s72-c/image_thumb%25255B2%25255D.png?imgmax=800" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2012/09/claim-based-access-control-for-php.html</feedburner:origLink></entry></feed>
