<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><title>The .NET Addict&apos;s Blog</title><link>http://dotnetaddict.dotnetdevelopersjournal.com/</link><description>The obsessive ramblings of a man hopelessly addicted to all things programming, including .NET, C#, Networking, Gaming, and much more.</description><copyright>Copyright 2010 dotnetaddict.dotnetdevelopersjournal.com</copyright><generator></generator><lastBuildDate>Thu, 18 Mar 2010 14:08:00 GMT</lastBuildDate><image><title>The .NET Addict&apos;s Blog</title><url>http://files.blog-city.com//files/J05/88284/p/f/penfold.jpg</url><link>http://dotnetaddict.dotnetdevelopersjournal.com/</link></image><ttl>360</ttl><docs>http://backend.userland.com/rss</docs><item><title>Windows Phone 7 Series, Initial Developer Impressions</title><guid isPermaLink="true">http://dotnetaddict.dotnetdevelopersjournal.com/initial_wp7_impressions.htm</guid><link>http://dotnetaddict.dotnetdevelopersjournal.com/initial_wp7_impressions.htm</link><pubDate>Thu, 18 Mar 2010 14:08:00 GMT</pubDate><comments>http://dotnetaddict.dotnetdevelopersjournal.com/console/comments/popup/?f=initial%5Fwp7%5Fimpressions</comments><dc:creator>Kevin Hoffman</dc:creator><description><![CDATA[<p>Windows Phone 7 Series (hereafter I&#39;ll just call it WP7) debuted a while ago at a press event but it&#39;s true coming out party was this past week at MIX 2010. This conference is a designer-developer hybrid conference and, of all the Microsoft development conferences I&#39;ve ever attended, this has consistently been the most informative and exciting of the bunch.</p><p>In case you&#39;ve been hiding under a rock this past week, Microsoft has been showing off WP7 and the development experience for it. I&#39;m going to oversimplify here, but this is the basic idea: You can choose to either develop for the platform in Silverlight or you can use the XNA toolkit normally used for building XBox and PC games in C#. WP7 has all the trimmings including push notifications, rich GUI (hardware accelerated), rich audio, the full power of Silverlight&#39;s media control, and it even has Xbox live integration allowing you to unlock achievements by playing games on the phone. Development tool is standard Visual Studio and for the Silverlight model you can use Expression Blend 4 to build you GUI (and there are some fantastic new improvements in Blend 4).</p><p>I&#39;m going to talk mostly about the Silverlight experience here since the last time I used XNA it was in beta and XNA has come a <strong><em>long</em></strong> way since then and I couldn&#39;t possibly do it justice. Your application is made of up pages (this concept should be familiar to SL3 developers), with each page acting like a specialized SL user control. These pages can have an application bar, which is similar to an iPhone tab bar control. The difference is that when you tap the elipsis (&quot;...&quot;) on the WP7 app bar, the app bar expands without you losing context while the iPhone tab bar &quot;more&quot; button transitions you to a fairly bland table view controller. At this point you can do pretty much anything you would normally be able to do in Silverlight, but you also get things like raw access to audio from the microphone, pickers for all native types of data on the phone like contacts, etc and the ability to send e-mails and SMS - all the stuff you&#39;d expect to have.</p><p>So, how does it feel to code for this thing and, more importantly, how does it compare to writing iPhone apps? First, let me preface this by saying that I&#39;ve been writing iPhone apps off and on since before the SDK came out and we had to &quot;fake it&quot; with clever CSS and HTML and for the past few months I&#39;ve been seriously writing heavy duty iPhone apps for real businesses. On many occasions over the past few months, I&#39;ve said that developing for the iPhone was &#39;fun&#39; and &#39;what coding should be like&#39;. That said, I have also forcibly rammed my head into my desk out of frustration with certain aspects of the iPhone development process.</p><p>Writing apps that look and feel like iPhone apps that look just like every other iPhone application is a task that takes little to no effort. I can go from empty project to a data-driven table view controller on the iPhone in pretty much no time at all. I can also do the same thing on the WP7 tools in about the same amount of time. Where the two begin to diverge is when I want to start customizing. I won&#39;t go into painful detail here because I plan on making a bunch of blog posts about WP7 and comparing it to the iPhone later. There are a few points that I want to make, however:</p><p><strong>Push Notifications</strong></p><p>As I said, I plan on delving into individual topics as I blog more about this, but I wanted to bring this up specifically. Dealing with the App Store and with the Developer Portal in general on the iPhone is a headache at best. When you add into it the juggling, management, and eventual botching of certificates and provisioning profiles, the mess gets even worse. Now you add into it the debacle of getting certificates based on provisioning profiles that are used by your servers to send push notifications to registered iPhone devices and it can bring the strongest of men to weeping on his knees. From firsthand experience, the act of getting your first push notification to work on an iPhone/iPod touch application is akin to climbing mount everest and when you get to the top you&#39;re thinking, &quot;#@*! I have to do this again!?&quot; With Apple, the phone contacts Apple to get a notification token (assuming the application is using a provisioning profile configured for notifications), the token then has to be sent by the app&#39;s code to the app owner&#39;s server for storage. That server needs to be configured with the right certificates to that it can send a proprietary binary package of goo containing the notification to Apple&#39;s servers, which will eventually make its way down to your app. Trust me, getting this to work is a victorious moment, preceded by weeks of eye-gouging pain.</p><p>Here&#39;s how it works with WP7: App gets a unique notification URI that represents notifications for that app on that device. App sends the URI to the app owner&#39;s server. When you want to send a notification, HTTP POST the contents of that notification (XML payload) to Microsoft&#39;s notification server. That&#39;s it. Done.</p><p>Small side note here: I like that you can send <em>unobtrusive toasts</em> with WP7 far better than sending modal dialog boxes with iPhone, they feel more like the Palm Pre notifications than iPhone dialogs.&nbsp;There are no certificates and private keys to manage, there are no provisioning profiles to deal with, there are no certificates required to be present on the notification sending server and there is no management portal you have to go to in order to maintain this stuff. For the first time recent history, Microsoft took the &quot;it just works&quot; approach whereas Apple&#39;s is hideously and unnecessarily complex.</p><p><strong>GUI Customization</strong></p><p>I alluded to this earlier in the post. If what I want to do is display two rows of textual information in a table view cell, then the iPhone gives me that out of the box and my application will feel perfectly at home on the device. However, when I want to mix in some icons and some other gauges and indicators that might not fall into the existing line-up of controls, I quickly drop from feeling safe and secure to feeling like I&#39;m back in the&nbsp;low-level Windows programming days of yore where everything I do needs to be a custom view with a custom render/paint method. It gets tedious, difficult, and time-consuming FAST. </p><p>Because WP7 lets me do all this stuff in Silverlight, I can use the advanced, composited, declarative UI to do truly remarkable things in very little time at all. I could make the cells in my table view (list view or grid in SL) have three rows and put whatever controls I want in there. Creating a type of UI that doesn&#39;t exist in the stock toolbox in Silverlight is easy... doing the same in the iPhone feels positively primitive by comparison.</p><p><strong>Overall Experience</strong></p><p>As you&#39;ll see in the blog posts I&#39;m planning on doing, WP7 development is like a&nbsp; breath of fresh air. It&#39;s funny, because I remember saying that when I first got my hands on the iPhone SDK and I was comparing iPhone development to Compact Framework for Windows Mobile. Cast aside all your preconceived notions about all previous versions of Microsoft mobile OS development - this is something entirely new. Also, keep in mind that when you build your mobile app in Silverlight, if you do it with a little forethought, you could potentially share 90+% of your code for an app that works on WP7, on a PC, and on a Mac.</p><p>I will still build apps for the iPhone, but only because people continue to want to pay me to do so. From now on, my mobile development for pleasure is going to be entirely WP7 based.</p><p>&nbsp;</p>]]></description><category>iphone</category><category>cocoa</category><category>dotnet</category><category>wp7</category><category>silverlight</category><category>xna</category><category>mix10</category><category>mix</category></item><item><title>Html.JqGrid - Cleaning up your jqGrid Code</title><guid isPermaLink="true">http://dotnetaddict.dotnetdevelopersjournal.com/html_jqgrid.htm</guid><link>http://dotnetaddict.dotnetdevelopersjournal.com/html_jqgrid.htm</link><pubDate>Tue, 22 Dec 2009 20:46:00 GMT</pubDate><comments>http://dotnetaddict.dotnetdevelopersjournal.com/console/comments/popup/?f=html%5Fjqgrid</comments><dc:creator>Kevin Hoffman</dc:creator><description><![CDATA[<p>I was recently working on a project where I had 5 or 6 different pages, each of which was going to have a full CRUD-enabled jqGrid complete with form editing, date pickers, fields that show up in the form and not on the grid, etc. The problem is after I got finished doing the first one I realized that there was a truckload of really redundant jqGrid code that I didn&#39;t want to have to re-type over and over again. Worse, the code is really fragile and if you misplace a comma, bracket, brace, or paren - the debugging of it will give you migraines.</p><p>So this is when I decided to write an HTML helper extension, <strong>JqGridExtension</strong>. This class exposes a single method called JqGrid that you invoke like this from your view page:</p><pre>&lt;%= <strong>Html.JqGrid&lt;ApplicationUser&gt;</strong>(<br />    caption:&quot;Users&quot;,<br />    entityNameCaption:&quot;User&quot;,<br />    gridWidth:700,<br />    formHeight:500,<br />    formWidth:600,<br />    pagerDivName:&quot;pager&quot;,<br />    gridTableName:&quot;userGrid&quot;,<br />    gridDataUrl:Url.Action(&quot;GridData&quot;, &quot;User&quot;),<br />    gridEditUrl:Url.Action(&quot;SaveUser&quot;, &quot;User&quot;),<br />    gridValidateEditUrl:Url.Action(&quot;GridValidateUserEdit&quot;, &quot;User&quot;),<br />    gridValidateDeleteUrl:Url.Action(&quot;GridValidateUserDelete&quot;, &quot;User&quot;))<br />%&gt; </pre><p>In this code example, you can see that I&#39;m creating a full CRUD grid with form editing (and paging, sorting, and filtering!). The cool part here is that I haven&#39;t littered my page with 100+ lines of incredibly difficult to read parameters to the jqGrid plugin. The HTML extension is just a method on a static class that returns a string, like this:</p><pre>public static class JqGridExtensions<br />{<br />public static string JqGrid&lt;T&gt;(this HtmlHelper helper,<br />    string caption,<br />    string entityNameCaption,<br />    int gridWidth,<br />    int formHeight,<br />    int formWidth,<br />    string pagerDivName,<br />    string gridTableName,<br />    string gridDataUrl,<br />    string gridEditUrl,<br />    string gridValidateEditUrl,<br />    string gridValidateDeleteUrl) { .... }<br /></pre><p>The code then just uses these parameters to spit out all of the tedious jqGrid code that I don&#39;t want to have to re-write all the time. There&#39;s another little piece of trickery here that I found extremely useful - I&#39;m using a custom attribute that I&#39;m decorating my viewmodel properties with. This custom attribute tells my jqgrid extension how it should handle that column - including whether the column is visible in the grid, visible in the form, editable, what the editor type is (text, datepicker, etc).</p><p>All I&#39;m really doing is getting the list of public instance properties on typeof(T). For each of those, I grab my custom attribute (<strong>JqGridColModelAttribute</strong>) and use the properties on that to build the &quot;colModel&quot; and &quot;columns&quot; jqGrid options and then finally I rig up the navigator and all the other stuff. Because the enterprise&#39;s use of grids is standardized to always have a certain set of options, I don&#39;t need to even prompt the developer for those - I just implement them the same way throughout the organization. If I need to make organization-wide changes to all of my grids, then I can just tweak my HTML helper method.</p><p>Creating an HTML helper extension like this takes very little time to do, but saves the developers on your team a TON of time.</p>]]></description><category>jquery</category><category>javascript</category><category>jqgrid</category><category>grid</category><category>aspnet</category><category>mvc</category><category>mvc2</category></item><item><title>Debugging EXC_BAD_ACCESS Errors with NSZombieEnabled</title><guid isPermaLink="true">http://dotnetaddict.dotnetdevelopersjournal.com/debug_iphone_nszombie.htm</guid><link>http://dotnetaddict.dotnetdevelopersjournal.com/debug_iphone_nszombie.htm</link><pubDate>Tue, 15 Dec 2009 15:25:00 GMT</pubDate><comments>http://dotnetaddict.dotnetdevelopersjournal.com/console/comments/popup/?f=debug%5Fiphone%5Fnszombie</comments><dc:creator>Kevin Hoffman</dc:creator><description><![CDATA[<p>One of the biggest problems developers have when building apps for the iPhone is memory violations. A lot of developers, especially those who come from a Java or .NET background, have trouble adjusting to an environment where they need to manually keep track of reference counts and they need to be explicitly aware of their own memory management.</p><p>I&#39;ve known quite a few developers who tried their hand at programming for the iPhone and they threw up their hands and quit when they started trying to track down memory problems. I&#39;m certainly not condoning that kind of behavior, I&#39;m just recognizing that the lack of built-in garbage collection represents both a learning curve and a frustration obstacle for new iPhone developers, whether they&#39;ve been doing other programming for 2 or 20 years.</p><p>Thankfully, there&#39;s something you can do about it. One of the biggest problems people get is an EXC_BAD_ACCESS error that terminates their debug session, but the callstack is empty and it&#39;s nearly impossible to figure out which method call caused the problem. There are several causes for <strong>EXC_BAD_ACCESS</strong> but the #1 most common cause for this is the attempt to send a message to a released object. The problem arises from the fact that since the released object isn&#39;t there, the bad access occurs and the call stack goes away before the debugger stops.</p><p>This is where <strong>NSZombie</strong> comes in. NSZombie is quite possibly one of the coolest, most clever tricks I&#39;ve ever seen in a programming environment. The way it works is, when you have zombies enabled (will show you how to do this in a second), a released object becomes a <em>zombie</em> when released. What this really means is that instead of deallocating and moving on, the original object is deallocated and an instance of NSZombie is left in its place. The sole purpose of NSZombie is to yell at you whenever someone tries to send it a message. Any message sent to a zombie will halt the debugger and put an entry in your console log telling you that you just tried to send a message to a released object.</p><p>I cannot even begin to describe how useful this is. This preserves the call stack so that you can see the exact line of code that sent a message to the released object. While this won&#39;t necessarily tell you what you did to prematurely release the object (premature release... too funny), it will tell you which object was released and what message you were trying to send and it&#39;ll preserve the call stack to give you other valuable debugging information.</p><p>To enable NSZombies all you need to do is double-click the application file in your &quot;Executables&quot; group and go to the parameters tab. At the bottom you&#39;ll see an area to configure environment variables. Add an environment variable called NSZombieEnabled and set its value to YES. Your screen should look like the screenshot below:&nbsp;</p><p>&nbsp;<img src="http://files.blog-city.com/files/J05/88284/p/f/nszombie.png" alt="" /></p><p>Now that zombies are enabled, you will be able to run your application and know that when you send a message to a released object, you&#39;re going to get a nice friendly execution termination, complete with call stack. You&#39;ll know which message was sent and you&#39;ll know which objects have been released because when you hover over them after the break, you&#39;ll see which ones are concrete instances (still alive) and which ones have been released (they&#39;ll be an instance of NSZombie).</p><p>Moral of the story: Not only are the undead good for entertainment value and destroying the earth in an unforgiving plague of destruction, but they&#39;re handy debugging tools as well.</p>]]></description><category>iphone</category><category>memory</category><category>debugging</category><category>nszombie</category></item><item><title>Would you like to touch my mono?</title><guid isPermaLink="true">http://dotnetaddict.dotnetdevelopersjournal.com/monotouch_or_not.htm</guid><link>http://dotnetaddict.dotnetdevelopersjournal.com/monotouch_or_not.htm</link><pubDate>Mon, 23 Nov 2009 14:59:00 GMT</pubDate><comments>http://dotnetaddict.dotnetdevelopersjournal.com/console/comments/popup/?f=monotouch%5For%5Fnot</comments><dc:creator>Kevin Hoffman</dc:creator><description><![CDATA[<p>Those of you who have been reading my blog for a while know that I&#39;m not always just about .NET - I&#39;m a pretty huge iPhone guy as well. In fact, I&#39;m a fan of all technologies and programming languages that don&#39;t suck, regardless of who makes them or on&nbsp;what platform they run.</p><p>At one point I was actually thinking about writing a book for .NET developers to learn Cocoa but other plans, time constraints, and life issues all got in the way. I have posted countless times comparing the worlds of Cocoa and .NET and have twice presented at Apple&#39;s WWDC comparing both the desktop and mobile programming environments of Apple and Microsoft. So you can imagine the raw, unfiltered, pure geek joy that coursed through my veins when I heard about <a href="http://monotouch.net/" target="_blank" title="Monotouch Website"><strong>Monotouch</strong></a>, a programming library coupled with an IDE (MonoDevelop + Interface Builder) that would let me <em>write my iPhone applications using C# and the .NET Framework</em> (the mono version).</p><p>To get Monotouch working you&#39;re going to need the following:</p><ul><li>A Mac. <ul><li>Intel</li><li>Running Leopard or Snow Leopard</li><li>Decently fast (a current Macbook Air is about the slowest I can tolerate for compilations)</li></ul></li><li>Monotouch Framework (can download the eval free)</li><li>MonoDevelop - IDE for mono and monotouch, <em>for the Mac, NOT Windows or linux!</em></li><li>$500 for the professional edition, $3500 for the enterprise edition. You can evaluate for free, but you can&#39;t put a monotouch app on an actual piece of hardware without forking over the duckets.</li></ul><p>Understanding all of the plumbing&nbsp;of how this works requires a time investment that I just can&#39;t put forth right now. So, for now, assume that little magic elves within the MonoDevelop IDE perform post-build tasks on your compiled mono application that can then convert it to native iPhone code. When you&#39;re working with C# classes like <em>UITableViewController</em>, all you&#39;re really doing is telling the post-compile steps that your final C type in the native app will be a <em>UITableViewController</em>. It&#39;s smoke and mirrors, but it&#39;s damned powerful smoke and mirrors.</p><p>So what&#39;s it like to build a monotouch application? It&#39;s actually pretty similar to building a regular Cocoa Touch application. You create a new project in monotouch (there are several really good &quot;hello world&quot; tutorials available on monotouch from their site). Drag UI elements into your XIB using Interface Builder and, here&#39;s where some of the magic starts, create outlets and actions and <em>link your C# code to your interface builder UI elements</em>. I am pretty sure portions of my brain liquified when I first created a C# view controller and ctrl-dragged to link UI actions to the controller.</p><p>This is where many of my avid .NET readers are going to think I&#39;ve simply flipped and gone off the reservation...</p><p>Despite the fact that I can now <em>quickly and easily</em> create <em>C#/.NET</em> classes and use them to power my iPhone applications, which gives me access to things like WCF and the <em>absolutely, definitively better</em> XML libraries of .NET... I am not going to be using monotouch for real application development.</p><p>ok, I&#39;ll pause here to let you all stop shouting, &quot;OMFGWTFTRAITOR!!!1&quot;</p><p>A little history: I learned C# in 2000 on .NET 1.0. I published my first book on the .NET Framework in 2001 and have been writing blogs, books, articles, and flaming truckloads of code on this framework for the past 9 years now. If there ever was a human being on the planet who should by all rights reach out to and lovingly hug the Monotouch box - it should be me. <em>However</em>, all of that time and experience has made me wary of layers of abstraction. I learned how to write Cocoa for the Mac when Leopard was in beta. I found the learning curve steep, and painful. I felt like I was being deprogrammed - but it was a good thing. If you remember my blog posts from that era, you&#39;ll recall that I felt like I was growing as a programmer and architect. My skills in .NET increased dramatically as a result of the enlightenment that I found while learning Cocoa and Objective-C. My .NET skills also increased (though not as dramatically) when I suffered through writing enterprise Java applications.</p><p>I literally spent hours trying to write down the list of reasons why I didn&#39;t want to use Monotouch and some of them were extremely valid reasons concerning the fact that monotouch is always going to be behind the leading SDK revision from Apple and blah blah yadda yadda... The bottom line is <em>I just love the way it feels to write Objective-C and Cocoa code.</em> Period. </p><p>Bottom line:</p><p><strong>[self heart:Cocoa];</strong></p><p>That said, there are a thousand reasons for people to use monotouch, including the ability to re-use .NET (mono) code across the client (iPhone) and server as well as to allow .NET developers who have absolutely no experience with Cocoa or Objective-C to quickly and easily get rolling building iPhone apps. In the real world we don&#39;t always have the luxury of learning new languages and environments - if you&#39;re a .NET developer and your boss tells you write an iPhone app for your company and to do it in 3 weeks or you&#39;re fired - you&#39;re going to use Monotouch (and so would I). I have the luxury of knowing both .NET and Cocoa and so I can pick and choose. Knowing both, I&#39;ll be writing my iPhone apps in Cocoa and the back-end servers that support them in .NET.</p>]]></description><category>cocoa</category><category>objectivec</category><category>apple</category><category>iphone</category><category>monotouch</category><category>mono</category><category>monodevelop</category></item><item><title>Getting the ASP.NET Providers working on the Azure Nov 2009 CTP</title><guid isPermaLink="true">http://dotnetaddict.dotnetdevelopersjournal.com/asp_providers_nov09_azure.htm</guid><link>http://dotnetaddict.dotnetdevelopersjournal.com/asp_providers_nov09_azure.htm</link><pubDate>Mon, 16 Nov 2009 01:01:00 GMT</pubDate><comments>http://dotnetaddict.dotnetdevelopersjournal.com/console/comments/popup/?f=asp%5Fproviders%5Fnov09%5Fazure</comments><dc:creator>Kevin Hoffman</dc:creator><description><![CDATA[<p>If you&#39;ve been trying to get the ASP.NET providers working on the November 2009 CTP of Windows Azure then you may have run into a snag, or a couple snags if you&#39;re using Visual Studio 2010.</p><p>First of all, if you&#39;re using Visual Studio 2010 Beta 2, then you&#39;re going to need to either up-convert the AspProviders project. For this, you want to go and grab the AspProviders (VS2008) sample from the <a href="http://code.msdn.microsoft.com/windowsazuresamples">Azure Code Samples</a> home page. Once you&#39;ve got it, you can either compile it in Visual Studio 2008 or, if you&#39;re coding in VS2010 Beta 2, you can either reference the compiled binary directly or just up-convert the project to VS2010 Beta 2.</p><p>The new AspProviders sample uses the new <em>Microsoft.WindowsAzure.StorageClient</em> library that now comes with the new version of the SDK. This version of the storage client is more robust, better supported, and more efficient than the sample storage client from previous versions of the SDK.</p><p>First, you&#39;re going to want to rig up your Web.config to use the new provider with elements like this:</p><pre>&lt;membership defaultProvider=&quot;TableStorageMembershipProvider&quot; <br />userIsOnlineTimeWindow = &quot;20&quot;&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;providers&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;clear/&gt;</pre><pre>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;add name=&quot;TableStorageMembershipProvider&quot;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type=&quot;Microsoft.Samples.ServiceHosting.AspProviders.TableStorageMembershipProvider&quot;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; description=&quot;Membership provider using table storage&quot;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; applicationName=&quot;AspProvidersDemo&quot;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enablePasswordRetrieval=&quot;false&quot;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enablePasswordReset=&quot;true&quot;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; requiresQuestionAndAnswer=&quot;false&quot;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; minRequiredPasswordLength=&quot;1&quot;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; minRequiredNonalphanumericCharacters=&quot;0&quot;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; requiresUniqueEmail=&quot;true&quot;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; passwordFormat=&quot;Hashed&quot;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /&gt;</pre><pre>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/providers&gt;<br />&nbsp;&nbsp;&nbsp; &lt;/membership&gt;</pre><pre>&nbsp;&nbsp;&nbsp; &lt;roleManager enabled=&quot;true&quot; defaultProvider=&quot;TableStorageRoleProvider&quot; <br />cacheRolesInCookie=&quot;true&quot; cookieName=&quot;.ASPXROLES&quot; cookieTimeout=&quot;30&quot;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cookiePath=&quot;/&quot; cookieRequireSSL=&quot;false&quot; cookieSlidingExpiration = &quot;true&quot;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cookieProtection=&quot;All&quot; &gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;providers&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;clear/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;add name=&quot;TableStorageRoleProvider&quot;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type=&quot;Microsoft.Samples.ServiceHosting.AspProviders.TableStorageRoleProvider&quot;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; description=&quot;Role provider using table storage&quot;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; applicationName=&quot;AspProvidersDemo&quot;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/providers&gt;<br />&nbsp;&nbsp;&nbsp; &lt;/roleManager&gt;</pre><pre>&nbsp;&nbsp;&nbsp; &lt;!--&lt;profile enabled=&quot;true&quot; defaultProvider=&quot;TableStorageProfileProvider&quot;<br /> inherits=&quot;UserProfile&quot;&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;providers&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;clear/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;add name=&quot;TableStorageProfileProvider&quot;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type=&quot;Microsoft.Samples.ServiceHosting.AspProviders.TableStorageProfileProvider&quot;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; description=&quot;Profile provider using structured storage&quot;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; applicationName=&quot;AspProvidersDemo&quot;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/providers&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --&gt;&lt;!--&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;properties&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;add name=&quot;Country&quot; type=&quot;string&quot;/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;add name=&quot;Gender&quot; type=&quot;string&quot;/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;add name=&quot;Age&quot; type=&quot;Int32&quot;/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/properties&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --&gt;&lt;!--<br />&nbsp;&nbsp;&nbsp; &lt;/profile&gt;--&gt;</pre><pre>&nbsp;&nbsp;&nbsp; &lt;sessionState mode=&quot;Custom&quot; customProvider=&quot;TableStorageSessionStateProvider&quot;&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;providers&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;clear /&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;add name=&quot;TableStorageSessionStateProvider&quot;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type=&quot;Microsoft.Samples.ServiceHosting.AspProviders.TableStorageSessionStateProvider&quot;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; applicationName=&quot;AspProvidersDemo&quot;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/providers&gt;<br />&nbsp;&nbsp;&nbsp; &lt;/sessionState&gt;</pre><p>You might have noticed that I&#39;ve commented out the profile provider. This is because if you use the profile provider, you might run into a problem where an exception is thrown at runtime (during app startup) that complains about you attempting to access an unloaded AppDomain. Microsoft is aware of this and I&#39;m expecting to shortly see a workaround, fix, or an update to the SDK. In the meantime, just comment out the profile provider and you&#39;ll be able to use the provider samples as-is.</p><p>Keep checking back here for more blog posts on using the new Nov 09 CTP of Windows Azure and any potential updates/fixes to this particular issue with the profile provider.</p>]]></description><category>azure</category><category>ctp</category><category>aspnet</category><category>providers</category></item><item><title>Working with Table Storage on the Windows Azure November 2009 CTP</title><guid isPermaLink="true">http://dotnetaddict.dotnetdevelopersjournal.com/azure_nov09_tablestorage.htm</guid><link>http://dotnetaddict.dotnetdevelopersjournal.com/azure_nov09_tablestorage.htm</link><pubDate>Sun, 15 Nov 2009 14:37:00 GMT</pubDate><comments>http://dotnetaddict.dotnetdevelopersjournal.com/console/comments/popup/?f=azure%5Fnov09%5Ftablestorage</comments><dc:creator>Kevin Hoffman</dc:creator><description><![CDATA[<p>If you&#39;ve been working with Azure for a while then you&#39;ve probably spent some time using the <strong>StorageClient</strong> <em>sample</em> that came with previous versions of the SDK. With the November 2009 release of the SDK (the one they&#39;ll be using at <strong>PDC 2009</strong>), they have wrapped that sample up into the SDK and refactored it to fit more in line with the conventions and quality standards of a Microsoft API. As a result, some of your code will break (but not much). Queue storage and Blob storage (discussed in upcoming posts) actually have more breaking changes than table storage.</p><p>Table storage, under the hood, is exposed as an ADO.NET Data Service (formerly Astoria). As a result, if you&#39;ve used the <em>System.Data.Services.Client</em> library before, you&#39;ve already got a leg up in interacting with Azure Storage.</p><p>When you&#39;re working with table storage, there are a few things that you&#39;re going to need. Once you&#39;ve got these, you&#39;re good to go:</p><ul><li>References to <em>System.Data.Services.Client</em> and <em>Microsoft.WindowsAzure.StorageClient</em> (obviously you also need a reference to service runtime if you&#39;re hitting table storage from within the cloud itself... remember that you can hit table storage from the desktop too, e.g. from WPF applications).</li><li>Credentials. There have been some changes to the way storage client credentials work that are beyond the scope of this post, but you can still use the same accountname/account shared key pattern that you used in the past.</li><li>A <em>DataServiceContext</em>. You&#39;re going to need this to interact with the tables in table storage. As you&#39;ll see in the code below, the pattern is to create your own context that derives from the base and exposes your tables as <em>IQueryable</em>s. If you&#39;ve ever worked with ADO.NET Data Services or Entity Framework before, this pattern should also look familiar.</li><li>Entity objects. Every table that you have in table storage contains arbitrary columns. In other words, if you really wanted, you could have a different schema for every row in your table. However, to work with it using the&nbsp;Data Services client, each row needs to conform to a fixed schema - this fixed schema you&#39;ll represent with a&nbsp;regular C# class that contains the necessary partition key and row key&nbsp;properties. This class also needs a parameterless constructor (required by the data services client to&nbsp;reconstitute instances of that&nbsp;class from the HTTP results)</li><li>The cloud&nbsp;table client. This new class&nbsp;will let you create tables and test for the existence of tables. You do not need to use this class for querying&nbsp;table storage, it&#39;s more of an administrative class for dealing with table storage itself.&nbsp;&nbsp;&nbsp;</li></ul><p>The first thing we&#39;re going to want to do is get the credentials. The new SDK allows us to dynamically determine if we&#39;re running in a fabric or running as a standalone app (which allows us to build apps that we can run on-premise OR in the cloud!). Here&#39;s some code I used to get the configuration settings for the account name and shared key:</p><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><p>string<font face="Consolas" size="2"><font face="Consolas" size="2"> accountKey = </font></font><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af">ConfigurationManager</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">.AppSettings[</font></font><font face="Consolas" size="2" color="#a31515"><font face="Consolas" size="2" color="#a31515"><font face="Consolas" size="2" color="#a31515">&quot;AccountSharedKey&quot;</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">];<br /></font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">string</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> tableBaseUri = </font></font><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af">ConfigurationManager</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">.AppSettings[</font></font><font face="Consolas" size="2" color="#a31515"><font face="Consolas" size="2" color="#a31515"><font face="Consolas" size="2" color="#a31515">&quot;TableStorageEndpoint&quot;</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">];<br /></font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">if</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> (</font></font><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af">RoleEnvironment</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">.IsAvailable)<br />{<br />&nbsp;&nbsp; accountName = </font></font><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af">RoleEnvironment</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">.GetConfigurationSettingValue(</font></font><font face="Consolas" size="2" color="#a31515"><font face="Consolas" size="2" color="#a31515"><font face="Consolas" size="2" color="#a31515">&quot;AccountName&quot;</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">);<br />&nbsp;&nbsp; accountKey = </font></font><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af">RoleEnvironment</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">.GetConfigurationSettingValue(</font></font><font face="Consolas" size="2" color="#a31515"><font face="Consolas" size="2" color="#a31515"><font face="Consolas" size="2" color="#a31515">&quot;AccountSharedKey&quot;</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">);<br />}</font></font></p></font></font></font><p>Once you&#39;ve got the account key and the account name, you can get an instance of the storage credentials and table client classes:</p><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><p>StorageCredentialsAccountAndKey<font face="Consolas" size="2"><font face="Consolas" size="2"> creds = <br />&nbsp;&nbsp;&nbsp; </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">new</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> </font></font><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af">StorageCredentialsAccountAndKey</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">(accountName, accountKey);<br /></font></font><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af">CloudTableClient</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> tableStorage = </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">new</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> </font></font><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af">CloudTableClient</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">(tableBaseUri, creds);<br /></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af">CustomerContext</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> ctx = </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">new</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> </font></font><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af">CustomerContext</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">(tableBaseUri, creds);</font></font></font></font></p></font></font></font><p>Using the table storage class, we can create a new table (if it doesn&#39;t already exist):</p><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><p>if<font face="Consolas" size="2"><font face="Consolas" size="2"> (tableStorage.CreateTableIfNotExist(</font></font><font face="Consolas" size="2" color="#a31515"><font face="Consolas" size="2" color="#a31515"><font face="Consolas" size="2" color="#a31515">&quot;Customers&quot;</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">))<br />{ <br /></font></font><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af">CustomerRow</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> cust = </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">new</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> </font></font><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af">CustomerRow</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">(</font></font><font face="Consolas" size="2" color="#a31515"><font face="Consolas" size="2" color="#a31515"><font face="Consolas" size="2" color="#a31515">&quot;AccountsReceivable&quot;</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">, </font></font><font face="Consolas" size="2" color="#a31515"><font face="Consolas" size="2" color="#a31515"><font face="Consolas" size="2" color="#a31515">&quot;kevin&quot;</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">);<br />cust.FirstName = </font></font><font face="Consolas" size="2" color="#a31515"><font face="Consolas" size="2" color="#a31515"><font face="Consolas" size="2" color="#a31515">&quot;Kevin&quot;</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">;<br />cust.LastName = </font></font><font face="Consolas" size="2" color="#a31515"><font face="Consolas" size="2" color="#a31515"><font face="Consolas" size="2" color="#a31515">&quot;Hoffman&quot;</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">;<br />ctx.AddObject(</font></font><font face="Consolas" size="2" color="#a31515"><font face="Consolas" size="2" color="#a31515"><font face="Consolas" size="2" color="#a31515">&quot;Customers&quot;</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">, cust);<br />ctx.SaveChanges(); <br />}</font></font>&nbsp;</p></font></font></font><p>Here I&#39;m also using my customer context class and my customer row class (will show those shortly) in order to put a new customer into table storage. Note my use of an application name for the partition key and the username for the row key. Entire chapters of books can (and will) be written on strategies and patterns for using partition and row keys.</p><p>Now let&#39;s say that we&#39;re inside an MVC 2 controller and we want to make the list of customers available to the view. If we&#39;re not doing a strongly typed view (which we should be doing unless we can&#39;t help it...) then we can use code that looks like this:</p><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><p>CustomerRow<font face="Consolas" size="2"><font face="Consolas" size="2">[] customers = ctx.Customers.ToArray();<br />ViewData[</font></font><font face="Consolas" size="2" color="#a31515"><font face="Consolas" size="2" color="#a31515"><font face="Consolas" size="2" color="#a31515">&quot;Customers&quot;</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">] = customers; </font></font></p></font></font></font><p>Now let&#39;s look at the CustomerContext class:</p><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><p>public<font face="Consolas" size="2"><font face="Consolas" size="2"> </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">class</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> </font></font><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af">CustomerContext</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> : </font></font><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af">TableServiceContext<br /></font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">{<br />&nbsp;&nbsp;&nbsp; </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">public</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> CustomerContext(</font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">string</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> uri, </font></font><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af">StorageCredentials</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> creds) : </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">base</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">(uri, creds) { }<br />&nbsp;&nbsp;&nbsp; </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">public</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> </font></font><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af">IQueryable</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">&lt;</font></font><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af">CustomerRow</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">&gt; Customers<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">get<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">return</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">this</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">.CreateQuery&lt;</font></font><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af">CustomerRow</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">&gt;(</font></font><font face="Consolas" size="2" color="#a31515"><font face="Consolas" size="2" color="#a31515"><font face="Consolas" size="2" color="#a31515">&quot;Customers&quot;</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; }<br />}</font></font></p></font></font></font><p>The CustomerRow class is just a POCO class that has a default constructor and a constructor that takes a partition key and a row key, and inherits from the <strong>TableServiceEntity</strong> class.</p><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">public</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">class</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> </font></font><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af">CustomerRow</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> : </font></font><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af">TableServiceEntity<br /></font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">{<br />&nbsp;&nbsp;&nbsp; </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">private</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">string</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> firstName;<br />&nbsp;&nbsp;&nbsp; </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">private</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">string</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> lastName;<br />&nbsp;&nbsp;&nbsp; </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">private</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">string</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> userName;<br />&nbsp;&nbsp;&nbsp; </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">private</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">string</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> applicationName;<br /><br />&nbsp;&nbsp;&nbsp; </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">public</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> CustomerRow(</font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">string</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> applicationName, </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">string</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> userName)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">base</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">(applicationName, userName)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ApplicationName = applicationName;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; UserName = userName; <br />&nbsp;&nbsp;&nbsp; }</font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> <p><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">&nbsp;&nbsp;&nbsp; public</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> CustomerRow() : </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">base</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">() { }</font></font></p></font></font><p>I snipped out the rest of the class for brevity - I&#39;m assuming we&#39;ve all seen stock property accessors before. At this point you should be ready to roll using table storage. There is also one other benefit they gave us in November 2009 CTP - <em><strong>you no longer need to pre-rig your database schema in your SQL 2008 database</strong></em>!! The new development storage simulator accurately simulates the dynamic schema nature of the actual table storage in the cloud. I can&#39;t begin to describe how many headaches this alleviates.</p><p>Enjoy table storage on the new Nov 2009 CTP and I&#39;ll be posting similar blog posts about the new Queue storage and Blob storage clients shortly!</p>]]></description><category>azure</category><category>tablestorage</category><category>azurestorage</category><category>cloud</category><category>ctp</category><category>pdc09</category></item><item><title>Setting up an ASP.NET MVC 2 Application for Windows Azure</title><guid isPermaLink="true">http://dotnetaddict.dotnetdevelopersjournal.com/azure_mvc2.htm</guid><link>http://dotnetaddict.dotnetdevelopersjournal.com/azure_mvc2.htm</link><pubDate>Sat, 14 Nov 2009 21:48:00 GMT</pubDate><comments>http://dotnetaddict.dotnetdevelopersjournal.com/console/comments/popup/?f=azure%5Fmvc2</comments><dc:creator>Kevin Hoffman</dc:creator><description><![CDATA[<p>Yesterday, Microsoft released another update to the Windows Azure SDK. This update includes a truckload of new goodies that I will be covering in additional blog posts. For this blog post, however, I want to walk you through getting an ASP.NET MVC 2 application working on Windows Azure <em>in Visual Studio 2010 Beta 2</em>. Now that Azure and VS2010 are finally starting to sync up, the amount of raw goodness coming out of Redmond cannot be measured.</p><p>First, install the Windows Azure SDK and the Windows Azure Tools for Visual Studio, making sure you pay attention to all of the installation details. There are lots of little hotfixes and things that you might need. Luckily, if you&#39;re running VS2010 Beta 2 on Windows 7, you have very little extra work to do beyond configuring IIS 7 for WCF HTTP activation.</p><p>Once you&#39;ve got that installed, create a new project. The project template you&#39;re looking for is in the group <strong>Cloud Service</strong> and is called <strong>Cloud Service</strong>. Once you give this new solution a name and click next, you&#39;ll be given a dialog box that looks like the one in the screenshot below:</p><p><img src="http://files.blog-city.com/files/J05/88284/p/f/azure_mvc2.png" alt="screenshot" width="638" height="400" /></p><p>The fantastic thing here is that you&#39;ll see, without us having to do any hackery or modify any .csproj files with notepad, there is a web role available for an ASP.NET MVC 2 application. Click the right-arrow button to add that to your cloud service and then pick a worker role if you want one.</p><p>After you get that started, if you are running SQL Express, you should be able to hit F5 and see a nice hello world application.&nbsp;The local development storage&nbsp;simulator requires either SQL Express&nbsp;or a full version of SQL 2005+.&nbsp;If you&#39;re not running SQL Express and you&#39;re running a full version of SQL 2008 like&nbsp;a <em>real developer</em> (kidding!) then you&#39;ll need to open up a command prompt. Go to the <strong>c:\program files\windows azure SDK\v1.0\bin\devstore</strong> directory (this is the same for both 64 and 32-bit systems). Then run the following command:</p><pre>dsinit /sqlinstance:. /forceCreate</pre><p>If you&#39;re not using the default SQL instance, then replace the &quot;.&quot; with the name of your instance. If your windows account doesn&#39;t have sufficient permissions to do this, then you&#39;ll need to either rectify that using SQL Server Management Studio or use an optional command-line parameter to specify the SQL server credentials required to create the development storage schemas. After executing this command, you&#39;ll see a dialog box like the one below:</p><p><img style="width: 505px; height: 349px" src="http://files.blog-city.com/files/J05/88284/p/f/azure_devstore.png" alt="screenshot" width="505" height="349" /></p><p>Now you should be good to go. If you hit F5 in Visual Studio 2010, you&#39;ll see some scrolling messages in the status bar about &quot;waiting for roles to startup&quot; and it&#39;ll take a few minutes initially, but eventually you&#39;ll see the default home page from your MVC 2 project. If you think you&#39;re done, think again.</p><p>Just as with getting the MVC 1 project to work on Windows Azure, you cannot use the default providers. These providers work against a local SQL Express database by default and they don&#39;t work against cloud storage. You&#39;re going to need to fix this before you deploy your application to the cloud. For that, you&#39;re going to have to wait for my next blog post ;) Get your hello world working locally and then you&#39;ll be ready to tweak it as you follow along with my next post.</p>]]></description><category>vs2010</category><category>azure</category><category>cloud</category><category>mvc</category><category>mvc2</category></item><item><title>Windows Identity Foundation (WIF) Release Candidate is out!</title><guid isPermaLink="true">http://dotnetaddict.dotnetdevelopersjournal.com/wif_rc.htm</guid><link>http://dotnetaddict.dotnetdevelopersjournal.com/wif_rc.htm</link><pubDate>Mon, 09 Nov 2009 13:31:00 GMT</pubDate><comments>http://dotnetaddict.dotnetdevelopersjournal.com/console/comments/popup/?f=wif%5Frc</comments><dc:creator>Kevin Hoffman</dc:creator><description><![CDATA[<p>I&#39;m not sure how all this managed to slip by me, but apparently last Friday the Windows Identity Foundation Release Candidate was unleashed on the world. Now keep in mind that this is <em>not</em> the ADFS v2 server, this is the foundational plumbing on which ADFS v2 will run. Good news, though, is that if you&#39;re like me and you&#39;re using WIF to build your own STS websites, then the RC will suit you just fine and you don&#39;t have to wait for the ADFS v2.</p><p>Anyway, if you&#39;d like to get your hands on some WIF action, click here for <a href="http://www.microsoft.com/downloads/details.aspx?familyid=DEFD2019-A61F-4327-9332-6A4B6103527A&amp;displaylang=en" target="_blank">the download link</a>.</p><p>It doesn&#39;t appear as though there are a lot of changes in the framework itself, though I think there are some possible breaking namespace changes but, I&#39;m still downloading it so I don&#39;t know at this point. Also, you might want to pick up the <a href="http://www.microsoft.com/downloads/details.aspx?familyid=C3E315FA-94E2-4028-99CB-904369F177C0&amp;displaylang=en" target="_blank">Identity Training Kit</a>. It has been revised and there&#39;s a new installer for the samples that works on Windows 7 <em>that actually works and installs the SSL certs properly</em>. Previous versions of the ID kit required lots of manual futzing around to get things to work properly with UAC and permissions and the whole &quot;Internet Zone&quot; download issue.</p><p>Enjoy!</p>]]></description><category>wif</category><category>identity</category><category>geneva</category><category>adfs2</category></item><item><title>Installing Geneva Beta 2 on Windows7</title><guid isPermaLink="true">http://dotnetaddict.dotnetdevelopersjournal.com/genevab2_win7.htm</guid><link>http://dotnetaddict.dotnetdevelopersjournal.com/genevab2_win7.htm</link><pubDate>Thu, 05 Nov 2009 13:38:00 GMT</pubDate><comments>http://dotnetaddict.dotnetdevelopersjournal.com/console/comments/popup/?f=genevab2%5Fwin7</comments><dc:creator>Kevin Hoffman</dc:creator><description><![CDATA[<p>Recently I installed the Beta 2 version of &quot;Geneva&quot;, or ADFS 2.0. All of my machines are now Windows 7&nbsp;machines, including just about all of my VHDs and virtual machines. The only time I use Win2k8 R2 is when the product I&#39;m installing specifically requires me to do that. So when I installed Geneva on my Win7 box, I thought everything would be fine.</p><p>Then I rebooted. The &quot;Modify STS Reference...&quot; and &quot;Update federation metadata&quot; menu items that are supposed to be added to the list of available options on an ASP.NET web application were gone. They were there before I rebooted but they were gone after. I also noticed something funny with the Identity training kit install. Every single directory and file in there was marked as &quot;read only&quot;. I would unset the read-only flag, right click the file, get properties, and sure enough, <em>it was still set to read only</em>. WTF?</p><p>Turns out that when I download files from the big bad scary internet, Windows 7 automatically flags them as &quot;bad content&quot; and they are blocked. The permissions of those files are significantly less than those of files I put onto my computer via DVD or whatever. This is actually as it should be, and it&#39;s designed to keep me from doing horribly bad things to my computer. </p><p>I uninstalled the Geneva SDK and the Identity Training Kit. I then right-clicked each of the <em>.msi</em> files, chose Properties and then clicked the magic <em><strong>Unblock</strong></em> button. After this, when I installed the Framework SDK, the Visual Studio extensions remained after reboot, and the files created by the identity training kit didn&#39;t have weird permission problems and the certificates installed by the lab set up actually bound to the SSL port properly.</p><p>So, the moral of the story is this: If you&#39;re going to install an MSI that you downloaded from a trusted source (like MSDN or Microsoft Downloads or h0tpr0n.com), unblock it before you install just to make sure you don&#39;t run into any goofy permission issues.</p>]]></description><category>geneva</category><category>identity</category><category>vs2008</category><category>windows7</category></item><item><title>Why we&apos;re all NOT going to die on December 21st, 2012.</title><guid isPermaLink="true">http://dotnetaddict.dotnetdevelopersjournal.com/maya_2012.htm</guid><link>http://dotnetaddict.dotnetdevelopersjournal.com/maya_2012.htm</link><pubDate>Wed, 04 Nov 2009 21:02:00 GMT</pubDate><comments>http://dotnetaddict.dotnetdevelopersjournal.com/console/comments/popup/?f=maya%5F2012</comments><dc:creator>Kevin Hoffman</dc:creator><description><![CDATA[<p>Unless you&#39;ve been living under a rock for the past couple of months, you&#39;ve probably not been able to escape the movie trailers, hype, and even SyFy channel (yes, SYFY channel..that should TELL YOU SOMETHING) specials regarding the Mayan &quot;prediction&quot; that the world will end in 2012.</p><p>First, some background on the Mayan calendar. The &quot;long count&quot; Mayan calendar is based, basically (I am oversimplifying a little bit), on interlocking wheels. You can think of these as gears where as the days pass, a bigger gear of seasons pass, which then slowly causes another bigger gear to pass. Finally, you end up with a gear that marks the passing of ages that marks the passage of a total of 26,000 years. There are 13 of these ages on the &quot;big gear&quot;. </p><p>The Mayan long count calendar reaches 13.0.0.0.0 on December 21st, 2012. Does this mean that the world is going to come to an end on that date? Does this mean that a huge apocalypse is going to rip the earth apart in huge explosions and other hollywood-like demolitions? Are we all going to cease to exist as time itself comes to a crashing halt?</p><p>UM. <strong><em><u>NO</u></em></strong>.</p><p>What we&#39;re looking at here is the Mayan equivalent of the Y2K problem. The Mayans, when constructing their calendars and the wheels/gears/ whatever they call them - constructed them to mark the passing of 26,000 years. When you think about how long that is, its a ridiculous amount of time. They probably said to themselves, &quot;Nobody is ever going to need more than 26,000 years on a calendar.&quot; Well, let&#39;s see. Where have we heard that mistake before? Oh yeah: <em>No one is ever going to need 4 digits to store a year in a piece of computer software</em>.</p><p>So if you&#39;re smart, you&#39;ll get people to give you all their worldy possessions on December 20th, 2012. Then, on December 22nd, 2012 - sell them all back at a premium. Call it the &quot;sucker surcharge&quot;, a fee for being such a gullable moron that they believed the world was going to end because a civilization <em>without the ability to predict the future</em> basically ran out of storage space in their gear-based calendar system.</p><p>I personally am thinking of having an &quot;end of the world&quot; party on December 21st, 2012. I had one on Jan 1, 2000 and I&#39;ll be there laughing at the mindless masses as they cringe in expectation of doomsday. I should be able to pick up some dirt cheap real estate, too.</p>]]></description><category>maya</category><category>2012</category><category>stupidity</category><category>hollywood</category></item><item><title>Something Wicked This Way Comes - Breaking Changes for .NET Services in Azure</title><guid isPermaLink="true">http://dotnetaddict.dotnetdevelopersjournal.com/something_wicked_this_way_comes__breaking_changes_for_net_.htm</guid><link>http://dotnetaddict.dotnetdevelopersjournal.com/something_wicked_this_way_comes__breaking_changes_for_net_.htm</link><pubDate>Mon, 02 Nov 2009 13:36:00 GMT</pubDate><comments>http://dotnetaddict.dotnetdevelopersjournal.com/console/comments/popup/?f=something%5Fwicked%5Fthis%5Fway%5Fcomes%5F%5Fbreaking%5Fchanges%5Ffor%5Fnet%5F</comments><dc:creator>Kevin Hoffman</dc:creator><description><![CDATA[<p>If you want the full gory details, check out the .NET Services team <a href="http://blogs.msdn.com/netservicesannounce/archive/2009/10/30/the-net-services-november-2009-ctp-breaking-changes-announcement-and-scheduled-maintenance.aspx">blog post here</a>. What follows below are some of the things that I think are most crucial to understand both for new developers and for developers unfortunate enough to be in a position of having to migrate a lot of code. Quite possibly the single most important thing to note is this:</p><blockquote><p><em>If you bought a book on Windows Azure that has already been released or will be released within the next month or two, it is out of date and completely irrelevant. PDC (along with the changes I&#39;m going to outline below) will substantially change all of the Azure offerings.</em></p></blockquote><p>I&#39;ve trimmed a little bit because some of the breaking changes are fairly minor and don&#39;t have too much impact on developers. Here is the list:</p><ul><li>Portal address change. This is an easy enough fix and a simple find-and-replace if you&#39;ve got any code that uses that portal address.</li><li>Solution region migration. Some solutions when migrated to the new version of .NET Services might end up hosted in a different geographical region than before. This isn&#39;t all that big of a deal (for most of us).</li><li><strong>Queues Are Being Removed</strong>. This is <em>huge</em>. In the current version of .NET Services, you can use queues as a way of sending reliable, durable messages between the cloud and on-premise applications without the other endpoint being physically connected. This is a huge change. A new concept called <em>Message Buffers</em> are being introduced. I don&#39;t have all that much information on them but it looks as though the message buffers are essentially transient queues. You send a message to a buffer and it&#39;ll hang out in the buffer while the other end steadily pulls messages out of the buffer. A key point they make is that if you&#39;re looking for durable, reliable, <em>persisted</em> messages between service bus endpoints, you might want to look at using Azure Storage. As painful as it is to see queues go, I think this is a good move. Azure storage already has Queues, and they are robust and powerful. If the reason you were using Queues was to keep from overloading an endpoint with too many messages, the message buffer is your new tool of choice. If you were using Queues so that you could send messages while the polling end was offline, then you&#39;re probably going to need to concoct something involving an Azure Storage queue.</li><li><strong>Routers Are Being Removed</strong>. This is also <em>huge</em>, though slightly less huge than queues. The router concept never really &quot;gelled&quot; with me to begin with - I couldn&#39;t quite figure out how best to use it. Now that they&#39;re being removed and there will be some samples on how to do things like load balancing and targeted delivery, architectural decisions in this area should become easier to make.</li><li>Relay Bindings are now secure (HTTPS) by default. You can override this behavior but there&#39;s very little reason to do so unless you are specifically trying to get your security information stolen.</li><li>Service Namespace. Now instead of the solution name being the hostname of your *.servicebus.windows.net server, you will be able to choose something called the service namespace and have that be the hostname prefix, e.g. (namespace).servicebus.windows.net. This has low impact but is actually very useful.</li><li><strong>TransportClientCredentialType</strong> is being limited. Transport client credentials can no longer include X509 certificates, username/password combinations, or CardSpace cards.</li><li><strong>TcpRelayConnectionMode.Direct</strong> will be removed. This bugs me a little bit because way WAY back when Azure was first unveiled to the public, I remembered talking to someone who said that we&#39;d be able to use the service bus to establish direct connections between two peers both of whom were behind firewalls. This is no longer a possibility, but I can see the reasoning behind it and, quite frankly, my particular use case for this feature was really niche-y.</li><li>Service publishing feed now matches transport. This is handy and makes things a little more straightforward. For those who don&#39;t know, a service publishing feed is basically an Atom feed that shows all of the endpoints on your service bus service that have indicated they want their presence known publicly. In other words, I could hit the service publishing feed and get a list of all connected endpoints. That one ability is <em>ridiculously</em> powerful and is not getting nearly enough hype for the number of scenarios it enables.</li><li>WSHttpRelayBinding has been removed. I&#39;m not gonna miss this one bit as I never used it. </li><li>WS2007FederationHttpRelayBinding removed. Again, not gonna miss it.</li><li><strong>Solution credentials replaced with issuer credentials in Access Control Service</strong>. This one is also quite big. Today, you can use a username/password combo, an X509 cert, or a CardSpace card to <em>request tokens from the STS</em>. As of Thursday, you&#39;re going to need an issuer credential (issuer key and issuer name). In addition, we&#39;re going to have to upload X509 certs to the portal to allow for SAML token requests. I will probably be doing a blog post on this once I get more information because this one is totally game changing and will halt development workflow as it stands now and totally change it after Thursday.</li><li><h2 style="line-height: normal; margin: 10pt 0in 0pt"><font face="Cambria" size="4">WS-Trust STS replaced with Web Resource Authorization Protocol (WRAP) STS</font></h2>&nbsp; - Yes, I made this one gigantic. Why? <em>Ding dong the witch is dead! The wicked witch is dead!</em> WRAP is RESTful people. WS-Trust is EVIL people. Enjoy. We&#39;ve all just been given a shiny cupcake with a frosting of <em>awesome</em> on top.</li><li>Access Control Service data <em><strong>will not be migrated</strong></em>. This means if you&#39;re one of those crazy early adopters and you&#39;ve already written a complete app on the existing ACS - <em>get your data backed up and saved somewhere now. It will be deleted on Thursday morning!</em></li><li>Access Control Management Portal is being replaced with a command-line tool. I know some of you might be thinking, <em>dammit! </em>But I see this as a good thing. It&#39;s an absolute pain in the ass to stop what I&#39;m doing and click through 8 billion links (including the 500,000,000,000,000 redirects involved with a Windows Live ID login) just to go tweak some small setting. I could probably take 20 minutes to rig up a couple .cmd files to do regular ACM tasks that are specific to my app and be done with it. This is going to be a big productivity gain, even though we lose some flashy web-based GUI.</li></ul><p>Here&#39;s the bottom line: </p><p><em>Windows Azure (including Azure Storage, SQL Azure, and .NET Services) is maturing. It is moving away from being an experiment and moving toward a product that can sustain regular income and regular usage and the 90% customer usage scenarios. As a result, they&#39;re going to break changes and add features and shut off lame or ineffective or almost-never-used features.</em></p><p>Can&#39;t wait to get my hands on the new bits Thursday.</p>]]></description><category>pdc09</category><category>azure</category><category>netservices</category><category>cloud</category><category>acs</category><category>servicebus</category></item><item><title>LINQ to SQL and Entity Framework on top of SQL Azure</title><guid isPermaLink="true">http://dotnetaddict.dotnetdevelopersjournal.com/l2s_ef_sqlazure.htm</guid><link>http://dotnetaddict.dotnetdevelopersjournal.com/l2s_ef_sqlazure.htm</link><pubDate>Wed, 28 Oct 2009 23:33:00 GMT</pubDate><comments>http://dotnetaddict.dotnetdevelopersjournal.com/console/comments/popup/?f=l2s%5Fef%5Fsqlazure</comments><dc:creator>Kevin Hoffman</dc:creator><description><![CDATA[<p>As mentioned in my <a href="/sqlazure_maintenance.htm" target="_blank">previous blog post</a>, you don&#39;t get full designer support on SQL Azure within SQL Server Management Studio. In addition, you don&#39;t get designer support for LINQ to SQL or Entity Framework, either. So what do you do if you want to take advantage of these awesome object mapping tools but the designers don&#39;t work directly against the cloud?</p><p>Conveniently enough, if you follow the tips in the previous blog post, you would have already created a local copy of your SQL Azure database. The &quot;trick&quot; (not really a trick at all, just not immediately obvious) is to point your EF or LINQ to SQL Visual Studio projects at your local database. This will give these mappers the schema and relationship information they need in order to create the appropriate conceptual&lt;-&gt;relational mappings.</p><p>For LINQ to SQL, all you need to do is replace the connection string that it adds to your <em>app.Config</em> file with the connection string supplied by the <em>sql.azure.com</em> portal. Remember to include your password in this connection string because the portal copies a version of this string to your clipboard with the password of <em>myPassword</em>. At this point you should also be thinking to yourself, &quot;<em>Wow, I just put a cleartext password in a .config file. It&#39;s a really good thing that this code isn&#39;t going to sit on someone&#39;s desktop and will be protected in the cloud.</em>&quot; </p><p>With Entity Framework, the connection string is a little more complicated. There&#39;s some entity stuff in there that points to the various model definition files in the project and then there&#39;s an embedded connection string. Replace the embedded connection string (take care to maintain the escaping of nested quotes, etc) with the one the SQL Azure portal supplied and change the password to reflect the right password.</p><p>At this point you should have been able to generate a model from your <em>local</em> database and then change the connection string so that the actual data comes from the <em>cloud</em> database. It might seem a little inconvenient but it isn&#39;t really all that bad. It just adds a few extra steps to your SDLC when you need to change the schema of a live application.</p><p>The feeling I got when I ran my first LINQ to Entities query against a cloud-based SQL Server database was overwhelming. Sure I love new technology as much as the next guy, but the possibilities that are being opened for developers by Windows Azure and cloud computing in general are so numerous it&#39;s hard to contain myself. </p><p>This is a <em>damn good time</em> to be a developer.</p>]]></description><category>sql</category><category>azure</category><category>sqlazure</category><category>entityframework</category><category>linq2sql</category><category>ef</category><category>orm</category></item><item><title>Creating and Manipulating your SQL Azure Database with SSMS and Visual Studio</title><guid isPermaLink="true">http://dotnetaddict.dotnetdevelopersjournal.com/sqlazure_maintenance.htm</guid><link>http://dotnetaddict.dotnetdevelopersjournal.com/sqlazure_maintenance.htm</link><pubDate>Wed, 28 Oct 2009 21:31:00 GMT</pubDate><comments>http://dotnetaddict.dotnetdevelopersjournal.com/console/comments/popup/?f=sqlazure%5Fmaintenance</comments><dc:creator>Kevin Hoffman</dc:creator><description><![CDATA[<p>So after the long and torturous wait, you&#39;re now in the SQL Azure CTP and you are ready to get the ball rolling with your fabulous, shiny new cloud-based SQL database server. Now what? Well, the first thing you&#39;re going to need to do is create a database.</p><p>To do that, you&#39;ll go to <strong>sql.azure.com</strong> and follow the directions to sign in - if you haven&#39;t already supplied the invite key you&#39;ll need to supply it after you sign in the first time. Select your project and click on it. At this point you&#39;ll see a pretty sparse management screen with two tabs: <em>databases</em> and <em>firewall settings</em>. On the database tab, create a new database (its up to you whether you create a 1GB or a 10GB max database). After you&#39;ve created it, you&#39;ll be able to click the <em>Connection Strings</em> button to get an ADO.NET connection string for the database as well as an ODBC connection string.</p><p>That&#39;s great, but how do you manage the schema? Can you just fire up SQL Server Management Studio (SSMS) and right-click on the &quot;Tables&quot; node and create new tables the old fashioned way? Unfortunately, no. You cannot connect to SQL Azure directly with SSMS the way you can to a regular SQL Server instance.</p><p>To connect to SQL Azure with SSMS:</p><ol><li>Open SSMS (this part should be pretty obvious)</li><li>When you are prompted to connect to a database, <em><strong>cancel that dialog</strong></em>.</li><li>You should be left with an empty management console. Click <em><strong>New Query</strong></em>.</li><li>For the server name, take the fully qualified host name from your SQL Azure connection string. It should look something like <em>(blah).database.windows.net</em>.</li><li>Choose SQL Server Authentication. Supply the username and password that you used for your database. Parts of this information should also be visible on your connection string.</li><li>Click on the <em>Options</em> button on the bottom right of the dialog box</li><li>Set the database name, manually, to the name of your database. It will not show up in the drop-down list.</li><li>Force the network protocol to be TCP/IP (this step may not be necessary, but I do it out of habit)</li><li>Make sure Server type is set to <em>Database engine</em> (this is the default, but might not be if you use SSMS for more than your average bear)</li><li>Now you can click <em>Connect</em>.</li></ol><p>At this point, if everything worked well, you should <em><strong>FAIL</strong></em> to connect to SQL Azure :) You should get some horrid message about a connection from your public IP address not being allowed. This is because this version of SQL Azure has a built-in firewall and, by default, it doesn&#39;t allow anything through.</p><p>Go back to the <em>sql.azure.com</em> portal and click on the <em>Firewall Settings</em> tab. Check the <em>Allow Microsoft Services to Access this server</em> box. Click the button to add a new record. At this point it will conveniently show you what it thinks your public IP is so you can create a new rule to allow your IP through. Keep in mind this is <em>only</em> required to allow your home computer to access your SQL Azure server. If you have checked the <em>Allow Microsoft Services...</em> checkbox, then connections from within the Azure fabric (like an ADO.NET call from inside an ASP.NET app in an Azure Web Role) will pass through the firewall unhindered. This firewall is specifically to keep the communication safe and give you a &quot;DMZ-like&quot; experience where only the people (IPs) you trust will be able to hit that server from outside the Azure cloud fabric.</p><p>Now, after adding the firewall rule, you will <em>need to wait up to 15 minutes or more</em>. When I did it, it took over 20 minutes. The reason is that the portal where you hit the submit button is not the same physical machine as your SQL Azure server. It takes a few minutes for your new firewall rule to make it over to the actual data center where your SQL Azure server has been provisioned (at least that&#39;s my best guess to explain this delay). So don&#39;t be alarmed if 10 seconds after you add the firewall rule you still can&#39;t get into your database.</p><p>Now you are free to write T-SQL until you are blue in the face. What&#39;s that, you don&#39;t love hand-writing T-SQL schema change scripts without any assistance from an IDE? Neither do I. This is why I created a Visual Studio 2008 &quot;Database Project&quot; that references a <em>local database with the same schema as the one I want to have in the cloud</em>. This is useful for multiple reasons. The biggest of which is that with a &quot;Database project&quot; I can version control my scripts. Secondly, I automatically gain the benefit of a local development copy of my database. Finally, this allows me to, from within VS, right-click any schema element and script it into the project. I can then open that script, <em>do some cleaning up</em>, and then execute that script in the aforementioned SSMS query window. The <em>cleaning up</em> I&#39;m referring to means stripping out the plethora of extraneous options on the ends of the <em>CREATE TABLE</em> statements and things like that. A lot of those options aren&#39;t available in SQL Azure so just strip them out after you script the table, proc, view, whatever. It&#39;s a pain in the butt, but it&#39;s certainly better than having to hand-craft all that T-SQL if you aren&#39;t into that sort of thing. I know some developers that like to get all kinky with their T-SQL and would never let VS script it for them. Me, I like to wear protective gear when I talk to the database schema so letting VS give me a head start <em>suggestion</em> as to the script I should run on SQL Azure works just fine for me.</p>]]></description><category>sql</category><category>azure</category><category>sqlazure</category><category>visualstudio</category><category>cloud</category><category>database</category></item><item><title>Client-Side Validation with jQuery, DataAnnotations, MVC 2, and VS2010 Beta 2</title><guid isPermaLink="true">http://dotnetaddict.dotnetdevelopersjournal.com/clientvalidation_mvc2.htm</guid><link>http://dotnetaddict.dotnetdevelopersjournal.com/clientvalidation_mvc2.htm</link><pubDate>Mon, 26 Oct 2009 13:58:00 GMT</pubDate><comments>http://dotnetaddict.dotnetdevelopersjournal.com/console/comments/popup/?f=clientvalidation%5Fmvc2</comments><dc:creator>Kevin Hoffman</dc:creator><description><![CDATA[<p>Anytime a feature of a framework gives me something for free that I don&#39;t need to manually implement I&#39;m a happy camper. One such feature of ASP.NET MVC 2 is jQuery client-side validation. The reason I like this is that unlike other jQuery frameworks, where you have to write the jQuery yourself - you don&#39;t need to do that with MVC 2. </p><p>Instead of having to maintain simple validation logic in two places (your business classes and your jQuery code), you can now use the Data Annotations attributes and metadata &quot;buddy&quot; classes to decorate your models. Those decorated models will <em>automatically</em> generate the appropriate jQuery code to enforce all of your validation rules on the client side before the form is ever submitted. Let&#39;s see how this works.</p><p>First, we need a model class. Let&#39;s do something simple like Customer:</p><pre>public partial class Customer<br />{<br />&nbsp;&nbsp;&nbsp; public string Name { get; set; }<br />&nbsp;&nbsp;&nbsp; public int Age { get; set; }<br />}</pre><p>This is great. I love the fact that it doesn&#39;t look ugly and view developers can look at it and immediately know what fields are available and they don&#39;t need to sift through a pile of persistence garbage or validation logic. You might have noticed that I&#39;ve made this class partial. The reason I&#39;m doing this is because I&#39;m going to create another file called <strong>Customer.metadata.cs</strong>. There are other samples on the web that don&#39;t do this, but I like cleanly separating the <em>definition </em>of my model from the <em>validation logic</em> for that model. Here&#39;s a look at my Customer.metadata.cs file:</p><pre>[MetadataType(typeof(CustomerMetaData))]<br />public partial class Customer<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;class CustomerMetaData<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; [Required(ErrorMessage=&quot;You must supply a name for a&nbsp;customer.&quot;)]<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; [StringLength(50, ErrorMessage = &quot;A customer name cannot exceed 50 characters.&quot;)]<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public string Name { get; set; }<br />&nbsp;&nbsp;&nbsp; }<br />}</pre><p>What I&#39;ve done here is used a metadata &quot;buddy class&quot; (that&#39;s what posts from Scott Guthrie and Scott Hanselman have been calling them, so I&#39;m sticking with convention here). This buddy class is a placeholder for all my validation logic attributes and the runtime will then merge all this stuff onto the actual model. MVC 2 will then examine the model and , with a few lines of code in the view, generate the appropriate jQuery client-side validation logic.</p><p>In your view code, add the following 3 script declarations:</p><font face="Consolas" size="2"><font face="Consolas" size="2"><p><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">&lt;</font></font></font><font face="Consolas" size="2" color="#800000"><font face="Consolas" size="2" color="#800000"><font face="Consolas" size="2" color="#800000">script</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> </font></font><font face="Consolas" size="2" color="#ff0000"><font face="Consolas" size="2" color="#ff0000"><font face="Consolas" size="2" color="#ff0000">type</font></font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">=&quot;text/javascript&quot;</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> </font></font><font face="Consolas" size="2" color="#ff0000"><font face="Consolas" size="2" color="#ff0000"><font face="Consolas" size="2" color="#ff0000">src</font></font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">=&quot;../../Scripts/jquery-1.3.2.min.js&quot;&gt;&lt;/</font></font></font><font face="Consolas" size="2" color="#800000"><font face="Consolas" size="2" color="#800000"><font face="Consolas" size="2" color="#800000">script</font></font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">&gt;<br /></font></font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">&lt;</font></font></font><font face="Consolas" size="2" color="#800000"><font face="Consolas" size="2" color="#800000"><font face="Consolas" size="2" color="#800000">script</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> </font></font><font face="Consolas" size="2" color="#ff0000"><font face="Consolas" size="2" color="#ff0000"><font face="Consolas" size="2" color="#ff0000">type</font></font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">=&quot;text/javascript&quot;</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> </font></font><font face="Consolas" size="2" color="#ff0000"><font face="Consolas" size="2" color="#ff0000"><font face="Consolas" size="2" color="#ff0000">src</font></font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">=&quot;../../Scripts/jquery.validate.min.js&quot;&gt;&lt;/</font></font></font><font face="Consolas" size="2" color="#800000"><font face="Consolas" size="2" color="#800000"><font face="Consolas" size="2" color="#800000">script</font></font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">&gt;<br /></font></font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">&lt;</font></font></font><font face="Consolas" size="2" color="#800000"><font face="Consolas" size="2" color="#800000"><font face="Consolas" size="2" color="#800000">script</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> </font></font><font face="Consolas" size="2" color="#ff0000"><font face="Consolas" size="2" color="#ff0000"><font face="Consolas" size="2" color="#ff0000">type</font></font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">=&quot;text/javascript&quot;</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> </font></font><font face="Consolas" size="2" color="#ff0000"><font face="Consolas" size="2" color="#ff0000"><font face="Consolas" size="2" color="#ff0000">src</font></font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">=&quot;../../Scripts/MicrosoftMvcJQueryValidation.js&quot;&gt;&lt;/</font></font></font><font face="Consolas" size="2" color="#800000"><font face="Consolas" size="2" color="#800000"><font face="Consolas" size="2" color="#800000">script</font></font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">&gt;</font></font></font></p></font></font><p>Finally, somewhere before the start of your form tag, add the following markup to the view code:</p><pre>&lt;% Html.EnableClientValidation(); %&gt;&nbsp;</pre><p>This will invoke the code that reads through the strongly typed model for your view, figures out all of the validation logic that applies, and generates the appropriate jQuery code.</p><p>While you could write your own jQuery validation code if you felt like it, using data annotations and MVC 2, you no longer have to maintain your validation logic in two places. The attributes apply to a single view model and all you have to do is change one of those attributes and the generated jQuery code will change as well. This is a <em>huge</em> timesaver and promises to dramatically increase overall productivity of developers building large-scale MVC 2 applications, especially LOB apps with lots of data entry forms.</p><p>&nbsp;</p>]]></description><category>vs2010</category><category>mvc2</category><category>jquery</category><category>dataannotations</category><category>validation</category><category>client</category><category>mvc</category><category>aspnet</category></item><item><title>Templated Helpers in ASP.NET MVC 2 (VS2010 Beta 2 Version)</title><guid isPermaLink="true">http://dotnetaddict.dotnetdevelopersjournal.com/mvc2_templated_helpers.htm</guid><link>http://dotnetaddict.dotnetdevelopersjournal.com/mvc2_templated_helpers.htm</link><pubDate>Thu, 22 Oct 2009 12:21:00 GMT</pubDate><comments>http://dotnetaddict.dotnetdevelopersjournal.com/console/comments/popup/?f=mvc2%5Ftemplated%5Fhelpers</comments><dc:creator>Kevin Hoffman</dc:creator><description><![CDATA[<p>Templated Helpers are one of the new features in ASP.NET MVC 2. The other day, Visual Studio 2010 Beta 2 came out and some of you may have noticed that it comes pre-equipped with a beta release of ASP.NET MVC 2. In short a templated helper is a way of using various combinations of implicit and explicit rules to automatically place partial controls wherever particular data types need to appear, either in edit mode or display mode.</p><p>So let&#39;s say you have a DateTime property on your model called MeetingDate. Rather than make every single view write its own (potentially contrasting!) code to render dates in view mode and in edit mode, you can now do something like this:</p><pre>&lt;%= Html.DisplayFor( m =&gt; m.MeetingDate ) %&gt;<br />&lt;%= Html.EditorFor( m=&gt; m.MeetingDate) %&gt;</pre><p>The <em>DisplayFor</em> helper will look at the data type of the thing you&#39;re looking for and try and figure out how to render that item. If you don&#39;t override convention, it will look in the <em>Shared/DisplayTemplates</em> folder for a <em>DateTime.ascx</em> control. If you want the display template to be specific to a certain controller, it can also look under the <em>Views/(ControllerName)/DisplayTemplates</em> folder. This same rule applies to <em>EditorFor</em>. It will look for the special <em>EditorTemplates</em> folder to try and find a suitable control. By &quot;control&quot; here I&#39;m actually referring to a <em>partial view</em> since technically there are no controls in the traditional ASP.NET sense in MVC.</p><p>There&#39;s another HTML helper that you can use in your top-level view to invoke the partial-view location heuristics for an entire model just by doing:</p><pre>&lt;%= Html.EditorForModel () %&gt;</pre><p>This will examine the data type of your strongly-typed view and go look in an <em>EditorTemplates</em> folder to find the appropriate partial view.</p><p>Finally, there&#39;s another way you can supply hints to the templated helper system. That&#39;s through the use of the <em>UIHint</em> attribute. The UIHint actually allows you to decorate your view model (you are using an isolated view model and not working against persistance objects directly, aren&#39;t you?) with hints as to which editor should be used. This is <em>fantastic</em> for drop-down lists because the underlying value of a dropdown list is usually the ID of the lookup column, which is just an Int. You can&#39;t infer from Int that you want the Country dropdown vs. the State dropdown vs. the Weapons dropdown. To tell the engine which template you want, you can use the UIHint attribute as follows:</p><pre>[UIHint(&quot;CustomerStatusDropDown&quot;)]<br />public CustomerStatus CustomerStatus { get; set; }</pre><p>Where CustomerStatus is another view model object that you&#39;ve got with a Name/ID pair (In my case I did it this way to accomodate the data coming from an ADO.NET Data Service). When you do <em>Html.DisplayFor</em> on this particular property of this particular class, it will override the normal algorithm and go look for a <em>DisplayTemplate</em> called <em>CustomerStatusDropdown.ascx</em>. When you do <em>Html.EditorFor</em>, it will look for a file called <em>CustomerStatusDropDown.ascx</em> but in the <em>EditorTemplate</em>s directory. This allows you to simply, cleanly, and elegantly control how you display and edit lookups. </p><p>If you want, you can control the template selection directly from the EditorFor method call:</p><pre>&lt;%= Html.EditorFor ( cust =&gt; cust.BirthDate, &quot;DateTime_jQuery&quot;) %&gt;</pre><p>You might use a pattern like this in order to allow some pages to edit date/times with a jQuery picker instead of a traditional date/time picker. The possibilities are endless.</p><p>The reason why I&#39;m blogging about this now, only a few days after Beta 2 comes out, is because I think this way of arranging your UI is <em>so, absolutely, positively</em> crucial to a clean, elegant, easy to maintain ASP.NET MVC application that everybody should be getting in the habit of using templated helpers now so that by the time VS 2010 hits RTM, the use of templated helpers will be old hat and we&#39;ll all be one step closer to ridding the world of &quot;tag soup&quot; forever.</p><p>p.s. If you invoke some of these EditorFor and DisplayFor helpers without actually having a suitable control in the EditorTemplates or DisplayTemplates directory, you might find some pretty interesting results. For example, if you do EditorForModel, and there isn&#39;t a control for that data type in your <em>EditorTemplates</em> directory, the system will actually use Reflection. It will sift through the public properties of your model, and for each property it will do the equivalent of invoking <em>EditorFor</em> and <em>LabelFor</em> on that property. In short, it will scaffold you up a &quot;best guess&quot; editor for your entire object. The reason this is in a &quot;p.s.&quot; is because such scaffolding is great for smoke testing, but rarely lasts long.</p>]]></description><category>vs2010</category><category>beta</category><category>mvc</category><category>mvc2</category><category>template</category><category>controls</category><category>ui</category><category>jquery</category></item><item><title>Kindle 2 vs. Nook</title><guid isPermaLink="true">http://dotnetaddict.dotnetdevelopersjournal.com/kindle_vs_nook.htm</guid><link>http://dotnetaddict.dotnetdevelopersjournal.com/kindle_vs_nook.htm</link><pubDate>Wed, 21 Oct 2009 01:59:00 GMT</pubDate><comments>http://dotnetaddict.dotnetdevelopersjournal.com/console/comments/popup/?f=kindle%5Fvs%5Fnook</comments><dc:creator>Kevin Hoffman</dc:creator><description><![CDATA[Barnes and Noble just recently unveiled their upcoming eReader, the Nook. On the blog of my non-techy alter-ego I&#39;ve posted a comparison of the two readers that is entirely based on my own personal feelings of what is cool and what isn&#39;t, so take it as opinion and certainly not as a technical review. <strong><a href="http://tinyurl.com/yjfyzcm">Click here</a></strong> to check out the blog post.]]></description><category>ereader</category><category>ebooks</category><category>kindle</category><category>nook</category><category>amazon</category><category>barnesandnoble</category></item><item><title>Get Your Red Hot VS2010 Beta 2!</title><guid isPermaLink="true">http://dotnetaddict.dotnetdevelopersjournal.com/vs2010_beta2_release.htm</guid><link>http://dotnetaddict.dotnetdevelopersjournal.com/vs2010_beta2_release.htm</link><pubDate>Mon, 19 Oct 2009 20:43:00 GMT</pubDate><comments>http://dotnetaddict.dotnetdevelopersjournal.com/console/comments/popup/?f=vs2010%5Fbeta2%5Frelease</comments><dc:creator>Kevin Hoffman</dc:creator><description><![CDATA[<p>Visual Studio 2010 Beta 2 is now available to MSDN subscribers and will be available to the public at large late next week. The list of stuff that is awesome and worth checking out in VS2010 Beta 2 is too long and ridiculously in-depth for me to cover here. Some of the big things that affect me right off the bat are the following:</p><ul><li><strong>ASP.NET MVC 2</strong> is now built right into the installation. Finally we get convergence of the ASP.NET MVC project and VS2010 tools. Up until now, MVC 2 was only working on VS2008 which sucked for us early adopters of VS2010 and MVC!</li><li>Azure Tools - there&#39;s a project type in here that when you create a new project of this type (&quot;Cloud Service&quot;) it tells you how to get going with Azure. Current versions of Azure only run on .NET Framework 3.5 SP1 and right now I have enough available virtualization and memory to not mingle. So right now, I&#39;m not going to even bother trying to get Azure working on VS2010 until I know the Azure back-end is running .NET Framework 4 and there is native, in-IDE tooling for VS2010 like there is for VS2008.</li><li><strong>EF4</strong> - All kinds of ridiculous stuff here. Be sure to check out the Entity Framework blog for information on what&#39;s new in Beta 2.</li><li><strong>WCF and WF</strong> - Workflow services, Workflow in general, and WCF overall have recieved quite a bit of overhauling and fine tuning since beta 1. Make sure you try workflow services with content-based correlation and service discovery - all very awesome stuff.</li><li><strong>Astoria with Projections</strong> - the same goodness that you&#39;ve been enjoying with the 1.5 CTP2 of Astoria (including projections!!) is available already inside VS2010.</li></ul><p>As I said, there are a billion other things available in VS2010 Beta 2 and there are a billion other blogs that have more detailed information on it so I&#39;m not going to duplicate that stuff here.</p><p>Bottom line is this: Go grab VS2010 from your MSDN subscription <em>now</em>, or wait until they release it to the public during PDC. Start messing with it and start playing with it.</p>]]></description><category>pdc</category><category>vs2010</category><category>beta</category></item><item><title>The Origin of Stupidity</title><guid isPermaLink="true">http://dotnetaddict.dotnetdevelopersjournal.com/origin_of_stupidity.htm</guid><link>http://dotnetaddict.dotnetdevelopersjournal.com/origin_of_stupidity.htm</link><pubDate>Wed, 14 Oct 2009 13:01:00 GMT</pubDate><comments>http://dotnetaddict.dotnetdevelopersjournal.com/console/comments/popup/?f=origin%5Fof%5Fstupidity</comments><dc:creator>Kevin Hoffman</dc:creator><description><![CDATA[<p>So apparently Kirk Cameron and a buddy of his are continuing their campaign of lies and outright stupidity because things like common sense, science, and cold hard fact threaten their fragile hold on sanity. Ordinarily I might on on a huge rant about this but everything I could say, the woman in this video says much more eloquently than I could. This is a must-watch.</p><p>&nbsp;</p><object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,29,0" width="445" height="364"><param name="movie" value="http://www.youtube.com/v/fmHN3JtyUXg&amp;hl=en&amp;fs=1&amp;rel=0&amp;border=1" /><param name="quality" value="high" /><param name="menu" value="false" /><param name="wmode" value="" /><embed src="http://www.youtube.com/v/fmHN3JtyUXg&amp;hl=en&amp;fs=1&amp;rel=0&amp;border=1" wmode="" quality="high" menu="false" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" width="445" height="364"></embed></object>]]></description><category>kirkcameron</category><category>atheism</category><category>evolution</category><category>darwin</category><category>humor</category></item><item><title>ADO.NET Data Services Projections Makes Sliced Bread Jealous</title><guid isPermaLink="true">http://dotnetaddict.dotnetdevelopersjournal.com/astoria_projections.htm</guid><link>http://dotnetaddict.dotnetdevelopersjournal.com/astoria_projections.htm</link><pubDate>Fri, 09 Oct 2009 15:07:00 GMT</pubDate><comments>http://dotnetaddict.dotnetdevelopersjournal.com/console/comments/popup/?f=astoria%5Fprojections</comments><dc:creator>Kevin Hoffman</dc:creator><description><![CDATA[<p>The other day I ran into a blog entry from the Astoria team discussing the <em>projections</em> feature of the 1.5 CTP2 version of the product. If you&#39;re not familiar with ADO.NET Data Services (formerly codenamed <em>Astoria</em>), it&#39;s basically a layer that you can put on top of an Entity Data Model and it will expose that model as a RESTful service. The URL format for this RESTful service is quite flexible, allowing you to select individual rows, perform filters, sorts, and many other things.</p><p>One of the new things that you can now do server-side via the new CTP2 URL syntax is projections. Projections actually allow you to control the shape of the output coming back. You can specifically choose which properties on the entity you want. Even more awesome is that this can be controller hierarchically. So if you bring back an Order entity and you include all of the OrderItem entities for that order, you can tell the server that you only want the customer for the Order and you only want Quantity and Price for the order items.</p><p>To perform a projection on the URL, you just use the $select parameter, like this:</p><pre>blah.svc/Orders?$select=OrderID,Quantity,Price</pre><p>And to control the shape of hierarchical data:</p><pre>blah.svc/Orders?$select=OrderID,Quantity,OrderItems/Price,OrderItems/Quantity&amp;$expand=OrderItems</pre><p>At this point when I saw this I started having convulsions of pure joy. The main reasons being that every ADO.NET Data Services URL query will output either AtomPub or JSON. This means I can get only the columns I need and give them to my Ajax calls. Then I noticed that support for the new projections is actually in the Astoria client library as well, allowing me to write the following query:</p><pre>var q = from order in ctx.Orders<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; where order.Price &gt; 300<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; orderby order.Price descending<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; select new { Price = order.Price, Quantity = order.Quantity };</pre><p>This will translate into an Astoria query that filters, sorts, AND projects all on the server side, leaving me with a network footprint that only transmits the information I want and nothing else. This is a godsend if you have entities with huge amounts of columns but each individual query might only need to use 1 or 2 of those columns at a time.</p><p>And now, if this wasn&#39;t ridiculous enough, you can actually perform updates using the projected objects, AND those updates will ONLY transmit the information necessary. For example, if I only want to change an order&#39;s price and I got the price from a projection, I don&#39;t need to carry the entire order payload across the wire in order to commit the change:</p><pre>order = q.First();<br />order.Quantity = order.Quantity + 42;<br />svc.UpdateObject(order);<br />svc.SaveChanges();</pre><p>This will figure out that the only thing changing is the Quantity field and it will ONLY send that information. After discovering the combination of projections and the efficient round-trips of Astoria, this is when my head exploded.</p><p>If you have a multi-tier scenario and you&#39;re using an Entity Data Model (EDM), then you should definitely look into using ADO.NET Data Services to expose that model via services because now with projections, you can really do some unbelievable stuff. All that garbage code you used to have to generate to convert between DTOs and ViewModels and Entities and back again? You can delete ALL of that crap.</p><p>I&#39;ve said it before but the folks working on ADO.NET Data Services deserve a medal. If you see a member of that team, buy them a beer. You have no idea how ridiculously complicated and difficult it is to write code that supports arbitrary projections like this. I&#39;m pretty sure every time you run an Astoria query with projections, an Angel gets its wings.</p>]]></description><category>astoria</category><category>adonet</category><category>dataservices</category><category>data</category><category>entityframework</category><category>projections</category></item><item><title>Using ASP.NET MVC Action Filters to Declare Reference Data for Views</title><guid isPermaLink="true">http://dotnetaddict.dotnetdevelopersjournal.com/aspnet_actionfilter_referencedata.htm</guid><link>http://dotnetaddict.dotnetdevelopersjournal.com/aspnet_actionfilter_referencedata.htm</link><pubDate>Fri, 02 Oct 2009 16:17:00 GMT</pubDate><comments>http://dotnetaddict.dotnetdevelopersjournal.com/console/comments/popup/?f=aspnet%5Factionfilter%5Freferencedata</comments><dc:creator>Kevin Hoffman</dc:creator><description><![CDATA[<p>When we all build websites, usually we&#39;re concerned with figuring out how we&#39;re going to get the major entities into the view. We want to know how we&#39;re going to handle the shopping cart or how we&#39;re going to get the customer record onto the page, etc. But, one of the little details that almost always comes back to bite us in the ass is the use of <em>reference data</em>.</p><p><em>Reference data</em> is data that rarely changes, is frequently queried, and shows up in multiple places throughout the application. This might be anything from the list of companies currently trading on a particular stock market if you&#39;re building a financial web application or things like the list of countries, states, cities, counties, tax rules, and shipping tables if you&#39;re doing fulfillment of orders online.</p><p>The problem is we rarely think about reference data ahead of time, so what usually happens is our strategy for handling reference data becomes an ugly pile of spaghetti and we have some controls doing their own queries to get reference data and some pages doing it and some services - it&#39;s a mess.</p><p>It would be awesome if we could have our controller methods declare ahead of time what reference data the view is going to need and then the view will simply have that data when it renders - completely abstracting the manual fetching of reference data for dropdownlists and other lookups. This centralization of reference data handling also gives us the ability to control the cache lifetimes of reference data items individually.</p><p>Thankfully ASP.NET MVC lets us do this easily. All we have to do is create our own action filter attribute. For example, let&#39;s say we&#39;ve got a Customer controller and we&#39;re building the <em>Edit(int id)</em> method. Our customer view model objects are normalized enough so that they have IDs on them for country, customer type, and membership type (totally contrived examples, don&#39;t diss my domain knowledge of CRMs...). A sample edit method might look like this:</p><pre>[RequireReferenceData(ReferenceDataKey = ReferenceDataKeys.Countries)]<br />[RequireReferenceData(ReferenceDataKey = ReferenceDataKeys.CustomerTypes)]<br />[ReqiureReferenceData(ReferenceDataKey = ReferenceDataKeys.MembershipTypes)]<br />public ActionResult Edit(int id)<br />{<br />&nbsp;&nbsp;&nbsp; Customer cust = customerRepository.GetCustomerByKey(id);<br />&nbsp;&nbsp;&nbsp; return View(cust);<br />}</pre><p>The beauty of this approach is that <em>anyone</em> reading your code will <em>immediately </em>know that the view being rendered is going to depend on having 3 different types of reference data lists made available, as well as the core <em>Customer</em> object itself. Compare how easy this is to read and maintain to a classic .ASPX page where you might have the countries lookup being loaded by a custom dropdown box and the customer types lookup being loaded by the page and the membership types being loaded by yet another pile of spaghetti elsewhere.</p><p>To create the RequireReferenceDataAttribute class, all you need to do is inherit from ActionFilterAttribute and override the OnExecuting method. In this method you would just fetch the reference data and store it in the ViewData dictionary like this:</p><pre>context.Controller.Model.ViewData[ReferenceDataKey] = (data fetched from elsewhere...);</pre><p>And then in your view you can do something like this:</p><pre>&lt;%= Html.DropDownList(&quot;CustomerTypeId&quot;,&nbsp;<br />(IEnumerable&lt;SelectListItem&gt;)ViewData[ReferenceDataKeys.CustomerTypes]) %&gt;</pre><p>And you&#39;re all set. The main moral of this story is to never underestimate the power of action filters. With ASP.NET MVC, if you want your intent to be more declarative and you want your code to be more readable, chances are you&#39;re only a few lines of code away from where you want to be.</p>]]></description><category>aspnet</category><category>mvc</category><category>actionfilter</category><category>referencedata</category></item><item><title>Creating Correlated Workflow Services in WF4 / .NET4 : Part 1</title><guid isPermaLink="true">http://dotnetaddict.dotnetdevelopersjournal.com/corr_wfservices1.htm</guid><link>http://dotnetaddict.dotnetdevelopersjournal.com/corr_wfservices1.htm</link><pubDate>Wed, 30 Sep 2009 14:02:00 GMT</pubDate><comments>http://dotnetaddict.dotnetdevelopersjournal.com/console/comments/popup/?f=corr%5Fwfservices1</comments><dc:creator>Kevin Hoffman</dc:creator><description><![CDATA[<p>In the past, Windows Workflow Foundation hasn&#39;t gotten a (deservedly so) bad reputation for being full of needless bloat, overly complicated, and missing a lot of key things that make workflow productive for developers. As a result of that, Microsoft completely overhauled WF in the .NET Framework 4.0. One of the new features of WF4 is the concept of a <em>workflow service</em>. A workflow service is really nothing more than a workflow that is hosting WCF endpoints within the activity. This allows the workflow to progress from start to finish by communicating with external clients, such as websites, WPF applications, or Silverlight applications.</p><p>In the sample I&#39;m going to illustrate in this series of blog posts, I&#39;m going to create a customer service helpdesk application. There will be a single workflow at the core of the application - the customer issue workflow. A customer calls complaining that their widget is completely, horribly broken and the customer service rep starts a new issue. The issue then persists forever while communciation goes back and forth between the customer until finally one of the communication types is a &quot;close ticket&quot; type. This is a really simple workflow, but should be similar enough to things that people do in the &quot;real world&quot; that the sample won&#39;t feel contrived or too &quot;hello world&quot;-ish.</p><p>Some of the stuff that I&#39;ll be showing here will look very similar to the WCF/WF 4 Training Kit. The main issue I have with that training kit is that there&#39;s too much &quot;magic&quot; in it. By &quot;magic&quot; I mean stuff that was pre-created for you (like service references consuming the workflow services), so in this sample I&#39;ll walk you through how to create all that magic.</p><p>So to get started let&#39;s create a Sequential workflow and host it in a console app. I would normally host it inside IIS but I couldn&#39;t figure out how to get the HTTP metadata exchange stuff to be published on the .xamlx endpoint. To do this, open up Visual Studio 2010 Beta 1 and create a new project of type <strong>Sequential Workflow Console Application</strong>. Delete the Sequence1.xaml file and add a new sequential workflow to the project called <strong>SupportCall.xaml</strong>. From the toolbar, drag over a <strong>ReceiveAndSendReply</strong> activity from the <strong>Messaging</strong> category. This is the activity that is going to allow your workflow to receive a message via WCF and then do something with it.</p><p>Before we can do something with the message, we need to know what the message looks like. To do that, I added a class library to the solution and created a data contract class that looks like this:</p><p><font face="Consolas" size="2"><font face="Consolas" size="2">[</font></font><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af">DataContract</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">]<br /></font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">public</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">class</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> </font></font><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af">Customer<br /></font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">{<br />[</font></font><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af">DataMember</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">]<br /></font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">public</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">string</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> FirstName { </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">get</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">; </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">set</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">; }</font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> <br />[</font></font><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af">DataMember</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">]<br /></font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">public</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">string</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> LastName { </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">get</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">; </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">set</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">; }<br />[</font></font><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af">DataMember</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">]<br /></font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">public</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">string</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> CustomerID { </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">get</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">; </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">set</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">; }</font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> <br />[</font></font><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af">DataMember</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">]<br /></font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">public</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">string</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> Address1 { </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">get</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">; </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">set</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">; }<br />[</font></font><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af">DataMember</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">]<br /></font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">public</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">string</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> Address2 { </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">get</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">; </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">set</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">; }</font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> <br />[</font></font><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af">DataMember</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">]<br /></font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">public</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">string</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> City { </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">get</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">; </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">set</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">; }<br /></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">[</font></font><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af">DataMember</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">]<br /></font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">public</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">string</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> State { </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">get</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">; </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">set</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">; }</font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> <br />[</font></font><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af"><font face="Consolas" size="2" color="#2b91af">DataMember</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">]<br /></font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">public</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">string</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> Zip { </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">get</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">; </font></font><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff"><font face="Consolas" size="2" color="#0000ff">set</font></font></font><font face="Consolas" size="2"><font face="Consolas" size="2">; }</font></font><font face="Consolas" size="2"><font face="Consolas" size="2"> <br />}</font></font></p><p>Add a reference to the contracts assembly from your workflow project and build the solution. Now you can modify the messaging piece of your workflow to accept messages of type <strong>Customer</strong>. To do this, you need to add a <em>variable</em> to the workflow.</p><p>Click the &quot;Variables&quot; button on the bottom left of the workflow designer surface and add a new variable named <strong>CurrentCustomer</strong>. When you choose the data type, click &quot;Browse&quot; and then type &quot;Customer&quot;, you should find under the &quot;Referenced Assemblies&quot; tree node the customer class from the contracts assembly. When you&#39;ve created this variable, your variables area should look something like this:</p><p><img src="http://files.blog-city.com/files/J05/88284/p/f/wf4_seq0.png" alt="" width="749" height="173" /></p><p>In order to receive data from a message, you need somewhere to put that data. In a workflow service, that somewhere is a variable. Now you can go and click on the Receive-Reply sequence and edit it so that the operation name is <strong>StartIssue</strong>, the service contract name is <strong>CustomerIssueService</strong> and the <em>Value</em> property (where the message value is stored) is the name of the variable we just created: <strong>CurrentCustomer</strong>. When you&#39;re done editing the receive-sendreply sequence, it should look something like this:</p><p><img src="http://files.blog-city.com/files/J05/88284/p/f/wf4_seq1.png" alt="" width="371" height="512" /></p><p>I modified the sendreply portion of the sequence and set the value to the following:</p><pre>&quot;A new issue has been created for &quot; + CurrentCustomer.FirstName + &quot; &quot; + CurrentCustomer.LastName</pre><p>If you&#39;re curious, the syntax for rules and expressions inside WF4 is ... *drumroll* ... <strong>Visual Basic!! </strong>This is important to keep in mind if you&#39;re in there editing rules and the rest of your application is written in C# - your stuff won&#39;t work if you start throwing C# syntax into the expression editors.</p><p>We&#39;re almost there. At this point we now have a workflow, but our solution won&#39;t compile because our <strong>Program.cs</strong> file from the stock VS template is full of junk related to launching <strong>Sequence1.xaml</strong>. Modify your <strong>Program.cs</strong> file to look like this:</p><pre>namespace CustomerSupport.Services<br />{<br />&nbsp;&nbsp;&nbsp; using System;<br />&nbsp;&nbsp;&nbsp; using System.Linq;<br />&nbsp;&nbsp;&nbsp; using System.Threading;<br />&nbsp;&nbsp;&nbsp; using System.Activities;<br />&nbsp;&nbsp;&nbsp; using System.Activities.Statements;<br />&nbsp;&nbsp;&nbsp; using System.ServiceModel.Activities;<br />&nbsp;&nbsp;&nbsp; using System.ServiceModel.Description;<br /><br /><br />&nbsp;&nbsp;&nbsp; <br />    class Program<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void Main(string[] args)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string baseAddress = http://localhost:8081/SupportCall;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />            using (WorkflowServiceHost host = <br />              new WorkflowServiceHost(typeof(SupportCall), new Uri(baseAddress)))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; host.Description.Behaviors.Add(new ServiceMetadataBehavior() { HttpGetEnabled = true });<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; host.AddDefaultEndpoints();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />                host.Open();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(&quot;Customer Support Service listening at: &quot; + <br />                  baseAddress);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(&quot;Press ENTER to exit&quot;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.ReadLine();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; host.Close();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; }<br />}</pre><p>Now we should be able to compile and when we run our console application (requires VS to be elevated!) we should see the message indicating that customer support service is running. We can quit the app now.</p><p>To create the client (we&#39;ll be making a better client in future blog posts) let&#39;s just create a new console application and add a reference to the contracts assembly. In order to add a service reference to the workflow service, you have to launch the workflow service console app from the command prompt because you can&#39;t add service references while Visual Studio is currently debugging something. </p><p>Modify the Program.cs for the client console application (after adding a service reference) to look like this:</p><pre>static void Main(string[] args)<br />{<br />&nbsp;&nbsp;&nbsp; CustomerIssueService.CustomerIssueServiceClient svc = <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new CustomerSupport.Client.CustomerIssueService.CustomerIssueServiceClient();</pre><pre>&nbsp;&nbsp;&nbsp; Customer cust = new Customer();<br />&nbsp;&nbsp;&nbsp; cust.FirstName = &quot;Bob&quot;;<br />&nbsp;&nbsp;&nbsp; cust.LastName = &quot;Asdf&quot;;<br />&nbsp;&nbsp;&nbsp; cust.Address1 = &quot;666 Evil Lane&quot;;<br />&nbsp;&nbsp;&nbsp; cust.Address2 = &quot;&quot;;<br />&nbsp;&nbsp;&nbsp; cust.City = &quot;Hades&quot;;<br />&nbsp;&nbsp;&nbsp; cust.State = &quot;NJ&quot;;<br />&nbsp;&nbsp;&nbsp; cust.Zip = &quot;99999&quot;;<br />&nbsp;&nbsp;&nbsp; cust.CustomerID = &quot;ASDF&quot;;<br />&nbsp;&nbsp;&nbsp; string response = svc.<strong><em>StartIssue</em></strong>(cust);<br />&nbsp;&nbsp;&nbsp; Console.WriteLine(response);<br />&nbsp;&nbsp;&nbsp; Console.ReadLine();<br />}</pre><p>Now you can run the application and you&#39;ll see a line of text indicating that a new issue has been created for customer <em>Bob Asdf</em>. In the next blog post, I&#39;m going to walk through adding more steps to the workflow to make it more realistic, including adding another web service call in the same service that uses <em>correlation</em> so that we can progress multiple instances of multiple workflows and correlate the messages to the right workflows based on message content.</p><p>Some things to keep in mind as you wait eagerly for the next blog post are how the naming of the service contract and operation name affect the names of the methods and proxies created when you add a service reference to the workflow service.</p>]]></description><category>wf4</category><category>workflow</category><category>net4</category><category>wcf</category><category>services</category><category>correlation</category></item><item><title>How to Build your First Azure-Powered MVC App</title><guid isPermaLink="true">http://dotnetaddict.dotnetdevelopersjournal.com/how_to_build_your_first_azurepowered_mvc_app.htm</guid><link>http://dotnetaddict.dotnetdevelopersjournal.com/how_to_build_your_first_azurepowered_mvc_app.htm</link><pubDate>Tue, 29 Sep 2009 14:16:00 GMT</pubDate><comments>http://dotnetaddict.dotnetdevelopersjournal.com/console/comments/popup/?f=how%5Fto%5Fbuild%5Fyour%5Ffirst%5Fazurepowered%5Fmvc%5Fapp</comments><dc:creator>Kevin Hoffman</dc:creator><description><![CDATA[<p>A good friend and colleague of mine has put up a great tutorial that walks you through the process of creating a new &quot;classic&quot; ASP.NET Azure web application and converting it into a cloud-based MVC application. In addition, he shows you how to point your membership, profile, and role providers at Azure cloud storage instead of the default SQL Express. Great read, check it out here:</p><p><a href="http://www.caffeinedi.com/2009/09/29/how-to-build-your-first-azure-powered-asp-net-mvc-app/">http://www.caffeinedi.com/2009/09/29/how-to-build-your-first-azure-powered-asp-net-mvc-app/</a></p>]]></description><category>mvc</category><category>aspnet</category><category>cloud</category><category>azure</category></item><item><title>Binary Serialization and Azure Web Applications</title><guid isPermaLink="true">http://dotnetaddict.dotnetdevelopersjournal.com/azure_binaryserialization.htm</guid><link>http://dotnetaddict.dotnetdevelopersjournal.com/azure_binaryserialization.htm</link><pubDate>Tue, 29 Sep 2009 00:54:00 GMT</pubDate><comments>http://dotnetaddict.dotnetdevelopersjournal.com/console/comments/popup/?f=azure%5Fbinaryserialization</comments><dc:creator>Kevin Hoffman</dc:creator><description><![CDATA[<p>You might be thinking, <em>pfft, I&#39;m never going to need to use Binary Serialization...that&#39;s old school</em>. And you might be right, but think about this: Azure Storage charges you by how much you&#39;re storing and some aspects of Azure also charge you based on the bandwidth consumed. Do you want to store/transmit a big-ass bloated pile of XML or do you want to store/transmit a condensed binary serialization of your object graph?</p><p>I&#39;m using Blob and Queue storage for several things and I&#39;ve actually got a couple of projects going right now where I&#39;m using binary serialization for both Blobs and Queue messages. The problem shows up when you try and use the <strong>BinaryFormatter</strong> class&#39; Serialize method. This method requires the <em>Security</em> privilege, which your code doesn&#39;t have when its running in the default Azure configuration.</p>So how do you fix this problem so that you can successfully serialize/deserialize binary object graphs and maybe save a buck or two? Easy! Turn on full-trust in your service definition for whichever role is going to be using the binary serialization (in my case both my worker and web roles will be using it...). To do this, open up your service definition file and look for the line that looks like this:&nbsp;<font size="2" color="#0000ff"><font size="2" color="#0000ff"></font></font><font size="2" color="#0000ff"><font size="2" color="#0000ff"> <p>&lt;<font size="2" color="#a31515"><font size="2" color="#a31515">WebRole</font></font><font size="2" color="#0000ff"><font size="2" color="#0000ff"> </font></font><font size="2" color="#ff0000"><font size="2" color="#ff0000">name</font></font><font size="2" color="#0000ff"><font size="2" color="#0000ff">=</font></font><font size="2">&quot;</font><font size="2" color="#0000ff"><font size="2" color="#0000ff">Foo.Web</font></font><font size="2">&quot;</font><font size="2" color="#0000ff"><font size="2" color="#0000ff"> </font></font><font size="2" color="#ff0000"><font size="2" color="#ff0000">enableNativeCodeExecution</font></font><font size="2" color="#0000ff"><font size="2" color="#0000ff">=</font></font><font size="2">&quot;</font><font size="2" color="#0000ff"><font size="2" color="#0000ff"><strong>false</strong></font></font><font size="2">&quot;</font><font size="2" color="#0000ff"><font size="2" color="#0000ff">&gt;</font></font></p></font></font><p>And change it to this:</p><font size="2" color="#0000ff"><font size="2" color="#0000ff"><p>&lt;<font size="2" color="#a31515"><font size="2" color="#a31515">WebRole</font></font><font size="2" color="#0000ff"><font size="2" color="#0000ff"> </font></font><font size="2" color="#ff0000"><font size="2" color="#ff0000">name</font></font><font size="2" color="#0000ff"><font size="2" color="#0000ff">=</font></font><font size="2">&quot;</font><font size="2" color="#0000ff"><font size="2" color="#0000ff">Foo.Web</font></font><font size="2">&quot;</font><font size="2" color="#0000ff"><font size="2" color="#0000ff"> </font></font><font size="2" color="#ff0000"><font size="2" color="#ff0000">enableNativeCodeExecution</font></font><font size="2" color="#0000ff"><font size="2" color="#0000ff">=</font></font><font size="2">&quot;</font><font size="2" color="#0000ff"><font size="2" color="#0000ff"><strong>true</strong></font></font><font size="2">&quot;</font><font size="2" color="#0000ff"><font size="2" color="#0000ff">&gt;</font></font></p></font></font><p>You&#39;ll have to do this for your WorkerRole as well if you want your worker role to be able to do this kind of serialization.&nbsp;That&#39;s it...Now when you run your application it will have sufficient privileges to perform the serialization/deserialization to keep your storage and transmission payloads as small as possible.</p>]]></description><category>azure</category><category>table</category><category>queue</category><category>blob</category><category>storage</category><category>binary</category><category>serialization</category></item><item><title>ASP.NET Membership Provider in the Cloud : The Chicken and the Egg Problem</title><guid isPermaLink="true">http://dotnetaddict.dotnetdevelopersjournal.com/aspnet_cloud_membership.htm</guid><link>http://dotnetaddict.dotnetdevelopersjournal.com/aspnet_cloud_membership.htm</link><pubDate>Mon, 28 Sep 2009 15:22:00 GMT</pubDate><comments>http://dotnetaddict.dotnetdevelopersjournal.com/console/comments/popup/?f=aspnet%5Fcloud%5Fmembership</comments><dc:creator>Kevin Hoffman</dc:creator><description><![CDATA[<p>Let&#39;s take a look at this pretty common scenario. You&#39;re building an ASP.NET application (MVC or otherwise) and you intend to publish it in the cloud and you&#39;re using Azure Storage (not SQL Azure) for your underlying data store. You&#39;ve already hooked your app up with the sample Azure-based Membership provider that comes with the Azure SDK and everything is running along nicely.</p><p>Your application has quite a bit of administrator-only functionality so, after you&#39;ve been using it locally for a while you put in some safeguards to block access to the admin areas unless the user is in the <em>Administrators</em> role. That&#39;s awesome and ASP.NET and ASP.NET MVC both have some really great code shortcuts for enabling this kind of situation and you can make yourself an administrator pretty darn easily.</p><p>So you&#39;re an admin and you deploy your application to staging and you go to run it and you try to log in. <em>Whoops</em> your account isn&#39;t there. This is because for the last couple of weeks you&#39;ve been running against your local SQL 2008 (or SQL Express) database and you forgot that you did a few tweaks to make yourself an administrator. In the last couple of weeks you removed the code on the site that allows users to self-register since your application is an LOB app with a manually administered user list.</p><p>There is a built-in tool that comes with Visual Studio 2008 that allows you to do site administration. In a non-cloud environment, this was a great way to do things because you could simply configure your providers and then click &quot;Project&quot; and then &quot;ASP.NET Configuration&quot; and you would be taken to a Cassini-based website that allows you to add/remove users, manipulate roles, etc. It was great.</p><p>The problem is that when you run an Azure application locally, you&#39;re running the <em>Role</em>, you&#39;re not running the ASP.NET application. This means that when you launch (at least as of last night when I tried this) the ASP.NET configuration site, you&#39;re going to get a pile of errors all stemming from the fact that information contained in your service configuration file wasn&#39;t found and you&#39;ll get other errors because the <em>local fabric</em> doesn&#39;t get initialized when you don&#39;t start the app through the role.</p><p>So what can you do? If you can&#39;t use the admin site&nbsp; then how do you create an admin user that can then create more users? Lots of really talented people have contributed to the MVC community including a fully functional admin site that uses the membership provider to administer users, etc and you can use this if you want. What I&#39;ve been doing, however, to ensure that I&#39;m never left without <em>some</em> form of administrative access to my sites is by creating a <em><strong>root account</strong></em>.</p><p>What I do is in the service definition I declare three settings:&nbsp;RootAccountName, RootAccountPassword, AdminRoleName. I then have code in my application startup that will use the Membership API to create this user with the given password and add them to the Admin Role (and create that role if it isn&#39;t created already). This guarantees me that any time I do a fresh deploy or even wipe my storage account that I&#39;ll still be able to login as an administrator to stage or production and I can keep the root account name different between stage and production.</p><p>Again, Azure development is awesome and shares a lot of similarities with traditional ASP.NET development but some things (like the built-in site admin tool) don&#39;t work out of the box via the cloud and so we have to keep these things in mind as we build applications for the cloud.</p>]]></description><category>aspnet</category><category>mvc</category><category>azure</category><category>cloud</category><category>membership</category></item><item><title>Configuration Settings in Azure Applications</title><guid isPermaLink="true">http://dotnetaddict.dotnetdevelopersjournal.com/azure_configurationsettings.htm</guid><link>http://dotnetaddict.dotnetdevelopersjournal.com/azure_configurationsettings.htm</link><pubDate>Mon, 28 Sep 2009 14:59:00 GMT</pubDate><comments>http://dotnetaddict.dotnetdevelopersjournal.com/console/comments/popup/?f=azure%5Fconfigurationsettings</comments><dc:creator>Kevin Hoffman</dc:creator><description><![CDATA[<p>One of the double-edged swords of Azure is that it feels so much like building regular web applications. This is a good thing in that you can re-use so much of your existing skills, knowledge, and best practices and they will still apply in the Azure world. However, it is really easy to make assumptions about how things work that turn out to be wrong.</p><p>For example, if you look at just about 99% of the Azure samples, blogs, and other reference material, you will see stuff that looks like the code below, sitting right inside <strong>web.config</strong>:</p><pre>&lt;add key=&quot;TableStorageEndpoint&quot; value=&quot;http://foo.table.core.cloudapp.net&quot;/&gt;<br />&lt;add key=&quot;QueueStorageEndpoint&quot; value=&quot;http://foo.queue.core.cloudapp.net&quot;/&gt;<br />&lt;add key=&quot;BlobStorageEndpoint&quot;&nbsp; value=&quot;http://foo.blog.core.cloudapp.net&quot;/&gt;<br />&lt;add key=&quot;AccountName&quot;&nbsp;&nbsp; value=&quot;foo&quot;/&gt;<br />&lt;add key=&quot;AccountSharedKey&quot;&nbsp;&nbsp; value=&quot;...lotsa stuff...&quot;/&gt;</pre><p>If you were to make assumptions about this, one might assume that you should be putting stuff like this in your web.config file even when you go to staging and production. NO! Stop right there!! This is not how Azure configuration settings are supposed to work!</p><p>Equally prevalent in the samples you will find calls to methods like <strong>GetDefaultTableStorageAccountFromConfiguration</strong>. there is actually a bit of useful logic going on in here that might not be immediately obvious.</p><p>This method is going to make attempts at getting configuration information from multiple different locations. It will check the web.config/app.config file, but it will also check your <em>service configuration</em> file. The most important thing to remember about this file is that it <em>can be edited directly from the Azure portal</em>. This means that you can deploy your application to stage and then go in and edit the service configuration file to change all the endpoints to your staging endpoints, then activate your app.</p><p>The reason this is important is because you never, <em>ever, ever</em> want to include your Azure key information in your web.config file, especially if you&#39;re posting on forums or sharing your code with other people. This is because if anybody gets your account name and shared key combination, they have full access to your Azure storage account and can basically run amok all over your data.</p><p>So, how do you know when you use a <em>service configuration</em> setting vs. a <em>web.config</em> setting? Here&#39;s a quick rundown:</p><ul><li>If you need to be able to edit the information after deploying, <em>it must be in service configuration</em> and <em><strong>not</strong></em> in web.config</li><li>If the information only changes once per full deploy to production, e.g. it&#39;s version bound not environment bound, you can leave the setting in web.config</li></ul><p>So, for example, in a typical Azure application, you might store the names of your queues and tables in web.config (because they should rarely change and will remain the same between stage and production), but you&#39;ll put the endpoint information related to your Azure Storage account in the service configuration file. </p><p>Hope this helps. The key thing to remember is that Azure service configuration can be a really powerful tool if you know its there... it can also screw you up if you forget its there :)</p>]]></description><category>azure</category><category>configuration</category><category>sdlc</category><category>cloud</category></item></channel></rss>