<?xml version="1.0" encoding="iso-8859-1"?><!-- generator="b2evolution/4.0.3" -->
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>All Blogs - Author(s): Eli Weinstock-Herman (tarwn)</title>
		<link>http://blogs.lessthandot.com/index.php/All/</link>
		<atom:link rel="self" type="application/rss+xml" href="http://blogs.lessthandot.com/index.php/All/?tempskin=_rss2" />
		<description>LessThanDot A Technical Community for IT Professionals</description>
		<language>en-US</language>
		<docs>http://blogs.law.harvard.edu/tech/rss</docs>
		<admin:generatorAgent rdf:resource="http://b2evolution.net/?v=4.0.3"/>
		<ttl>60</ttl>
				<item>
			<title>Deploying Database Changes with PowerShell</title>
			<link>http://blogs.lessthandot.com/index.php/DataMgmt/DBProgramming/deploying-database-changes-with-powershell</link>
			<pubDate>Fri, 17 May 2013 07:36:00 +0000</pubDate>			<dc:creator>Eli Weinstock-Herman (tarwn)</dc:creator>
			<category domain="main">Database Programming</category>
<category domain="alt">Microsoft SQL Server</category>			<guid isPermaLink="false">2190@http://blogs.lessthandot.com/</guid>
						<description>&lt;p&gt;Recently, while working on a personal project, I found myself needing a lightweight way to deploy database changes to multiple environments. In the past I have used a wide range of methods, ranging from applying the changes manually to applying changes via a diff tool (SQL Compare), to automatically applying manually created change scripts, to automatically applying diff scripts that were automatically generated, to working directly in production..er, pretend you didn&#039;t see that one. &lt;/p&gt;

&lt;h2&gt;Why not _________ tool?&lt;/h2&gt;

&lt;p&gt;There are a lot of tools out there to handle database deployments, but this is a small project that I am building incrementally as a minimum viable product. Rather than tie up a bunch of time researching and experimenting with database deployment tools early on, I decided to do something simple that would work for the time being and free me up to work on the actual product. &lt;/p&gt;

&lt;p&gt;What I want from the deployment is to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Spend as little time on this as possible&lt;/li&gt;
&lt;li&gt;Work against SQL Azure and a local 2008 R2 Server&lt;/li&gt;
&lt;li&gt;Call it from TeamCity for a local server or a remote one&lt;/li&gt;
&lt;li&gt;Produce readable output for TeamCity logs&lt;/li&gt;
&lt;li&gt;Create the databases and users from the ground up&lt;/li&gt;
&lt;li&gt;Include randomly generated data&lt;/li&gt;
&lt;li&gt;Manage scripts for 2 independent databases in the same build&lt;/li&gt;
&lt;li&gt;Allow real SQL (I&#039;m not scared of SQL and I don&#039;t want to learn a code abstraction just to deploy changes)&lt;/li&gt;
&lt;li&gt;Not worry about rollbacks. I am deploying small changes and if something breaks I&#039;ll be charging forward&lt;/li&gt;
&lt;li&gt;Not expose credentials, as the code will be visible to the public&lt;/li&gt;
&lt;li&gt;Be replaceable. I might replace it with a tool one day, so keep the deployment logic separate from the application&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Looking back at this list and what I eventually created, I probably could have used something like &lt;a href=&quot;https://github.com/brunomlopes/dbdeploy.net&quot; &quot;dbdploy on github&quot;&gt;DBDeploy&lt;/a&gt;. The scripts I created ended up taking a very similar approach.&lt;/p&gt;

&lt;h2&gt;The Deployment Scripts&lt;/h2&gt;

&lt;p&gt;My deployment consists of 4 PowerShell scripts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ApplyDatabaseUpdates.ps1&lt;/strong&gt; - Responsible for generically applying changes from a folder to a specified database&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UpdateCoreDatabase.ps1&lt;/strong&gt; - Responsible for the application&#039;s Core Database, calls ApplyDatabaseUpdates&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UpdateSampleDatabase.ps1&lt;/strong&gt; - Response for the application&#039;s Sample Database, calls ApplyDatabaseUpdates&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RunLocally.ps1&lt;/strong&gt; - Executes the two Update scripts against the local database on my development machine(s)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This project has been spread out over 6 months, intermixed with life, other projects, blog posts, etc. Along the way I also upgraded my local development machine to SQL Server 2012 but my main test database server is on 2008 still and my release environment is Azure Database/SQL Azure/(whatever the name is this week).&lt;/p&gt;

&lt;h3&gt;ApplyDatabaseUpdates.ps1&lt;/h3&gt;
&lt;p&gt;The purpose of the ApplyDatabaseUpdates script is to apply all of the scripts in a specified folder to the specified server. To do this it creates a tracking table on the target database, then iterates through the contents of the folder, building a script containing any files that were not previously logged in the tracking table.&lt;/p&gt;

&lt;div style=&quot;text-align:center; color: #666666;&quot;&gt;
   &lt;img src=&quot;http://tiernok.com/LTDBlog/DatabaseDeployment/SQLScripts.png&quot; alt=&quot;Core DB Scripts folder&quot; /&gt;&lt;br /&gt;
   Core Database Scripts Folder
&lt;/div&gt;

&lt;p&gt;The deployment script wraps the contents of each script file in an EXECUTE statement, followed by an INSERT to add it to the tracking table for the database.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;&lt;a href=&quot;https://github.com/tarwn/SQLisHard/blob/master/Database/ApplyDatabaseUpdates.ps1&quot; title=&quot;View on github&quot;&gt;ApplyDatabaseUpdates.ps1&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;powershell&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;powershell&quot; id=&quot;cb96929&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;function ApplyDatabaseUpdates&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; &amp;nbsp; param (&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; [parameter(Mandatory=$true)]&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; [string]&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $UpdatesFolder,&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; [parameter(Mandatory=$true)]&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; [string]&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $Server,&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; [parameter(Mandatory=$true)]&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; [string]&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $Database,&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; [parameter(Mandatory=$true)]&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; [string]&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $AdminUserName,&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; [parameter(Mandatory=$true)]&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; [string]&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $AdminPassword&lt;br /&gt;&amp;nbsp; &amp;nbsp; )&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; $path = (Get-Location).Path&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; # For SQL 2008 - load the modules&lt;br /&gt;&amp;nbsp; &amp;nbsp; try{ &amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if ( (Get-PSSnapin -Name SqlServerCmdletSnapin100 -ErrorAction SilentlyContinue) -eq $null -and (Get-PSSnapin -Registered -Name SqlServerCmdletSnapin100 -ErrorAction SilentlyContinue) -ne $null){&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Add-PSSnapin SqlServerCmdletSnapin100 -ErrorAction SilentlyContinue&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Add-PSSnapin SqlServerProviderSnapin100 -ErrorAction SilentlyContinue&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp; &amp;nbsp; catch{&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Write-Error &amp;quot;Powershell Script error: $_&amp;quot; -EA Stop&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; #updates tracking&lt;br /&gt;&amp;nbsp; &amp;nbsp; try{&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Write-Host &amp;quot;Creating Update Tracking Table If Not Exists&amp;quot;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Invoke-Sqlcmd -Query &amp;quot;IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = &#039;UpdateTracking&#039;) CREATE TABLE UpdateTracking (UpdateTrackingKey int IDENTITY(1,1) PRIMARY KEY, Name varchar(255) NOT NULL, Applied DateTime NOT NULL);&amp;quot; -ServerInstance &amp;quot;$Server&amp;quot; -Username &amp;quot;$AdminUserName&amp;quot; -Password &amp;quot;$AdminPassword&amp;quot; -Database &amp;quot;$Database&amp;quot; -ErrorAction Stop&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Write-Host &amp;quot;Done&amp;quot;&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp; &amp;nbsp; catch{&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Write-Error &amp;quot;Powershell Script error: $_&amp;quot; -EA Stop&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; #database updates&lt;br /&gt;&amp;nbsp; &amp;nbsp; $outputPath = &amp;quot;$path\UpdatesBatch.sql&amp;quot;&lt;br /&gt;&amp;nbsp; &amp;nbsp; $stream = [System.IO.StreamWriter] &amp;quot;$outputPath&amp;quot;&lt;br /&gt;&amp;nbsp; &amp;nbsp; $fileUpdates = Get-ChildItem &amp;quot;$UpdatesFolder&amp;quot;&lt;br /&gt;&amp;nbsp; &amp;nbsp; $datestamp = $(get-date -f &amp;quot;yyyy-MM-dd HH:mm&amp;quot;)&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; $stream.WriteLine(&amp;quot;/* SQL Core Updates - Updated $datestamp */&amp;quot;)&lt;br /&gt;&amp;nbsp; &amp;nbsp; $stream.WriteLine(&amp;quot;BEGIN TRANSACTION&amp;quot;)&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; foreach($file in $fileUpdates)&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $name = ($file.Name)&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $namewe = ([System.IO.Path]::GetFileNameWithoutExtension($name))&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $stream.WriteLine(&amp;quot;&amp;quot;)&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $stream.WriteLine(&amp;quot;/* File: $name */&amp;quot;)&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $stream.WriteLine(&amp;quot;IF NOT EXISTS (SELECT 1 FROM UpdateTracking WHERE Name = &#039;$namewe&#039;)&amp;quot;)&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $stream.WriteLine(&amp;quot;BEGIN&amp;quot;)&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $stream.WriteLine(&amp;quot;`tPrint &#039;Applying Update: $namewe&#039;&amp;quot;)&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $stream.WriteLine(&amp;quot;`tEXEC(&#039;&amp;quot;)&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (Get-Content &amp;quot;$UpdatesFolder\$name&amp;quot;) | % {$_ -replace &amp;quot;&#039;&amp;quot;, &amp;quot;&#039;&#039;&amp;quot;} | % {$stream.WriteLine(&amp;quot;`t`t$_&amp;quot;)}&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $stream.WriteLine(&amp;quot;`t&#039;);&amp;quot;)&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $stream.WriteLine(&amp;quot;`tINSERT INTO UpdateTracking(Name, Applied) SELECT &#039;$namewe&#039;, GETUTCDATE();&amp;quot;)&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $stream.WriteLine(&amp;quot;END&amp;quot;)&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; $stream.WriteLine(&amp;quot;COMMIT TRANSACTION&amp;quot;)&lt;br /&gt;&amp;nbsp; &amp;nbsp; $stream.Close()&lt;br /&gt;&amp;nbsp; &amp;nbsp; Write-Host &amp;quot;Update Script Created.&amp;quot;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Write-Host &amp;quot;Running updates...&amp;quot;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Invoke-SqlCmd -InputFile &amp;quot;$outputPath&amp;quot; -ServerInstance &amp;quot;$Server&amp;quot; -Username &amp;quot;$AdminUserName&amp;quot; -Password &amp;quot;$AdminPassword&amp;quot; -Database &amp;quot;$Database&amp;quot; -Verbose -ErrorAction Stop&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Remove-Item &amp;quot;$outputPath&amp;quot;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Write-Host &amp;quot;Updates completed.&amp;quot;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb34988&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;i style=&quot;display: block; padding: 1em; margin: 1em; background-color: #eeeeee&quot;&gt;Note: this has only been run in the context of my personal project. That means don&#039;t copy, paste, and run it immediately against your production environment. Running stuff blindly from the internet is known as both a bad idea and a career limiting maneuver.&lt;/i&gt;&lt;/p&gt;

&lt;h3&gt;Update____Database.ps1&lt;/h3&gt;

&lt;p&gt;My application has two databases which it will access via different accounts. I want the ability to rebuild these databases from scratch as well as manage their credentials from an external system (in this case, TeamCity). If the worst should happen and these databases are compromised or overwritten in some fashion, I want to be able to recreate them with new credentials, account names, the works. &lt;/p&gt;

&lt;p&gt;To make life more difficult, many of these commands have to be executed individually in order to work with Azure Databases.&lt;/p&gt;

&lt;p&gt;Both scripts detect if their specified database exists and, if not, create them. The UpdateSampleDatabase is capable of recreating the database in Azure, provided some extra options are passed in to it (the Core Database script is missing this bit, unfortunately):&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Excerpt from &lt;a href=&quot;https://github.com/tarwn/SQLisHard/blob/master/Database/UpdateSampleDatabase.ps1&quot; title=&quot;View on github&quot;&gt;UpdateSampleDatabase.ps1&lt;/a&gt;:&lt;/b&gt;&lt;/p&gt;
&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;powershell&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;powershell&quot; id=&quot;cb61050&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;# ...&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; #database&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Write-Host &amp;quot;Checking database exists...&amp;quot;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $result = Invoke-Sqlcmd -Query &amp;quot;SELECT [name] FROM [sys].[databases] WHERE [name] = N&#039;$database&#039;&amp;quot; -ServerInstance &amp;quot;$Server&amp;quot; -Username &amp;quot;$AdminUserName&amp;quot; -Password &amp;quot;$AdminPassword&amp;quot; -Database &amp;quot;master&amp;quot; -ErrorAction Stop&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if($result.name){&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Write-Host &amp;quot;Database already exists&amp;quot;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; else{&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Write-Host &amp;quot;Creating Database: $database&amp;quot;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Invoke-Sqlcmd -Query &amp;quot;CREATE DATABASE $database&amp;quot; -ServerInstance &amp;quot;$Server&amp;quot; -Username &amp;quot;$AdminUserName&amp;quot; -Password &amp;quot;$AdminPassword&amp;quot; -Database &amp;quot;master&amp;quot; -ErrorAction Stop&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Invoke-Sqlcmd -Query &amp;quot;ALTER DATABASE $database SET RECOVERY SIMPLE&amp;quot; -ServerInstance &amp;quot;$Server&amp;quot; -Username &amp;quot;$AdminUserName&amp;quot; -Password &amp;quot;$AdminPassword&amp;quot; -Database &amp;quot;master&amp;quot; -ErrorAction Stop&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Write-Host &amp;quot;Created.&amp;quot;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; # ...&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb85330&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;They also generate the users specified by the build server (which will also be dynamically added into the relevant web.config files for the website):&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Excerpt from &lt;a href=&quot;https://github.com/tarwn/SQLisHard/blob/master/Database/UpdateCoreDatabase.ps1&quot; title=&quot;View on github&quot;&gt;UpdateCoreDatabase.ps1&lt;/a&gt;:&lt;/b&gt;&lt;/p&gt;
&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;powershell&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;powershell&quot; id=&quot;cb32078&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;# ...&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; #user&lt;br /&gt;&amp;nbsp; &amp;nbsp; try{&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Write-Host &amp;quot;Creating User: $NewUserName&amp;quot;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $result = Invoke-Sqlcmd -Query &amp;quot;SELECT [name] FROM sys.sql_logins WHERE name = &#039;$NewUserName&#039;&amp;quot; -ServerInstance &amp;quot;$Server&amp;quot; -Username &amp;quot;$AdminUserName&amp;quot; -Password &amp;quot;$AdminPassword&amp;quot; -Database &amp;quot;master&amp;quot; -ErrorAction Stop&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if($result.name){&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Write-Host &amp;quot;Login already exists&amp;quot;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; else{&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Write-Host &amp;quot;Creating login...&amp;quot;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Invoke-Sqlcmd -Query &amp;quot;CREATE LOGIN $NewUserName WITH PASSWORD = &#039;$NewPassword&#039;&amp;quot; -ServerInstance &amp;quot;$Server&amp;quot; -Username &amp;quot;$AdminUserName&amp;quot; -Password &amp;quot;$AdminPassword&amp;quot; -Database &amp;quot;master&amp;quot; -ErrorAction Stop&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Write-Host &amp;quot;Login Created.&amp;quot;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $result = Invoke-Sqlcmd -Query &amp;quot;SELECT [name] FROM sys.sysusers WHERE name = &#039;$NewUserName&#039;&amp;quot; -ServerInstance &amp;quot;$Server&amp;quot; -Username &amp;quot;$AdminUserName&amp;quot; -Password &amp;quot;$AdminPassword&amp;quot; -Database &amp;quot;$Database&amp;quot; -ErrorAction Stop&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if($result.name){&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Write-Host &amp;quot;User already exists&amp;quot;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; else{&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Write-Host &amp;quot;Creating user...&amp;quot;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Invoke-Sqlcmd -Query &amp;quot;CREATE USER $NewUserName FOR LOGIN $NewUserName WITH DEFAULT_SCHEMA = dbo&amp;quot; -ServerInstance &amp;quot;$Server&amp;quot; -Username &amp;quot;$AdminUserName&amp;quot; -Password &amp;quot;$AdminPassword&amp;quot; -Database &amp;quot;$Database&amp;quot; -ErrorAction Stop&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Invoke-Sqlcmd -Query &amp;quot;EXEC sp_addrolemember &#039;db_datareader&#039;,&#039;$NewUserName&#039;; EXEC sp_addrolemember &#039;db_datawriter&#039;,&#039;$NewUserName&#039;&amp;quot; -ServerInstance &amp;quot;$Server&amp;quot; -Username &amp;quot;$AdminUserName&amp;quot; -Password &amp;quot;$AdminPassword&amp;quot; -Database &amp;quot;$Database&amp;quot; -ErrorAction Stop&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Write-Host &amp;quot;User Created.&amp;quot;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp; &amp;nbsp; catch{&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Write-Error &amp;quot;Powershell Script error: $_&amp;quot; -EA Stop&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; # ...&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb82431&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Once the database and users are created, the SampleDatabase script produces a replacement for one of it&#039;s script files that will contain some randomized data. The original file is a placeholder and produces an error if it hasn&#039;t been replaced.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Excerpt from &lt;a href=&quot;https://github.com/tarwn/SQLisHard/blob/master/Database/UpdateSampleDatabase.ps1&quot; title=&quot;View on github&quot;&gt;UpdateSampleDatabase.ps1&lt;/a&gt;:&lt;/b&gt;&lt;/p&gt;
&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;powershell&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;powershell&quot; id=&quot;cb67763&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;# ...&lt;br /&gt;&amp;nbsp;&lt;br /&gt;# ---------------------------------- Content Generation ---------------------------------------------&lt;br /&gt;# Scripts to generate content dynamically and update the appropriate update script&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; #generate customers table content&lt;br /&gt;&amp;nbsp; &amp;nbsp; $CustomersContentPath = &amp;quot;$UpdatesFolder\0002_CustomersData.sql&amp;quot;&lt;br /&gt;&amp;nbsp; &amp;nbsp; try{&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Write-Host &amp;quot;Generating content script for dbo.Customers&amp;quot;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $girlsnames = (&amp;quot;&amp;lt;ns&amp;gt;&amp;lt;n&amp;gt;&amp;quot; + [string]::Join(&amp;quot;&amp;lt;/n&amp;gt;&amp;lt;n&amp;gt;&amp;quot;,(Get-Content &amp;quot;$path\Data\girlsforenames.txt&amp;quot;)) + &amp;quot;&amp;lt;/n&amp;gt;&amp;lt;/ns&amp;gt;&amp;quot;).Replace(&amp;quot;&#039;&amp;quot;,&amp;quot;&#039;&#039;&amp;quot;)&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $boysnames = &amp;nbsp;(&amp;quot;&amp;lt;ns&amp;gt;&amp;lt;n&amp;gt;&amp;quot; + [string]::Join(&amp;quot;&amp;lt;/n&amp;gt;&amp;lt;n&amp;gt;&amp;quot;,(Get-Content &amp;quot;$path\Data\boysforenames.txt&amp;quot;)) + &amp;quot;&amp;lt;/n&amp;gt;&amp;lt;/ns&amp;gt;&amp;quot;).Replace(&amp;quot;&#039;&amp;quot;,&amp;quot;&#039;&#039;&amp;quot;)&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $lastnames = &amp;nbsp;(&amp;quot;&amp;lt;ns&amp;gt;&amp;lt;n&amp;gt;&amp;quot; + [string]::Join(&amp;quot;&amp;lt;/n&amp;gt;&amp;lt;n&amp;gt;&amp;quot;,(Get-Content &amp;quot;$path\Data\surnames.txt&amp;quot;)) + &amp;quot;&amp;lt;/n&amp;gt;&amp;lt;/ns&amp;gt;&amp;quot;).Replace(&amp;quot;&#039;&amp;quot;,&amp;quot;&#039;&#039;&amp;quot;)&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (Get-Content &amp;quot;$path\Data\BulkImportNames.AzureFriendly.sql&amp;quot;) `&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | % {$_ -replace &amp;quot;{{GIRLSNAMES}}&amp;quot;, $girlsnames} `&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | % {$_ -replace &amp;quot;{{BOYSNAMES}}&amp;quot;, $boysnames} `&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | % {$_ -replace &amp;quot;{{LASTNAMES}}&amp;quot;, $lastnames} `&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | Set-Content -path &amp;quot;$CustomersContentPath&amp;quot;&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp; &amp;nbsp; catch{&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Write-Error &amp;quot;Powershell Script error: $_&amp;quot; -EA Stop&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; # ...&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb72553&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This generated data is a necessary part of the application that I initially replaced on each deployment, but now only use on new database deployments. Keeping it random and replaceable prevents the application code from making any assumptions about the data in this table.&lt;/p&gt;

&lt;p&gt;The final step for both scripts is to run the ApplyDatabaseUpdates function on their respective folders and databases.&lt;/p&gt;

&lt;h3&gt;RunLocally.sample.ps1&lt;/h3&gt;
&lt;p&gt;The RunLocally.sample.ps1 script will bring a local development environment all the way up to the latest version without requiring me to type out a long series of arguments and credentials. It is basically just a list of hardcoded variables and then calls to the two Update______Database.ps1 scripts. &lt;/p&gt;

&lt;p&gt;&lt;b&gt;RunLocally.sample.ps1:&lt;/b&gt;&lt;/p&gt;
&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;powershell&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;powershell&quot; id=&quot;cb82246&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;# 1) Copy this file to RunLocally.ps1&lt;br /&gt;# 2) Open RunLocally.ps1 + substitute meaningful values for the variables below (update web.config connection strings also)&lt;br /&gt;# 3) [Cross your fingers and] Run it &lt;br /&gt;&amp;nbsp;&lt;br /&gt;$DbServer = &amp;quot;localhost&amp;quot;&lt;br /&gt;$DbAdminUsername = &amp;quot;admin&amp;quot;&lt;br /&gt;$DbAdminPassword = &amp;quot;password&amp;quot;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;$DbSampleDatabase = &amp;quot;SampleDB&amp;quot;&lt;br /&gt;$DbSampleReadUsername = &amp;quot;readuser&amp;quot;&lt;br /&gt;$DbSampleReadPassword = &amp;quot;password&amp;quot;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;$DbCoreDatabase = &amp;quot;CoreDB&amp;quot;&lt;br /&gt;$DbCoreUsername = &amp;quot;coreuser&amp;quot;&lt;br /&gt;$DbCorePassword = &amp;quot;password&amp;quot;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;.\UpdateSampleDatabase.ps1 -s $DbServer -d $DbSampleDatabase -nu $DbSampleReadUsername -np $DbSampleReadPassword -au $DbAdminUsername -ap $DbAdminPassword -DeleteGeneratedContentAfter $true&lt;br /&gt;&amp;nbsp;&lt;br /&gt;.\UpdateCoreDatabase.ps1 -s $DbServer -d $DbCoreDatabase -nu $DbCoreUsername -np $DbCorePassword -au $DbAdminUsername -ap $DbAdminPassword&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb55160&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The reason it is a sample file is because the real one is going to be different for my desktop and laptop and I knew if they were under source control I would constantly be accidentally committing them and having to change back and forth as I switched systems. To use it, I create a copy of the sample file, rename it to RunLocally.ps1 (which is ignored via the .gitignore for the project) and fill in the real values.&lt;/p&gt;

&lt;h2&gt;Future Plans&lt;/h2&gt;
&lt;p&gt;I&#039;m not a fan of the libraries that try to abstract away the SQL in SQL deployments. I know SQL and don&#039;t need to spend the time learning a library abstraction that, at best, can offer me no better control and ease of use then raw SQL. Many developers feel less than confident in their SQL skills and an abstracted library seems to reduce the need to learn SQL, but in reality the less you know about SQL the harder it will be to determine if the abstraction is doing what you think it is doing, and doing it in a safe and performant manner (and frequently the answer is &quot;it&#039;s not&quot;).&lt;/p&gt;

&lt;p&gt;This set of scripts evolved as a I built the project. In the future I&#039;ll probably switch over to something like DbDeploy, as I mentioned earlier. Having the scripts in file system folders makes it easy to glance over the list to see what has changed, makes them easily accessible in my git repositories, can be copied and pasted (or opened and saved) directly from SSMS, and requires no extra tooling.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;The scripts above are part of the deployment process for a personal project I have been working on called  &lt;a href=&quot;http://SQLisHard.com&quot;&gt;SQLisHard.com&lt;/a&gt;. Launching in the next few weeks (quietly), the site is designed to help people interactively learn or improve their SQL skills and help build the knowledge and confidence that comes from writing and solving real SQL problems.&lt;/i&gt;&lt;/p&gt;&lt;div class=&quot;item_footer&quot;&gt;&lt;p&gt;&lt;small&gt;&lt;a href=&quot;http://blogs.lessthandot.com/index.php/DataMgmt/DBProgramming/deploying-database-changes-with-powershell&quot;&gt;Original post&lt;/a&gt; blogged on &lt;a href=&quot;http://lessthandot.com/&quot;&gt;LessThanDot&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;/div&gt;</description>
			<content:encoded><![CDATA[<p>Recently, while working on a personal project, I found myself needing a lightweight way to deploy database changes to multiple environments. In the past I have used a wide range of methods, ranging from applying the changes manually to applying changes via a diff tool (SQL Compare), to automatically applying manually created change scripts, to automatically applying diff scripts that were automatically generated, to working directly in production..er, pretend you didn't see that one. </p>

<h2>Why not _________ tool?</h2>

<p>There are a lot of tools out there to handle database deployments, but this is a small project that I am building incrementally as a minimum viable product. Rather than tie up a bunch of time researching and experimenting with database deployment tools early on, I decided to do something simple that would work for the time being and free me up to work on the actual product. </p>

<p>What I want from the deployment is to:</p>

<ol>
<li>Spend as little time on this as possible</li>
<li>Work against SQL Azure and a local 2008 R2 Server</li>
<li>Call it from TeamCity for a local server or a remote one</li>
<li>Produce readable output for TeamCity logs</li>
<li>Create the databases and users from the ground up</li>
<li>Include randomly generated data</li>
<li>Manage scripts for 2 independent databases in the same build</li>
<li>Allow real SQL (I'm not scared of SQL and I don't want to learn a code abstraction just to deploy changes)</li>
<li>Not worry about rollbacks. I am deploying small changes and if something breaks I'll be charging forward</li>
<li>Not expose credentials, as the code will be visible to the public</li>
<li>Be replaceable. I might replace it with a tool one day, so keep the deployment logic separate from the application</li>
</ol>

<p>Looking back at this list and what I eventually created, I probably could have used something like <a href="https://github.com/brunomlopes/dbdeploy.net" "dbdploy on github">DBDeploy</a>. The scripts I created ended up taking a very similar approach.</p>

<h2>The Deployment Scripts</h2>

<p>My deployment consists of 4 PowerShell scripts:</p>

<ul>
<li><strong>ApplyDatabaseUpdates.ps1</strong> - Responsible for generically applying changes from a folder to a specified database</li>
<li><strong>UpdateCoreDatabase.ps1</strong> - Responsible for the application's Core Database, calls ApplyDatabaseUpdates</li>
<li><strong>UpdateSampleDatabase.ps1</strong> - Response for the application's Sample Database, calls ApplyDatabaseUpdates</li>
<li><strong>RunLocally.ps1</strong> - Executes the two Update scripts against the local database on my development machine(s)</li>
</ul>

<p>This project has been spread out over 6 months, intermixed with life, other projects, blog posts, etc. Along the way I also upgraded my local development machine to SQL Server 2012 but my main test database server is on 2008 still and my release environment is Azure Database/SQL Azure/(whatever the name is this week).</p>

<h3>ApplyDatabaseUpdates.ps1</h3>
<p>The purpose of the ApplyDatabaseUpdates script is to apply all of the scripts in a specified folder to the specified server. To do this it creates a tracking table on the target database, then iterates through the contents of the folder, building a script containing any files that were not previously logged in the tracking table.</p>

<div style="text-align:center; color: #666666;">
   <img src="http://tiernok.com/LTDBlog/DatabaseDeployment/SQLScripts.png" alt="Core DB Scripts folder" /><br />
   Core Database Scripts Folder
</div>

<p>The deployment script wraps the contents of each script file in an EXECUTE statement, followed by an INSERT to add it to the tracking table for the database.</p>

<p><b><a href="https://github.com/tarwn/SQLisHard/blob/master/Database/ApplyDatabaseUpdates.ps1" title="View on github">ApplyDatabaseUpdates.ps1</a></b></p>
<div class="codebox"><div class="codeheader"><span>powershell</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb83093'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb83093','cb20041'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="powershell" id="cb83093" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1">function ApplyDatabaseUpdates</li><li style="" class="li2">{</li><li style="" class="li1">&nbsp; &nbsp; param (</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; [parameter(Mandatory=$true)]</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; [string]</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; $UpdatesFolder,</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; [parameter(Mandatory=$true)]</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; [string]</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; $Server,</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; [parameter(Mandatory=$true)]</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; [string]</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; $Database,</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; [parameter(Mandatory=$true)]</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; [string]</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; $AdminUserName,</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; [parameter(Mandatory=$true)]</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; [string]</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; $AdminPassword</li><li style="" class="li1">&nbsp; &nbsp; )</li><li style="" class="li2">&nbsp;</li><li style="" class="li1">&nbsp; &nbsp; $path = (Get-Location).Path</li><li style="" class="li2">&nbsp;</li><li style="" class="li1">&nbsp; &nbsp; # For SQL 2008 - load the modules</li><li style="" class="li2">&nbsp; &nbsp; try{ &nbsp; &nbsp;</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; if ( (Get-PSSnapin -Name SqlServerCmdletSnapin100 -ErrorAction SilentlyContinue) -eq $null -and (Get-PSSnapin -Registered -Name SqlServerCmdletSnapin100 -ErrorAction SilentlyContinue) -ne $null){</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Add-PSSnapin SqlServerCmdletSnapin100 -ErrorAction SilentlyContinue</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Add-PSSnapin SqlServerProviderSnapin100 -ErrorAction SilentlyContinue</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; }</li><li style="" class="li1">&nbsp; &nbsp; }</li><li style="" class="li2">&nbsp; &nbsp; catch{</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; Write-Error &quot;Powershell Script error: $_&quot; -EA Stop</li><li style="" class="li2">&nbsp; &nbsp; }</li><li style="" class="li1">&nbsp;</li><li style="" class="li2">&nbsp; &nbsp; #updates tracking</li><li style="" class="li1">&nbsp; &nbsp; try{</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; Write-Host &quot;Creating Update Tracking Table If Not Exists&quot;</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; Invoke-Sqlcmd -Query &quot;IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'UpdateTracking') CREATE TABLE UpdateTracking (UpdateTrackingKey int IDENTITY(1,1) PRIMARY KEY, Name varchar(255) NOT NULL, Applied DateTime NOT NULL);&quot; -ServerInstance &quot;$Server&quot; -Username &quot;$AdminUserName&quot; -Password &quot;$AdminPassword&quot; -Database &quot;$Database&quot; -ErrorAction Stop</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; Write-Host &quot;Done&quot;</li><li style="" class="li1">&nbsp; &nbsp; }</li><li style="" class="li2">&nbsp; &nbsp; catch{</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; Write-Error &quot;Powershell Script error: $_&quot; -EA Stop</li><li style="" class="li2">&nbsp; &nbsp; }</li><li style="" class="li1">&nbsp;</li><li style="" class="li2">&nbsp; &nbsp; #database updates</li><li style="" class="li1">&nbsp; &nbsp; $outputPath = &quot;$path\UpdatesBatch.sql&quot;</li><li style="" class="li2">&nbsp; &nbsp; $stream = [System.IO.StreamWriter] &quot;$outputPath&quot;</li><li style="" class="li1">&nbsp; &nbsp; $fileUpdates = Get-ChildItem &quot;$UpdatesFolder&quot;</li><li style="" class="li2">&nbsp; &nbsp; $datestamp = $(get-date -f &quot;yyyy-MM-dd HH:mm&quot;)</li><li style="" class="li1">&nbsp;</li><li style="" class="li2">&nbsp; &nbsp; $stream.WriteLine(&quot;/* SQL Core Updates - Updated $datestamp */&quot;)</li><li style="" class="li1">&nbsp; &nbsp; $stream.WriteLine(&quot;BEGIN TRANSACTION&quot;)</li><li style="" class="li2">&nbsp;</li><li style="" class="li1">&nbsp; &nbsp; foreach($file in $fileUpdates)</li><li style="" class="li2">&nbsp; &nbsp; {</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; $name = ($file.Name)</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; $namewe = ([System.IO.Path]::GetFileNameWithoutExtension($name))</li><li style="" class="li1">&nbsp;</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; $stream.WriteLine(&quot;&quot;)</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; $stream.WriteLine(&quot;/* File: $name */&quot;)</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; $stream.WriteLine(&quot;IF NOT EXISTS (SELECT 1 FROM UpdateTracking WHERE Name = '$namewe')&quot;)</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; $stream.WriteLine(&quot;BEGIN&quot;)</li><li style="" class="li2">&nbsp;</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; $stream.WriteLine(&quot;`tPrint 'Applying Update: $namewe'&quot;)</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; $stream.WriteLine(&quot;`tEXEC('&quot;)</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; (Get-Content &quot;$UpdatesFolder\$name&quot;) | % {$_ -replace &quot;'&quot;, &quot;''&quot;} | % {$stream.WriteLine(&quot;`t`t$_&quot;)}</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; $stream.WriteLine(&quot;`t');&quot;)</li><li style="" class="li1">&nbsp;</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; $stream.WriteLine(&quot;`tINSERT INTO UpdateTracking(Name, Applied) SELECT '$namewe', GETUTCDATE();&quot;)</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; $stream.WriteLine(&quot;END&quot;)</li><li style="" class="li2">&nbsp; &nbsp; }</li><li style="" class="li1">&nbsp;</li><li style="" class="li2">&nbsp; &nbsp; $stream.WriteLine(&quot;COMMIT TRANSACTION&quot;)</li><li style="" class="li1">&nbsp; &nbsp; $stream.Close()</li><li style="" class="li2">&nbsp; &nbsp; Write-Host &quot;Update Script Created.&quot;</li><li style="" class="li1">&nbsp;</li><li style="" class="li2">&nbsp; &nbsp; Write-Host &quot;Running updates...&quot;</li><li style="" class="li1">&nbsp;</li><li style="" class="li2">&nbsp; &nbsp; Invoke-SqlCmd -InputFile &quot;$outputPath&quot; -ServerInstance &quot;$Server&quot; -Username &quot;$AdminUserName&quot; -Password &quot;$AdminPassword&quot; -Database &quot;$Database&quot; -Verbose -ErrorAction Stop</li><li style="" class="li1">&nbsp;</li><li style="" class="li2">&nbsp; &nbsp; Remove-Item &quot;$outputPath&quot;</li><li style="" class="li1">&nbsp;</li><li style="" class="li2">&nbsp; &nbsp; Write-Host &quot;Updates completed.&quot;</li><li style="" class="li1">}</li></ol></div><div id="cb20041" style="display: none; color: red;"></div></div></div>

<p><i style="display: block; padding: 1em; margin: 1em; background-color: #eeeeee">Note: this has only been run in the context of my personal project. That means don't copy, paste, and run it immediately against your production environment. Running stuff blindly from the internet is known as both a bad idea and a career limiting maneuver.</i></p>

<h3>Update____Database.ps1</h3>

<p>My application has two databases which it will access via different accounts. I want the ability to rebuild these databases from scratch as well as manage their credentials from an external system (in this case, TeamCity). If the worst should happen and these databases are compromised or overwritten in some fashion, I want to be able to recreate them with new credentials, account names, the works. </p>

<p>To make life more difficult, many of these commands have to be executed individually in order to work with Azure Databases.</p>

<p>Both scripts detect if their specified database exists and, if not, create them. The UpdateSampleDatabase is capable of recreating the database in Azure, provided some extra options are passed in to it (the Core Database script is missing this bit, unfortunately):</p>

<p><b>Excerpt from <a href="https://github.com/tarwn/SQLisHard/blob/master/Database/UpdateSampleDatabase.ps1" title="View on github">UpdateSampleDatabase.ps1</a>:</b></p>
<div class="codebox"><div class="codeheader"><span>powershell</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb73140'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb73140','cb41728'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="powershell" id="cb73140" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1"># ...</li><li style="" class="li2">&nbsp;</li><li style="" class="li1">&nbsp; &nbsp; #database</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; Write-Host &quot;Checking database exists...&quot;;</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; $result = Invoke-Sqlcmd -Query &quot;SELECT [name] FROM [sys].[databases] WHERE [name] = N'$database'&quot; -ServerInstance &quot;$Server&quot; -Username &quot;$AdminUserName&quot; -Password &quot;$AdminPassword&quot; -Database &quot;master&quot; -ErrorAction Stop</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; if($result.name){</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Write-Host &quot;Database already exists&quot;;</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; }</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; else{</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Write-Host &quot;Creating Database: $database&quot;</li><li style="" class="li1">&nbsp;</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Invoke-Sqlcmd -Query &quot;CREATE DATABASE $database&quot; -ServerInstance &quot;$Server&quot; -Username &quot;$AdminUserName&quot; -Password &quot;$AdminPassword&quot; -Database &quot;master&quot; -ErrorAction Stop</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Invoke-Sqlcmd -Query &quot;ALTER DATABASE $database SET RECOVERY SIMPLE&quot; -ServerInstance &quot;$Server&quot; -Username &quot;$AdminUserName&quot; -Password &quot;$AdminPassword&quot; -Database &quot;master&quot; -ErrorAction Stop</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Write-Host &quot;Created.&quot;</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; }</li><li style="" class="li2">&nbsp;</li><li style="" class="li1">&nbsp; &nbsp; # ...</li></ol></div><div id="cb41728" style="display: none; color: red;"></div></div></div>

<p>They also generate the users specified by the build server (which will also be dynamically added into the relevant web.config files for the website):</p>

<p><b>Excerpt from <a href="https://github.com/tarwn/SQLisHard/blob/master/Database/UpdateCoreDatabase.ps1" title="View on github">UpdateCoreDatabase.ps1</a>:</b></p>
<div class="codebox"><div class="codeheader"><span>powershell</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb33937'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb33937','cb67502'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="powershell" id="cb33937" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1"># ...</li><li style="" class="li2">&nbsp;</li><li style="" class="li1">&nbsp; &nbsp; #user</li><li style="" class="li2">&nbsp; &nbsp; try{</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; Write-Host &quot;Creating User: $NewUserName&quot;</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; $result = Invoke-Sqlcmd -Query &quot;SELECT [name] FROM sys.sql_logins WHERE name = '$NewUserName'&quot; -ServerInstance &quot;$Server&quot; -Username &quot;$AdminUserName&quot; -Password &quot;$AdminPassword&quot; -Database &quot;master&quot; -ErrorAction Stop</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; if($result.name){</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Write-Host &quot;Login already exists&quot;</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; }</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; else{</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Write-Host &quot;Creating login...&quot;</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Invoke-Sqlcmd -Query &quot;CREATE LOGIN $NewUserName WITH PASSWORD = '$NewPassword'&quot; -ServerInstance &quot;$Server&quot; -Username &quot;$AdminUserName&quot; -Password &quot;$AdminPassword&quot; -Database &quot;master&quot; -ErrorAction Stop</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Write-Host &quot;Login Created.&quot;</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; }</li><li style="" class="li1">&nbsp;</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; $result = Invoke-Sqlcmd -Query &quot;SELECT [name] FROM sys.sysusers WHERE name = '$NewUserName'&quot; -ServerInstance &quot;$Server&quot; -Username &quot;$AdminUserName&quot; -Password &quot;$AdminPassword&quot; -Database &quot;$Database&quot; -ErrorAction Stop</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; if($result.name){</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Write-Host &quot;User already exists&quot;</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; }</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; else{</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Write-Host &quot;Creating user...&quot;</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Invoke-Sqlcmd -Query &quot;CREATE USER $NewUserName FOR LOGIN $NewUserName WITH DEFAULT_SCHEMA = dbo&quot; -ServerInstance &quot;$Server&quot; -Username &quot;$AdminUserName&quot; -Password &quot;$AdminPassword&quot; -Database &quot;$Database&quot; -ErrorAction Stop</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Invoke-Sqlcmd -Query &quot;EXEC sp_addrolemember 'db_datareader','$NewUserName'; EXEC sp_addrolemember 'db_datawriter','$NewUserName'&quot; -ServerInstance &quot;$Server&quot; -Username &quot;$AdminUserName&quot; -Password &quot;$AdminPassword&quot; -Database &quot;$Database&quot; -ErrorAction Stop</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Write-Host &quot;User Created.&quot;</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; }</li><li style="" class="li2">&nbsp; &nbsp; }</li><li style="" class="li1">&nbsp; &nbsp; catch{</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; Write-Error &quot;Powershell Script error: $_&quot; -EA Stop</li><li style="" class="li1">&nbsp; &nbsp; }</li><li style="" class="li2">&nbsp;</li><li style="" class="li1">&nbsp; &nbsp; # ...</li></ol></div><div id="cb67502" style="display: none; color: red;"></div></div></div>

<p>Once the database and users are created, the SampleDatabase script produces a replacement for one of it's script files that will contain some randomized data. The original file is a placeholder and produces an error if it hasn't been replaced.</p>

<p><b>Excerpt from <a href="https://github.com/tarwn/SQLisHard/blob/master/Database/UpdateSampleDatabase.ps1" title="View on github">UpdateSampleDatabase.ps1</a>:</b></p>
<div class="codebox"><div class="codeheader"><span>powershell</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb2286'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb2286','cb30596'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="powershell" id="cb2286" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1"># ...</li><li style="" class="li2">&nbsp;</li><li style="" class="li1"># ---------------------------------- Content Generation ---------------------------------------------</li><li style="" class="li2"># Scripts to generate content dynamically and update the appropriate update script</li><li style="" class="li1">&nbsp;</li><li style="" class="li2">&nbsp; &nbsp; #generate customers table content</li><li style="" class="li1">&nbsp; &nbsp; $CustomersContentPath = &quot;$UpdatesFolder\0002_CustomersData.sql&quot;</li><li style="" class="li2">&nbsp; &nbsp; try{</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; Write-Host &quot;Generating content script for dbo.Customers&quot;</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; $girlsnames = (&quot;&lt;ns&gt;&lt;n&gt;&quot; + [string]::Join(&quot;&lt;/n&gt;&lt;n&gt;&quot;,(Get-Content &quot;$path\Data\girlsforenames.txt&quot;)) + &quot;&lt;/n&gt;&lt;/ns&gt;&quot;).Replace(&quot;'&quot;,&quot;''&quot;)</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; $boysnames = &nbsp;(&quot;&lt;ns&gt;&lt;n&gt;&quot; + [string]::Join(&quot;&lt;/n&gt;&lt;n&gt;&quot;,(Get-Content &quot;$path\Data\boysforenames.txt&quot;)) + &quot;&lt;/n&gt;&lt;/ns&gt;&quot;).Replace(&quot;'&quot;,&quot;''&quot;)</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; $lastnames = &nbsp;(&quot;&lt;ns&gt;&lt;n&gt;&quot; + [string]::Join(&quot;&lt;/n&gt;&lt;n&gt;&quot;,(Get-Content &quot;$path\Data\surnames.txt&quot;)) + &quot;&lt;/n&gt;&lt;/ns&gt;&quot;).Replace(&quot;'&quot;,&quot;''&quot;)</li><li style="" class="li1">&nbsp; &nbsp; </li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; (Get-Content &quot;$path\Data\BulkImportNames.AzureFriendly.sql&quot;) `</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | % {$_ -replace &quot;{{GIRLSNAMES}}&quot;, $girlsnames} `</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | % {$_ -replace &quot;{{BOYSNAMES}}&quot;, $boysnames} `</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | % {$_ -replace &quot;{{LASTNAMES}}&quot;, $lastnames} `</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | Set-Content -path &quot;$CustomersContentPath&quot;</li><li style="" class="li1">&nbsp; &nbsp; }</li><li style="" class="li2">&nbsp; &nbsp; catch{</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; Write-Error &quot;Powershell Script error: $_&quot; -EA Stop</li><li style="" class="li2">&nbsp; &nbsp; }</li><li style="" class="li1">&nbsp;</li><li style="" class="li2">&nbsp; &nbsp; # ...</li></ol></div><div id="cb30596" style="display: none; color: red;"></div></div></div>

<p>This generated data is a necessary part of the application that I initially replaced on each deployment, but now only use on new database deployments. Keeping it random and replaceable prevents the application code from making any assumptions about the data in this table.</p>

<p>The final step for both scripts is to run the ApplyDatabaseUpdates function on their respective folders and databases.</p>

<h3>RunLocally.sample.ps1</h3>
<p>The RunLocally.sample.ps1 script will bring a local development environment all the way up to the latest version without requiring me to type out a long series of arguments and credentials. It is basically just a list of hardcoded variables and then calls to the two Update______Database.ps1 scripts. </p>

<p><b>RunLocally.sample.ps1:</b></p>
<div class="codebox"><div class="codeheader"><span>powershell</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb49070'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb49070','cb27948'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="powershell" id="cb49070" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1"># 1) Copy this file to RunLocally.ps1</li><li style="" class="li2"># 2) Open RunLocally.ps1 + substitute meaningful values for the variables below (update web.config connection strings also)</li><li style="" class="li1"># 3) [Cross your fingers and] Run it </li><li style="" class="li2">&nbsp;</li><li style="" class="li1">$DbServer = &quot;localhost&quot;</li><li style="" class="li2">$DbAdminUsername = &quot;admin&quot;</li><li style="" class="li1">$DbAdminPassword = &quot;password&quot;</li><li style="" class="li2">&nbsp;</li><li style="" class="li1">$DbSampleDatabase = &quot;SampleDB&quot;</li><li style="" class="li2">$DbSampleReadUsername = &quot;readuser&quot;</li><li style="" class="li1">$DbSampleReadPassword = &quot;password&quot;</li><li style="" class="li2">&nbsp;</li><li style="" class="li1">$DbCoreDatabase = &quot;CoreDB&quot;</li><li style="" class="li2">$DbCoreUsername = &quot;coreuser&quot;</li><li style="" class="li1">$DbCorePassword = &quot;password&quot;</li><li style="" class="li2">&nbsp;</li><li style="" class="li1">.\UpdateSampleDatabase.ps1 -s $DbServer -d $DbSampleDatabase -nu $DbSampleReadUsername -np $DbSampleReadPassword -au $DbAdminUsername -ap $DbAdminPassword -DeleteGeneratedContentAfter $true</li><li style="" class="li2">&nbsp;</li><li style="" class="li1">.\UpdateCoreDatabase.ps1 -s $DbServer -d $DbCoreDatabase -nu $DbCoreUsername -np $DbCorePassword -au $DbAdminUsername -ap $DbAdminPassword</li></ol></div><div id="cb27948" style="display: none; color: red;"></div></div></div>

<p>The reason it is a sample file is because the real one is going to be different for my desktop and laptop and I knew if they were under source control I would constantly be accidentally committing them and having to change back and forth as I switched systems. To use it, I create a copy of the sample file, rename it to RunLocally.ps1 (which is ignored via the .gitignore for the project) and fill in the real values.</p>

<h2>Future Plans</h2>
<p>I'm not a fan of the libraries that try to abstract away the SQL in SQL deployments. I know SQL and don't need to spend the time learning a library abstraction that, at best, can offer me no better control and ease of use then raw SQL. Many developers feel less than confident in their SQL skills and an abstracted library seems to reduce the need to learn SQL, but in reality the less you know about SQL the harder it will be to determine if the abstraction is doing what you think it is doing, and doing it in a safe and performant manner (and frequently the answer is "it's not").</p>

<p>This set of scripts evolved as a I built the project. In the future I'll probably switch over to something like DbDeploy, as I mentioned earlier. Having the scripts in file system folders makes it easy to glance over the list to see what has changed, makes them easily accessible in my git repositories, can be copied and pasted (or opened and saved) directly from SSMS, and requires no extra tooling.</p>

<p><i>The scripts above are part of the deployment process for a personal project I have been working on called  <a href="http://SQLisHard.com">SQLisHard.com</a>. Launching in the next few weeks (quietly), the site is designed to help people interactively learn or improve their SQL skills and help build the knowledge and confidence that comes from writing and solving real SQL problems.</i></p><div class="item_footer"><p><small><a href="http://blogs.lessthandot.com/index.php/DataMgmt/DBProgramming/deploying-database-changes-with-powershell">Original post</a> blogged on <a href="http://lessthandot.com/">LessThanDot</a>.</small></p></div>]]></content:encoded>
								<comments>http://blogs.lessthandot.com/index.php/DataMgmt/DBProgramming/deploying-database-changes-with-powershell#comments</comments>
			<wfw:commentRss>http://blogs.lessthandot.com/index.php/DataMgmt/?tempskin=_rss2&#38;disp=comments&#38;p=2190</wfw:commentRss>
		</item>
				<item>
			<title>Intellisense for custom XML in Visual Studio</title>
			<link>http://blogs.lessthandot.com/index.php/DesktopDev/MSTech/vs2012/intellisense-for-custom-xml-in</link>
			<pubDate>Mon, 06 May 2013 13:44:00 +0000</pubDate>			<dc:creator>Eli Weinstock-Herman (tarwn)</dc:creator>
			<category domain="main">Vistual Studio 2012</category>			<guid isPermaLink="false">2191@http://blogs.lessthandot.com/</guid>
						<description>&lt;p&gt;This is one of those things that I only need once every several months and always forget how to do. Working with custom XML in Visual Studio is a whole lot easier with intellisense. Schema errors are highlighted, enumerated values are displayed, and the amount of typing goes from full tag names to just a few characters followed by tab to complete.&lt;/p&gt;

&lt;p&gt;There are a few ways to do this, but if you have a schema (XSD) for the file, then here are the steps to make the magic happen.&lt;/p&gt;

&lt;h2&gt;Sample Files&lt;/h2&gt;
&lt;p&gt;So let&#039;s assume for the moment that you have the following sample files:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;AwesomeFile.xml&lt;/b&gt;&lt;/p&gt;
&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;xml&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;xml&quot; id=&quot;cb40035&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;?xml&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;version&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;1.0&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;encoding&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt; &lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;AwesomeList&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;AwesomeItem&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;AwesomenessFactor&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;11&amp;quot;&lt;/span&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;AwesomeType&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;Is Awesome&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/AwesomeType&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/AwesomeItem&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/AwesomeList&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb13916&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;b&gt;Awesome.xsd&lt;/b&gt;&lt;/p&gt;
&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;xml&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;xml&quot; id=&quot;cb76360&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;?xml&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;version&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;1.0&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;encoding&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;xs:schema&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;id&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;MyAwesomeSchema&amp;quot;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000066;&quot;&gt;xmlns:xs&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;http://www.w3.org/2001/XMLSchema&amp;quot;&lt;/span&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;xs:simpleType&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;name&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;AwesomeLevel&amp;quot;&lt;/span&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;xs:restriction&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;base&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;xs:integer&amp;quot;&lt;/span&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;xs:enumeration&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;value&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/xs:enumeration&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;xs:enumeration&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;value&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;5&amp;quot;&lt;/span&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/xs:enumeration&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;xs:enumeration&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;value&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;10&amp;quot;&lt;/span&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/xs:enumeration&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;xs:enumeration&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;value&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;11&amp;quot;&lt;/span&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/xs:enumeration&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/xs:restriction&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/xs:simpleType&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;xs:complexType&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;name&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;AwesomeElement&amp;quot;&lt;/span&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;xs:sequence&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;xs:element&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;name&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;AwesomeType&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;type&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;xs:string&amp;quot;&lt;/span&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/xs:element&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/xs:sequence&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;xs:attribute&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;name&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;AwesomenessFactor&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;type&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;AwesomeLevel&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;use&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;required&amp;quot;&lt;/span&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/xs:attribute&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/xs:complexType&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;xs:element&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;name&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;AwesomeList&amp;quot;&lt;/span&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;xs:complexType&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;xs:sequence&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;xs:element&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;name&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;AwesomeItem&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;type&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;AwesomeElement&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;minOccurs&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;maxOccurs&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;unbounded&amp;quot;&lt;/span&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/xs:element&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/xs:sequence&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/xs:complexType&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/xs:element&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/xs:schema&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb5224&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Visual Studio gives us handy intellisense suggestions and warnings when we&#039;re writing the schema because we have specified a namespace it knows, but how do we get that usefulness when we&#039;re adding more content to our awesome XML file?&lt;/p&gt;

&lt;h2&gt;More Cowbell&lt;/h2&gt;
&lt;p&gt;Turns out, adding this functionality is pretty easy. Visual Studio is smart enough to use know schemas, so all we have to do is provide the information that makes our schema known and relevant for our XML file. &lt;/p&gt;

&lt;p&gt;For this example I am assuming that the two files are in the same folder. I&#039;ve also made the file complex enough that the additions we make should work for far more complex setups also.&lt;/p&gt;

&lt;p&gt;Here&#039;s the steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Define a target namespace on the schema&lt;/li&gt;
&lt;li&gt;Define the empty namespace of the schema as this namespace&lt;/li&gt;
&lt;li&gt;set attributeFormDefault to unqualified so attributes in our XML file won&#039;t require namespace declarations&lt;/li&gt;
&lt;li&gt;Add the namespace declaration to the XML file&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Updating our files (and adding comments to reflect the list above), we have:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;AwesomeFile.xml&lt;/b&gt;&lt;/p&gt;
&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;xml&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;xml&quot; id=&quot;cb58352&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;?xml&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;version&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;1.0&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;encoding&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt; &lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;AwesomeList&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;xmlns&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;my://awesomeness&amp;quot;&lt;/span&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;&amp;lt;!-- (4) --&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;AwesomeItem&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;AwesomenessFactor&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;11&amp;quot;&lt;/span&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;AwesomeType&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;Is Awesome&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/AwesomeType&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/AwesomeItem&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/AwesomeList&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb96735&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;b&gt;Awesome.xsd&lt;/b&gt;&lt;/p&gt;
&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;xml&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;xml&quot; id=&quot;cb35048&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;?xml&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;version&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;1.0&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;encoding&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;xs:schema&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;id&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;MyAwesomeSchema&amp;quot;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000066;&quot;&gt;xmlns:xs&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;http://www.w3.org/2001/XMLSchema&amp;quot;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000066;&quot;&gt;targetNamespace&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;my://awesomeness&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;&amp;lt;!-- (1) --&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; xmlns=&amp;quot;my://awesomeness&amp;quot; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;&amp;lt;!-- (2) --&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; attributeFormDefault=&amp;quot;unqualified&amp;quot; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;&amp;lt;!-- (3) --&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; elementFormDefault=&amp;quot;qualified&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;xs:simpleType&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;name&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;AwesomeLevel&amp;quot;&lt;/span&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;xs:restriction&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;base&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;xs:integer&amp;quot;&lt;/span&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;xs:enumeration&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;value&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/xs:enumeration&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;xs:enumeration&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;value&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;5&amp;quot;&lt;/span&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/xs:enumeration&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;xs:enumeration&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;value&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;10&amp;quot;&lt;/span&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/xs:enumeration&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;xs:enumeration&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;value&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;11&amp;quot;&lt;/span&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/xs:enumeration&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/xs:restriction&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/xs:simpleType&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;xs:complexType&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;name&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;AwesomeElement&amp;quot;&lt;/span&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;xs:sequence&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;xs:element&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;name&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;AwesomeType&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;type&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;xs:string&amp;quot;&lt;/span&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/xs:element&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/xs:sequence&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;xs:attribute&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;name&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;AwesomenessFactor&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;type&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;AwesomeLevel&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;use&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;required&amp;quot;&lt;/span&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/xs:attribute&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/xs:complexType&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;xs:element&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;name&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;AwesomeList&amp;quot;&lt;/span&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;xs:complexType&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;xs:sequence&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;xs:element&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;name&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;AwesomeItem&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;type&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;AwesomeElement&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;minOccurs&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;maxOccurs&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;unbounded&amp;quot;&lt;/span&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/xs:element&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/xs:sequence&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/xs:complexType&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/xs:element&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/xs:schema&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb94736&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And there we have it.&lt;/p&gt;

&lt;h2&gt;Results&lt;/h2&gt;

&lt;p&gt;Now when we start typing in the XML file we will get intellisense suggestions/completion:&lt;/p&gt;

&lt;div style=&quot;text-align:center; margin: .5em 0;&quot;&gt;
   &lt;img src=&quot;http://tiernok.com/LTDBlog/XmlSchemaIntellisense/Intellisense.png&quot; alt=&quot;Intellisense suggestions&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;We also get warnings when we forget a required attribute:&lt;/p&gt;

&lt;div style=&quot;text-align:center; margin: .5em 0;&quot;&gt;
   &lt;img src=&quot;http://tiernok.com/LTDBlog/XmlSchemaIntellisense/SchemaWarning.png&quot; alt=&quot;Intellisense suggestions&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;And when we use the wrong type:&lt;/p&gt;

&lt;div style=&quot;text-align:center; margin: .5em 0;&quot;&gt;
   &lt;img src=&quot;http://tiernok.com/LTDBlog/XmlSchemaIntellisense/WrongTypeWarning.png&quot; alt=&quot;Intellisense suggestions&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;&lt;i&gt;Hopefully the custom color scheme isn&#039;t confusing, was feeling too lazy to switch it and switch it back&lt;/i&gt;&lt;/p&gt;&lt;div class=&quot;item_footer&quot;&gt;&lt;p&gt;&lt;small&gt;&lt;a href=&quot;http://blogs.lessthandot.com/index.php/DesktopDev/MSTech/vs2012/intellisense-for-custom-xml-in&quot;&gt;Original post&lt;/a&gt; blogged on &lt;a href=&quot;http://lessthandot.com/&quot;&gt;LessThanDot&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;/div&gt;</description>
			<content:encoded><![CDATA[<p>This is one of those things that I only need once every several months and always forget how to do. Working with custom XML in Visual Studio is a whole lot easier with intellisense. Schema errors are highlighted, enumerated values are displayed, and the amount of typing goes from full tag names to just a few characters followed by tab to complete.</p>

<p>There are a few ways to do this, but if you have a schema (XSD) for the file, then here are the steps to make the magic happen.</p>

<h2>Sample Files</h2>
<p>So let's assume for the moment that you have the following sample files:</p>

<p><b>AwesomeFile.xml</b></p>
<div class="codebox"><div class="codeheader"><span>xml</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb46747'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb46747','cb48814'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="xml" id="cb46747" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;utf-8&quot;</span> <span style="font-weight: bold; color: black;">?&gt;</span></span></li><li style="" class="li2"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;AwesomeList<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;AwesomeItem</span> <span style="color: #000066;">AwesomenessFactor</span>=<span style="color: #ff0000;">&quot;11&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span></li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;AwesomeType<span style="font-weight: bold; color: black;">&gt;</span></span></span>Is Awesome<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/AwesomeType<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/AwesomeItem<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li2"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/AwesomeList<span style="font-weight: bold; color: black;">&gt;</span></span></span></li></ol></div><div id="cb48814" style="display: none; color: red;"></div></div></div>

<p><b>Awesome.xsd</b></p>
<div class="codebox"><div class="codeheader"><span>xml</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb47696'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb47696','cb67629'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="xml" id="cb47696" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;utf-8&quot;</span><span style="font-weight: bold; color: black;">?&gt;</span></span></li><li style="" class="li2"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;xs:schema</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;MyAwesomeSchema&quot;</span></li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #000066;">xmlns:xs</span>=<span style="color: #ff0000;">&quot;http://www.w3.org/2001/XMLSchema&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span></li><li style="" class="li2">&nbsp;</li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;xs:simpleType</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;AwesomeLevel&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span></li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;xs:restriction</span> <span style="color: #000066;">base</span>=<span style="color: #ff0000;">&quot;xs:integer&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;xs:enumeration</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;1&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/xs:enumeration<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;xs:enumeration</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;5&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/xs:enumeration<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;xs:enumeration</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;10&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/xs:enumeration<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;xs:enumeration</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;11&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/xs:enumeration<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/xs:restriction<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li2">&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/xs:simpleType<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li1">&nbsp;</li><li style="" class="li2">&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;xs:complexType</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;AwesomeElement&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;xs:sequence<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;xs:element</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;AwesomeType&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;xs:string&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/xs:element<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/xs:sequence<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;xs:attribute</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;AwesomenessFactor&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;AwesomeLevel&quot;</span> <span style="color: #000066;">use</span>=<span style="color: #ff0000;">&quot;required&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/xs:attribute<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/xs:complexType<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li2">&nbsp;</li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;xs:element</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;AwesomeList&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span></li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;xs:complexType<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;xs:sequence<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;xs:element</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;AwesomeItem&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;AwesomeElement&quot;</span> <span style="color: #000066;">minOccurs</span>=<span style="color: #ff0000;">&quot;0&quot;</span> <span style="color: #000066;">maxOccurs</span>=<span style="color: #ff0000;">&quot;unbounded&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/xs:element<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/xs:sequence<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/xs:complexType<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li2">&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/xs:element<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li1">&nbsp; &nbsp; </li><li style="" class="li2"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/xs:schema<span style="font-weight: bold; color: black;">&gt;</span></span></span></li></ol></div><div id="cb67629" style="display: none; color: red;"></div></div></div>

<p>Visual Studio gives us handy intellisense suggestions and warnings when we're writing the schema because we have specified a namespace it knows, but how do we get that usefulness when we're adding more content to our awesome XML file?</p>

<h2>More Cowbell</h2>
<p>Turns out, adding this functionality is pretty easy. Visual Studio is smart enough to use know schemas, so all we have to do is provide the information that makes our schema known and relevant for our XML file. </p>

<p>For this example I am assuming that the two files are in the same folder. I've also made the file complex enough that the additions we make should work for far more complex setups also.</p>

<p>Here's the steps:</p>
<ol>
<li>Define a target namespace on the schema</li>
<li>Define the empty namespace of the schema as this namespace</li>
<li>set attributeFormDefault to unqualified so attributes in our XML file won't require namespace declarations</li>
<li>Add the namespace declaration to the XML file</li>
</ol>

<p>Updating our files (and adding comments to reflect the list above), we have:</p>

<p><b>AwesomeFile.xml</b></p>
<div class="codebox"><div class="codeheader"><span>xml</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb18577'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb18577','cb27458'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="xml" id="cb18577" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;utf-8&quot;</span> <span style="font-weight: bold; color: black;">?&gt;</span></span></li><li style="" class="li2"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;AwesomeList</span> <span style="color: #000066;">xmlns</span>=<span style="color: #ff0000;">&quot;my://awesomeness&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span> <span style="color: #009900;"><span style="color: #808080; font-style: italic;">&lt;!-- (4) --&gt;</span></span></li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;AwesomeItem</span> <span style="color: #000066;">AwesomenessFactor</span>=<span style="color: #ff0000;">&quot;11&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span></li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;AwesomeType<span style="font-weight: bold; color: black;">&gt;</span></span></span>Is Awesome<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/AwesomeType<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/AwesomeItem<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li2"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/AwesomeList<span style="font-weight: bold; color: black;">&gt;</span></span></span></li></ol></div><div id="cb27458" style="display: none; color: red;"></div></div></div>

<p><b>Awesome.xsd</b></p>
<div class="codebox"><div class="codeheader"><span>xml</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb3910'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb3910','cb17786'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="xml" id="cb3910" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;utf-8&quot;</span><span style="font-weight: bold; color: black;">?&gt;</span></span></li><li style="" class="li2"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;xs:schema</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;MyAwesomeSchema&quot;</span></li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #000066;">xmlns:xs</span>=<span style="color: #ff0000;">&quot;http://www.w3.org/2001/XMLSchema&quot;</span></li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066;">targetNamespace</span>=<span style="color: #ff0000;">&quot;my://awesomeness&quot;</span> <span style="color: #808080; font-style: italic;">&lt;!-- (1) --&gt;</span></span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; xmlns=&quot;my://awesomeness&quot; <span style="color: #009900;"><span style="color: #808080; font-style: italic;">&lt;!-- (2) --&gt;</span></span></li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; attributeFormDefault=&quot;unqualified&quot; <span style="color: #009900;"><span style="color: #808080; font-style: italic;">&lt;!-- (3) --&gt;</span></span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; elementFormDefault=&quot;qualified&quot;&gt;</li><li style="" class="li2">&nbsp;</li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;xs:simpleType</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;AwesomeLevel&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span></li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;xs:restriction</span> <span style="color: #000066;">base</span>=<span style="color: #ff0000;">&quot;xs:integer&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;xs:enumeration</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;1&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/xs:enumeration<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;xs:enumeration</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;5&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/xs:enumeration<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;xs:enumeration</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;10&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/xs:enumeration<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;xs:enumeration</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;11&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/xs:enumeration<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/xs:restriction<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li2">&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/xs:simpleType<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li1">&nbsp;</li><li style="" class="li2">&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;xs:complexType</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;AwesomeElement&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;xs:sequence<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;xs:element</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;AwesomeType&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;xs:string&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/xs:element<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/xs:sequence<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;xs:attribute</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;AwesomenessFactor&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;AwesomeLevel&quot;</span> <span style="color: #000066;">use</span>=<span style="color: #ff0000;">&quot;required&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/xs:attribute<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/xs:complexType<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li2">&nbsp;</li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;xs:element</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;AwesomeList&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span></li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;xs:complexType<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;xs:sequence<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;xs:element</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;AwesomeItem&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;AwesomeElement&quot;</span> <span style="color: #000066;">minOccurs</span>=<span style="color: #ff0000;">&quot;0&quot;</span> <span style="color: #000066;">maxOccurs</span>=<span style="color: #ff0000;">&quot;unbounded&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/xs:element<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/xs:sequence<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/xs:complexType<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li2">&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/xs:element<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li1">&nbsp;</li><li style="" class="li2"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/xs:schema<span style="font-weight: bold; color: black;">&gt;</span></span></span></li></ol></div><div id="cb17786" style="display: none; color: red;"></div></div></div>

<p>And there we have it.</p>

<h2>Results</h2>

<p>Now when we start typing in the XML file we will get intellisense suggestions/completion:</p>

<div style="text-align:center; margin: .5em 0;">
   <img src="http://tiernok.com/LTDBlog/XmlSchemaIntellisense/Intellisense.png" alt="Intellisense suggestions" />
</div>

<p>We also get warnings when we forget a required attribute:</p>

<div style="text-align:center; margin: .5em 0;">
   <img src="http://tiernok.com/LTDBlog/XmlSchemaIntellisense/SchemaWarning.png" alt="Intellisense suggestions" />
</div>

<p>And when we use the wrong type:</p>

<div style="text-align:center; margin: .5em 0;">
   <img src="http://tiernok.com/LTDBlog/XmlSchemaIntellisense/WrongTypeWarning.png" alt="Intellisense suggestions" />
</div>

<p><i>Hopefully the custom color scheme isn't confusing, was feeling too lazy to switch it and switch it back</i></p><div class="item_footer"><p><small><a href="http://blogs.lessthandot.com/index.php/DesktopDev/MSTech/vs2012/intellisense-for-custom-xml-in">Original post</a> blogged on <a href="http://lessthandot.com/">LessThanDot</a>.</small></p></div>]]></content:encoded>
								<comments>http://blogs.lessthandot.com/index.php/DesktopDev/MSTech/vs2012/intellisense-for-custom-xml-in#comments</comments>
			<wfw:commentRss>http://blogs.lessthandot.com/index.php/DesktopDev/?tempskin=_rss2&#38;disp=comments&#38;p=2191</wfw:commentRss>
		</item>
				<item>
			<title>IT vs The Business</title>
			<link>http://blogs.lessthandot.com/index.php/ITProfessionals/other/it-vs-the-business</link>
			<pubDate>Tue, 26 Mar 2013 07:36:00 +0000</pubDate>			<dc:creator>Eli Weinstock-Herman (tarwn)</dc:creator>
			<category domain="alt">Project Management</category>
<category domain="alt">IT Processes</category>
<category domain="main">Other</category>			<guid isPermaLink="false">2164@http://blogs.lessthandot.com/</guid>
						<description>&lt;p&gt;Monday I caught the &lt;a href=&quot;http://foodfightshow.org/&quot;&gt;Food Fight Show&lt;/a&gt;, discussing &lt;a href=&quot;http://foodfightshow.org/2013/03/the-phoenix-project.html&quot;&gt;The Phoenix Project&lt;/a&gt; and featuring Gene Kim (&lt;a href=&quot;http://www.realgenekim.me/&quot; title=&quot;Gene Kim&#039;s website&quot;&gt;site&lt;/a&gt;|&lt;a href=&quot;https://twitter.com/RealGeneKim&quot; title=&quot;@realgenekim on twitter&quot;&gt;twitter&lt;/a&gt;), Jez Humble (&lt;a href=&quot;http://jezhumble.net/&quot; title=&quot;Jez&#039;s website&quot;&gt;blog&lt;/a&gt;|&lt;a href=&quot;https://twitter.com/jezhumble&quot; title=&quot;@jezhumble on twitter&quot;&gt;twitter&lt;/a&gt;), and Matthew Zeier (&lt;a href=&quot;http://blog.mozilla.org/mrz/&quot; title=&quot;mrz&#039;s Mozilla/Firefox blog&quot;&gt;blog&lt;/a&gt;|&lt;a href=&quot;https://twitter.com/mrz&quot; title=&quot;@mrz on twitter&quot;&gt;twitter&lt;/a&gt;). &lt;/p&gt;

&lt;p&gt;Part of the way through the show, a conversation took place that I couldn&#039;t get out of my head. &lt;/p&gt;

&lt;h2&gt;Here&#039;s the situation:&lt;/h2&gt;

&lt;p&gt;A business person is asking IT to implement a blog using a specific NoSQL database solution and we push back and try to examine why they want it, and oh by the way we have this great business opportunity for you (around 29:30). &lt;/p&gt;

&lt;p&gt;Which reminded me of a related question I heard (I thought in the show, but apparently it must have been earlier in the day):&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Why it is OK for the IT person to talk business to the business person, when it&#039;s not OK for the business person to talk IT to the IT person.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;What bothered me the whole drive home is the built in assumption that the business and IT are separate entities. The panel went deep into value streams and hypotheses-driven development from here, but I think there was something wrong with the root of this story, where we accepted the separation of IT person and business. This may seem overly detail-oriented, but I think far too many IT people see themselves exactly this way. &lt;/p&gt;

&lt;h2&gt;And it&#039;s wrong.&lt;/h2&gt;

&lt;p&gt;Here&#039;s the flaw in this story (and every other place we talk about IT vs the business):&lt;/p&gt;

&lt;p&gt;Joe Random Executive doesn&#039;t know all the intricacies of accounting, purchasing, warehousing, marketing, sales, law, human resources, or any of a dozen other areas. They will probably know a couple in detail, but they are no more an expert in the rest then they are in IT (and of course we assume they didn&#039;t have an IT Background). These are all skills or roles that get casually lumped under the &quot;business&quot; umbrella. Because somehow all areas but IT are business, while only IT is non-business.&lt;/p&gt;

&lt;p&gt;Is this ego or laziness? Some of both. Only in the IT department do we somehow think our role gives us a magic ticket to be totally ignorant about the company we work for. &lt;/p&gt;

&lt;h2&gt;This is absurd.&lt;/h2&gt;

&lt;p&gt;It makes no more sense then suggesting that accounting is far too intricate to spend time learning how the business around them works. Or that the ever-changing logistics and supply market supersedes understanding the products we are purchasing or shipping. Or that knowing what markets we sell to has any importance to the lawyers. Or that our business growth strategies should take any time away from HR activities around screening and hiring,.&lt;/p&gt;

&lt;p&gt;Maybe the whole company is siloed, but seeing it as IT vs The Business is silly (see Gene Kim&#039;s point 25 minutes in).&lt;/p&gt;

&lt;div style=&quot;text-align: center; font-style: italic&quot;&gt;As an aside, spellcheck prefers to call that soiled. I find myself in agreement.&lt;/div&gt;

&lt;p&gt;But wait, these are IT ops people talking, surely this is different, right? &lt;/p&gt;

&lt;p&gt;I&#039;ll give you a hint, Gene Kim talks early on about how The Phoenix Project was influenced by &lt;a href=&quot;http://en.wikipedia.org/wiki/The_Goal_%28novel%29&quot;&gt;The Goal (Eliyahu Goldratt)&lt;/a&gt;, whose main character is a plant operations manager. So no, IT Ops, IT QA, IT Technician, you are no more off the hook then the enormous variety of lawyers a business may need to work with over the course of it&#039;s life.&lt;/p&gt;

&lt;p&gt;There are two types of workers, and they aren&#039;t IT and non-IT, they are engaged and not engaged. &lt;/p&gt;

&lt;h2&gt;Are you doing your job?&lt;/h2&gt;

&lt;p&gt;Are you doing the job, or just playing with technology?&lt;/p&gt;

&lt;p&gt;An engaged worker knows how the company works, at some level. They can discuss the strategies the business is executing, what their company does, and who their customers are. They may not be able to discuss these things with equal facility as the executives or experts in specific departments, but they can have an intelligent conversation about their business. &lt;/p&gt;

&lt;p&gt;The not-engaged worker is just there to do a job and go home. They are the protectors of turf, the ones that deny every request they can get away with, or the ones that simply don&#039;t care. &lt;/p&gt;

&lt;div style=&quot;text-align: center; font-weight: bold;&quot;&gt;Ignorance of how your company works is a sign of incompetence, not something to be proud of. &lt;/div&gt;

&lt;p&gt;So the reason an IT person (even an IT Ops person) can speak to a non-IT worker about the business is because &quot;the business&quot; is the common language they share. IT, accounting, purchasing, human resources, whoever ... when we need to discuss why something is important, we discuss it&#039;s impact on the the business, the strategies or targets it effects, etc. In fact, being in IT typically requires a &lt;u&gt;higher&lt;/u&gt; level of day-to-day, cross-functional contact then any of the prior examples. More, not less.&lt;/p&gt;

&lt;p&gt;Engaging the business has come and gone as part of many buzzy things, and in DevOps it&#039;s rising again. Regardless of it&#039;s current popularity, if you work for a company, being an IT person doesn&#039;t magically separate you from the goals everyone else is working towards. Engage, learn the business, help them succeed, you&#039;ll find that you&#039;re company is doing some really interesting things and works with some really interesting people. If it&#039;s not, find one that resonates with you and learn what they&#039;re doing. Either way, you&#039;re part of the business, an you chose whether you&#039;re competent or not.&lt;/p&gt;&lt;div class=&quot;item_footer&quot;&gt;&lt;p&gt;&lt;small&gt;&lt;a href=&quot;http://blogs.lessthandot.com/index.php/ITProfessionals/other/it-vs-the-business&quot;&gt;Original post&lt;/a&gt; blogged on &lt;a href=&quot;http://lessthandot.com/&quot;&gt;LessThanDot&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;/div&gt;</description>
			<content:encoded><![CDATA[<p>Monday I caught the <a href="http://foodfightshow.org/">Food Fight Show</a>, discussing <a href="http://foodfightshow.org/2013/03/the-phoenix-project.html">The Phoenix Project</a> and featuring Gene Kim (<a href="http://www.realgenekim.me/" title="Gene Kim's website">site</a>|<a href="https://twitter.com/RealGeneKim" title="@realgenekim on twitter">twitter</a>), Jez Humble (<a href="http://jezhumble.net/" title="Jez's website">blog</a>|<a href="https://twitter.com/jezhumble" title="@jezhumble on twitter">twitter</a>), and Matthew Zeier (<a href="http://blog.mozilla.org/mrz/" title="mrz's Mozilla/Firefox blog">blog</a>|<a href="https://twitter.com/mrz" title="@mrz on twitter">twitter</a>). </p>

<p>Part of the way through the show, a conversation took place that I couldn't get out of my head. </p>

<h2>Here's the situation:</h2>

<p>A business person is asking IT to implement a blog using a specific NoSQL database solution and we push back and try to examine why they want it, and oh by the way we have this great business opportunity for you (around 29:30). </p>

<p>Which reminded me of a related question I heard (I thought in the show, but apparently it must have been earlier in the day):</p>

<blockquote><p>Why it is OK for the IT person to talk business to the business person, when it's not OK for the business person to talk IT to the IT person.</p></blockquote>

<p>What bothered me the whole drive home is the built in assumption that the business and IT are separate entities. The panel went deep into value streams and hypotheses-driven development from here, but I think there was something wrong with the root of this story, where we accepted the separation of IT person and business. This may seem overly detail-oriented, but I think far too many IT people see themselves exactly this way. </p>

<h2>And it's wrong.</h2>

<p>Here's the flaw in this story (and every other place we talk about IT vs the business):</p>

<p>Joe Random Executive doesn't know all the intricacies of accounting, purchasing, warehousing, marketing, sales, law, human resources, or any of a dozen other areas. They will probably know a couple in detail, but they are no more an expert in the rest then they are in IT (and of course we assume they didn't have an IT Background). These are all skills or roles that get casually lumped under the "business" umbrella. Because somehow all areas but IT are business, while only IT is non-business.</p>

<p>Is this ego or laziness? Some of both. Only in the IT department do we somehow think our role gives us a magic ticket to be totally ignorant about the company we work for. </p>

<h2>This is absurd.</h2>

<p>It makes no more sense then suggesting that accounting is far too intricate to spend time learning how the business around them works. Or that the ever-changing logistics and supply market supersedes understanding the products we are purchasing or shipping. Or that knowing what markets we sell to has any importance to the lawyers. Or that our business growth strategies should take any time away from HR activities around screening and hiring,.</p>

<p>Maybe the whole company is siloed, but seeing it as IT vs The Business is silly (see Gene Kim's point 25 minutes in).</p>

<div style="text-align: center; font-style: italic">As an aside, spellcheck prefers to call that soiled. I find myself in agreement.</div>

<p>But wait, these are IT ops people talking, surely this is different, right? </p>

<p>I'll give you a hint, Gene Kim talks early on about how The Phoenix Project was influenced by <a href="http://en.wikipedia.org/wiki/The_Goal_%28novel%29">The Goal (Eliyahu Goldratt)</a>, whose main character is a plant operations manager. So no, IT Ops, IT QA, IT Technician, you are no more off the hook then the enormous variety of lawyers a business may need to work with over the course of it's life.</p>

<p>There are two types of workers, and they aren't IT and non-IT, they are engaged and not engaged. </p>

<h2>Are you doing your job?</h2>

<p>Are you doing the job, or just playing with technology?</p>

<p>An engaged worker knows how the company works, at some level. They can discuss the strategies the business is executing, what their company does, and who their customers are. They may not be able to discuss these things with equal facility as the executives or experts in specific departments, but they can have an intelligent conversation about their business. </p>

<p>The not-engaged worker is just there to do a job and go home. They are the protectors of turf, the ones that deny every request they can get away with, or the ones that simply don't care. </p>

<div style="text-align: center; font-weight: bold;">Ignorance of how your company works is a sign of incompetence, not something to be proud of. </div>

<p>So the reason an IT person (even an IT Ops person) can speak to a non-IT worker about the business is because "the business" is the common language they share. IT, accounting, purchasing, human resources, whoever ... when we need to discuss why something is important, we discuss it's impact on the the business, the strategies or targets it effects, etc. In fact, being in IT typically requires a <u>higher</u> level of day-to-day, cross-functional contact then any of the prior examples. More, not less.</p>

<p>Engaging the business has come and gone as part of many buzzy things, and in DevOps it's rising again. Regardless of it's current popularity, if you work for a company, being an IT person doesn't magically separate you from the goals everyone else is working towards. Engage, learn the business, help them succeed, you'll find that you're company is doing some really interesting things and works with some really interesting people. If it's not, find one that resonates with you and learn what they're doing. Either way, you're part of the business, an you chose whether you're competent or not.</p><div class="item_footer"><p><small><a href="http://blogs.lessthandot.com/index.php/ITProfessionals/other/it-vs-the-business">Original post</a> blogged on <a href="http://lessthandot.com/">LessThanDot</a>.</small></p></div>]]></content:encoded>
								<comments>http://blogs.lessthandot.com/index.php/ITProfessionals/other/it-vs-the-business#comments</comments>
			<wfw:commentRss>http://blogs.lessthandot.com/index.php/ITProfessionals/?tempskin=_rss2&#38;disp=comments&#38;p=2164</wfw:commentRss>
		</item>
				<item>
			<title>Azure Worker Role - Exiting Safely</title>
			<link>http://blogs.lessthandot.com/index.php/DesktopDev/MSTech/azure-worker-role-exiting-safely</link>
			<pubDate>Mon, 11 Feb 2013 18:59:00 +0000</pubDate>			<dc:creator>Eli Weinstock-Herman (tarwn)</dc:creator>
			<category domain="main">Microsoft Technologies</category>			<guid isPermaLink="false">2090@http://blogs.lessthandot.com/</guid>
						<description>&lt;p&gt;The basic Azure Worker Role consists of a run method, an endless loop, and a sleep statement. Earlier this week, Magnus Martensson walked through &lt;a href=&quot;http://magnusmartensson.com/howto-wait-in-a-workerrole-using-system-timers-timer-and-system-threading-eventwaithandle-over-system-threading-thread-sleep&quot; title=&quot;HowTo wait in a WorkerRole using Timer and EventWaitHandle over Thread.Sleep&quot;&gt;implementing a more sophisticated wait object&lt;/a&gt; than the generic Thread.Sleep call. Which reminded me of a problem inherent in the basic Microsoft template.&lt;/p&gt;

&lt;p&gt;Every exit is a crash.&lt;/p&gt;

&lt;p&gt;The basic Worker Role is a while(true) statement that alternates between doing work and sleeping for a period of time. When it&#039;s time for Azure to recycle the instance, deploy a new one, scale...what happens to this while(true) statement?&lt;/p&gt;

&lt;p&gt;It&#039;s killed. &lt;/p&gt;

&lt;p&gt;The more critical it was, the higher our chances it was in the work side of the work/sleep loop.&lt;/p&gt;

&lt;p&gt;(Ouch.)&lt;/p&gt;

&lt;h2&gt;The Basic Worker Role&lt;/h2&gt;
&lt;p&gt;Here is the worker class that Visual Studio generates on when creating a new Worker Role project:&lt;/p&gt;

&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;csharp&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;csharp&quot; id=&quot;cb36976&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;&lt;span style=&quot;color: #0600FF;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #FF0000;&quot;&gt;class&lt;/span&gt; WorkerRole : RoleEntryPoint&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #0600FF;&quot;&gt;override&lt;/span&gt; &lt;span style=&quot;color: #0600FF;&quot;&gt;void&lt;/span&gt; Run&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #008080; font-style: italic;&quot;&gt;// This is a sample worker implementation. Replace with your logic.&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Trace.&lt;span style=&quot;color: #0000FF;&quot;&gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;WorkerRole1 entry point called&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;Information&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF;&quot;&gt;while&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #0600FF;&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Thread.&lt;span style=&quot;color: #0000FF;&quot;&gt;Sleep&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;10000&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Trace.&lt;span style=&quot;color: #0000FF;&quot;&gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;Working&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;Information&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #0600FF;&quot;&gt;override&lt;/span&gt; &lt;span style=&quot;color: #FF0000;&quot;&gt;bool&lt;/span&gt; OnStart&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #008080; font-style: italic;&quot;&gt;// Set the maximum number of concurrent connections &lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ServicePointManager.&lt;span style=&quot;color: #0000FF;&quot;&gt;DefaultConnectionLimit&lt;/span&gt; = &lt;span style=&quot;color: #FF0000;&quot;&gt;12&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #008080; font-style: italic;&quot;&gt;// For information on handling configuration changes&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #008080; font-style: italic;&quot;&gt;// see the MSDN topic at &amp;lt;a href=&amp;quot;http://go.microsoft.com/fwlink/?LinkId=166357&amp;quot;&amp;gt;http://go.microsoft.com/fwlink/?LinkId=166357&amp;lt;/a&amp;gt;.&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #0600FF;&quot;&gt;base&lt;/span&gt;.&lt;span style=&quot;color: #0000FF;&quot;&gt;OnStart&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb66218&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Azure calls the OnStart when it starts, then calls the Run method. This sample will hard crash when Azure scales it out of existence, swaps in new instances, decides it&#039;s Windows patch time, lets us press the Stop button, and so on. &lt;/p&gt;

&lt;p&gt;Let&#039;s see it in action. I&#039;ve added a DoWork() method that sleeps for 10 seconds to simulate important work being done. I&#039;ve also added Trace.WriteLine calls to the existing methods and to an override of the OnStop method, so we can see what&#039;s happening.&lt;/p&gt;

&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;csharp&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;csharp&quot; id=&quot;cb11019&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;&lt;span style=&quot;color: #0600FF;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #0600FF;&quot;&gt;override&lt;/span&gt; &lt;span style=&quot;color: #0600FF;&quot;&gt;void&lt;/span&gt; Run&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #008080; font-style: italic;&quot;&gt;// This is a sample worker implementation. Replace with your logic.&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Trace.&lt;span style=&quot;color: #0000FF;&quot;&gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;BasicWorker - Entry point called&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;Information&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF;&quot;&gt;while&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #0600FF;&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Thread.&lt;span style=&quot;color: #0000FF;&quot;&gt;Sleep&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;10000&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Trace.&lt;span style=&quot;color: #0000FF;&quot;&gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;BasicWorker - Starting some work&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;Information&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; DoWork&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Trace.&lt;span style=&quot;color: #0000FF;&quot;&gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;BasicWorker - Finished some work&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;Information&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;color: #0600FF;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #0600FF;&quot;&gt;void&lt;/span&gt; DoWork&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Thread.&lt;span style=&quot;color: #0000FF;&quot;&gt;Sleep&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;10000&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;color: #0600FF;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #0600FF;&quot;&gt;override&lt;/span&gt; &lt;span style=&quot;color: #0600FF;&quot;&gt;void&lt;/span&gt; OnStop&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Trace.&lt;span style=&quot;color: #0000FF;&quot;&gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;BasicWorker - OnStop&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;Information&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb11391&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If we run this in the emulator and suspend the worker role in the middle of our important work, it exits right on cue, in the middle of the work.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Diagnostic Trace Output&lt;/b&gt;&lt;/p&gt;
&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;text&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;text&quot; id=&quot;cb34696&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;Information: 000.1s - BasicWorker - Entry point called&lt;br /&gt;Information: 010.1s - BasicWorker - Starting some work&lt;br /&gt;Information: 020.1s - BasicWorker - Finished some work&lt;br /&gt;Information: 030.1s - BasicWorker - Starting some work&lt;br /&gt;Information: 040.1s - BasicWorker - Finished some work&lt;br /&gt;Information: 050.1s - BasicWorker - Starting some work&lt;br /&gt;Information: 056.1s - BasicWorker - OnStop&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb68449&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;i&gt;note: I later added timestamps to the Trace output for readability&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;If this were a real worker role, we could have been doing just about anything in that step when it was killed. Is our system still in a good state?&lt;/p&gt;

&lt;h2&gt;A Cancel-able Worker Role&lt;/h2&gt;

&lt;p&gt;The base class for a WorkerRole is the RoleEntryPoint. As we saw above, it offers an OnStop method that will be called when the instance is suspended. More importantly, though, we are allowed to delay that OnStop method &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/microsoft.windowsazure.serviceruntime.roleentrypoint.onstop.aspx&quot; title=&quot;RoleEntryPoint.OnStop, MSDN&quot;&gt;up to 30 seconds&lt;/a&gt; to finish up what we are working on.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Note: Early last year (2012) this was extended to 5 minutes, though it&#039;s not reflected in the documentation above.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;The first change we want to make is to replace the while(true) construct with a method that we can &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/dd997364.aspx&quot; title=&quot;Cancellation in Managed Threads, MSDN&quot;&gt;cancel&lt;/a&gt;. Using a &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/system.threading.cancellationtokensource.aspx&quot; title=&quot;CancellationTokenSource, MSDN&quot;&gt;CancellationTokenSource&lt;/a&gt;, we can instead loop while that token is not cancelled.&lt;/p&gt;

&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;csharp&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;csharp&quot; id=&quot;cb44114&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;&lt;span style=&quot;color: #0600FF;&quot;&gt;private&lt;/span&gt; CancellationTokenSource _cancellationTokenSource;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;color: #0600FF;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #0600FF;&quot;&gt;override&lt;/span&gt; &lt;span style=&quot;color: #0600FF;&quot;&gt;void&lt;/span&gt; Run&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Trace.&lt;span style=&quot;color: #0000FF;&quot;&gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;SafeWorker - Entry point called&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;Information&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; _cancellationTokenSource = &lt;a href=&quot;http://www.google.com/search?q=new+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;new&lt;/span&gt;&lt;/a&gt; CancellationTokenSource&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; var token = _cancellationTokenSource.&lt;span style=&quot;color: #0000FF;&quot;&gt;Token&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF;&quot;&gt;while&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;!token.&lt;span style=&quot;color: #0000FF;&quot;&gt;IsCancellationRequested&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Trace.&lt;span style=&quot;color: #0000FF;&quot;&gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;SafeWorker - Starting some work&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;Information&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; DoWork&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Trace.&lt;span style=&quot;color: #0000FF;&quot;&gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;SafeWorker - Finished some work&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;Information&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; token.&lt;span style=&quot;color: #0000FF;&quot;&gt;WaitHandle&lt;/span&gt;.&lt;span style=&quot;color: #0000FF;&quot;&gt;WaitOne&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;10000&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #008080; font-style: italic;&quot;&gt;// sleep 10s or exit early if cancellation is signalled&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #008080; font-style: italic;&quot;&gt;// ...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb47050&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Replacing the Thread.Sleep with a &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/cc189907.aspx&quot; title=&quot;WaitOne, MSDN&quot;&gt;WaitOne()&lt;/a&gt; call will allow us to reduce the time to cancel. Unless it receives a signal (cancellation), the token will wait the specified number of milliseconds before continuing. Moving the WaitOne to the end ensures that if a cancellation is signaled, we won&#039;t pick up one last bit of work before exiting.&lt;/p&gt;

&lt;p&gt;The other piece of the equation is making the OnStop wait until the we have safely exited the loop. We can achieve this by creating a &quot;Safe to exit&quot; WaitHandle that is only set after successfully exiting the loop. The OnStop will Cancel via the CancellationToken, then wait for the &quot;Safe to exit&quot; token to be set before returning.&lt;/p&gt;

&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;csharp&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;csharp&quot; id=&quot;cb93916&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;&lt;span style=&quot;color: #0600FF;&quot;&gt;private&lt;/span&gt; CancellationTokenSource _cancellationTokenSource;&lt;br /&gt;&lt;span style=&quot;color: #0600FF;&quot;&gt;private&lt;/span&gt; ManualResetEvent _safeToExitHandle;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;color: #0600FF;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #0600FF;&quot;&gt;override&lt;/span&gt; &lt;span style=&quot;color: #0600FF;&quot;&gt;void&lt;/span&gt; Run&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Trace.&lt;span style=&quot;color: #0000FF;&quot;&gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;SafeWorker - Entry point called&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;Information&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; _cancellationTokenSource = &lt;a href=&quot;http://www.google.com/search?q=new+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;new&lt;/span&gt;&lt;/a&gt; CancellationTokenSource&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; _safeToExitHandle = &lt;a href=&quot;http://www.google.com/search?q=new+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;new&lt;/span&gt;&lt;/a&gt; ManualResetEvent&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #0600FF;&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; var token = _cancellationTokenSource.&lt;span style=&quot;color: #0000FF;&quot;&gt;Token&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF;&quot;&gt;while&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;!token.&lt;span style=&quot;color: #0000FF;&quot;&gt;IsCancellationRequested&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Trace.&lt;span style=&quot;color: #0000FF;&quot;&gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;SafeWorker - Starting some work&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;Information&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; DoWork&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Trace.&lt;span style=&quot;color: #0000FF;&quot;&gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;SafeWorker - Finished some work&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;Information&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; token.&lt;span style=&quot;color: #0000FF;&quot;&gt;WaitHandle&lt;/span&gt;.&lt;span style=&quot;color: #0000FF;&quot;&gt;WaitOne&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;10000&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #008080; font-style: italic;&quot;&gt;// sleep 10s or exit early if cancellation is signalled&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Trace.&lt;span style=&quot;color: #0000FF;&quot;&gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;SafeWorker - Ready to exit&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;Information&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; _safeToExitHandle.&lt;span style=&quot;color: #0000FF;&quot;&gt;Set&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #008080; font-style: italic;&quot;&gt;// cleanly exited the main loop&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;color: #008080; font-style: italic;&quot;&gt;// ...&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;color: #0600FF;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #0600FF;&quot;&gt;override&lt;/span&gt; &lt;span style=&quot;color: #0600FF;&quot;&gt;void&lt;/span&gt; OnStop&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Trace.&lt;span style=&quot;color: #0000FF;&quot;&gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;SafeWorker - OnStop Called&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;Information&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; _cancellationTokenSource.&lt;span style=&quot;color: #0000FF;&quot;&gt;Cancel&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; _safeToExitHandle.&lt;span style=&quot;color: #0000FF;&quot;&gt;WaitOne&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Trace.&lt;span style=&quot;color: #0000FF;&quot;&gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;SafeWorker - OnStop Complete, Exiting Safely&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;Information&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb96912&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now if we run this like the BasicWorker above, hitting the Suspend button in the middle of the DoWork call, we see the system takes the time to exit out safely:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Diagnostic Trace Output&lt;/b&gt;&lt;/p&gt;
&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;text&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;text&quot; id=&quot;cb82914&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;Information: 000.0s - SafeWorker - Entry point called&lt;br /&gt;Information: 000.1s - SafeWorker - Starting some work&lt;br /&gt;Information: 010.1s - SafeWorker - Finished some work&lt;br /&gt;Information: 020.1s - SafeWorker - Starting some work&lt;br /&gt;Information: 030.1s - SafeWorker - Finished some work&lt;br /&gt;Information: 040.1s - SafeWorker - Starting some work&lt;br /&gt;Information: 046.4s - SafeWorker - OnStop Called&lt;br /&gt;Information: 050.1s - SafeWorker - Finished some work&lt;br /&gt;Information: 050.1s - SafeWorker - Ready to exit&lt;br /&gt;Information: 050.1s - SafeWorker - OnStop Complete, Exiting Safely&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb84151&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;i&gt;note: I later added timestamps to the Trace output for readability&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;We can see the OnStop call come in in the middle of our Starting some Work/Finished some work output, but instead of exiting immediately, the worker calmly finished up it&#039;s work and then announced it was ready to exit (by setting the _safeToExitHandle WaitHandle).&lt;/p&gt;

&lt;h2&gt;Wrapping Up&lt;/h2&gt;
&lt;p&gt;Letting your application die in the middle of an operation is typically not a good idea. &lt;/p&gt;

&lt;p&gt;The example code for this post is available on github at &lt;a href=&quot;https://github.com/tarwn/AzureWorkerRole_Cancellation&quot; title=&quot;tarwn/AzureWorkerRole_Cancellation, GitHub&quot;&gt;tarwn/AzureWorkerRole_Cancellation&lt;/a&gt;. After finishing the code samples above, I went back and add seconds elapsed to the trace output message. I didn&#039;t update the code samples above because it would have only served to distract from the real code.&lt;/p&gt;

&lt;p&gt;I haven&#039;t posted on Azure as much as I probably should have, given how much of my time I spend working with it. Expect to see more posts on this in the upcoming months.&lt;/p&gt;&lt;div class=&quot;item_footer&quot;&gt;&lt;p&gt;&lt;small&gt;&lt;a href=&quot;http://blogs.lessthandot.com/index.php/DesktopDev/MSTech/azure-worker-role-exiting-safely&quot;&gt;Original post&lt;/a&gt; blogged on &lt;a href=&quot;http://lessthandot.com/&quot;&gt;LessThanDot&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;/div&gt;</description>
			<content:encoded><![CDATA[<p>The basic Azure Worker Role consists of a run method, an endless loop, and a sleep statement. Earlier this week, Magnus Martensson walked through <a href="http://magnusmartensson.com/howto-wait-in-a-workerrole-using-system-timers-timer-and-system-threading-eventwaithandle-over-system-threading-thread-sleep" title="HowTo wait in a WorkerRole using Timer and EventWaitHandle over Thread.Sleep">implementing a more sophisticated wait object</a> than the generic Thread.Sleep call. Which reminded me of a problem inherent in the basic Microsoft template.</p>

<p>Every exit is a crash.</p>

<p>The basic Worker Role is a while(true) statement that alternates between doing work and sleeping for a period of time. When it's time for Azure to recycle the instance, deploy a new one, scale...what happens to this while(true) statement?</p>

<p>It's killed. </p>

<p>The more critical it was, the higher our chances it was in the work side of the work/sleep loop.</p>

<p>(Ouch.)</p>

<h2>The Basic Worker Role</h2>
<p>Here is the worker class that Visual Studio generates on when creating a new Worker Role project:</p>

<div class="codebox"><div class="codeheader"><span>csharp</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb53031'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb53031','cb65004'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="csharp" id="cb53031" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1"><span style="color: #0600FF;">public</span> <span style="color: #FF0000;">class</span> WorkerRole : RoleEntryPoint</li><li style="" class="li2"><span style="color: #000000;">&#123;</span></li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">override</span> <span style="color: #0600FF;">void</span> Run<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span></li><li style="" class="li2">&nbsp; &nbsp; <span style="color: #000000;">&#123;</span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080; font-style: italic;">// This is a sample worker implementation. Replace with your logic.</span></li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; Trace.<span style="color: #0000FF;">WriteLine</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;WorkerRole1 entry point called&quot;</span>, <span style="color: #808080;">&quot;Information&quot;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li1">&nbsp;</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">while</span> <span style="color: #000000;">&#40;</span><span style="color: #0600FF;">true</span><span style="color: #000000;">&#41;</span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span></li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Thread.<span style="color: #0000FF;">Sleep</span><span style="color: #000000;">&#40;</span><span style="color: #FF0000;">10000</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Trace.<span style="color: #0000FF;">WriteLine</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;Working&quot;</span>, <span style="color: #808080;">&quot;Information&quot;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span></li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #000000;">&#125;</span></li><li style="" class="li2">&nbsp;</li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">override</span> <span style="color: #FF0000;">bool</span> OnStart<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span></li><li style="" class="li2">&nbsp; &nbsp; <span style="color: #000000;">&#123;</span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080; font-style: italic;">// Set the maximum number of concurrent connections </span></li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; ServicePointManager.<span style="color: #0000FF;">DefaultConnectionLimit</span> = <span style="color: #FF0000;">12</span>;</li><li style="" class="li1">&nbsp;</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080; font-style: italic;">// For information on handling configuration changes</span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080; font-style: italic;">// see the MSDN topic at &lt;a href=&quot;http://go.microsoft.com/fwlink/?LinkId=166357&quot;&gt;http://go.microsoft.com/fwlink/?LinkId=166357&lt;/a&gt;.</span></li><li style="" class="li2">&nbsp;</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> <span style="color: #0600FF;">base</span>.<span style="color: #0000FF;">OnStart</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp; &nbsp; <span style="color: #000000;">&#125;</span></li><li style="" class="li1"><span style="color: #000000;">&#125;</span></li></ol></div><div id="cb65004" style="display: none; color: red;"></div></div></div>

<p>Azure calls the OnStart when it starts, then calls the Run method. This sample will hard crash when Azure scales it out of existence, swaps in new instances, decides it's Windows patch time, lets us press the Stop button, and so on. </p>

<p>Let's see it in action. I've added a DoWork() method that sleeps for 10 seconds to simulate important work being done. I've also added Trace.WriteLine calls to the existing methods and to an override of the OnStop method, so we can see what's happening.</p>

<div class="codebox"><div class="codeheader"><span>csharp</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb22549'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb22549','cb4132'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="csharp" id="cb22549" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1"><span style="color: #0600FF;">public</span> <span style="color: #0600FF;">override</span> <span style="color: #0600FF;">void</span> Run<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span></li><li style="" class="li2"><span style="color: #000000;">&#123;</span></li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #008080; font-style: italic;">// This is a sample worker implementation. Replace with your logic.</span></li><li style="" class="li2">&nbsp; &nbsp; Trace.<span style="color: #0000FF;">WriteLine</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;BasicWorker - Entry point called&quot;</span>, <span style="color: #808080;">&quot;Information&quot;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li1">&nbsp;</li><li style="" class="li2">&nbsp; &nbsp; <span style="color: #0600FF;">while</span> <span style="color: #000000;">&#40;</span><span style="color: #0600FF;">true</span><span style="color: #000000;">&#41;</span></li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #000000;">&#123;</span></li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; Thread.<span style="color: #0000FF;">Sleep</span><span style="color: #000000;">&#40;</span><span style="color: #FF0000;">10000</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; Trace.<span style="color: #0000FF;">WriteLine</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;BasicWorker - Starting some work&quot;</span>, <span style="color: #808080;">&quot;Information&quot;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; DoWork<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; Trace.<span style="color: #0000FF;">WriteLine</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;BasicWorker - Finished some work&quot;</span>, <span style="color: #808080;">&quot;Information&quot;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp; &nbsp; <span style="color: #000000;">&#125;</span></li><li style="" class="li1"><span style="color: #000000;">&#125;</span></li><li style="" class="li2">&nbsp;</li><li style="" class="li1"><span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> DoWork<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span></li><li style="" class="li2"><span style="color: #000000;">&#123;</span></li><li style="" class="li1">&nbsp; &nbsp; Thread.<span style="color: #0000FF;">Sleep</span><span style="color: #000000;">&#40;</span><span style="color: #FF0000;">10000</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li2"><span style="color: #000000;">&#125;</span></li><li style="" class="li1">&nbsp;</li><li style="" class="li2"><span style="color: #0600FF;">public</span> <span style="color: #0600FF;">override</span> <span style="color: #0600FF;">void</span> OnStop<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span></li><li style="" class="li1"><span style="color: #000000;">&#123;</span></li><li style="" class="li2">&nbsp; &nbsp; Trace.<span style="color: #0000FF;">WriteLine</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;BasicWorker - OnStop&quot;</span>, <span style="color: #808080;">&quot;Information&quot;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li1"><span style="color: #000000;">&#125;</span></li></ol></div><div id="cb4132" style="display: none; color: red;"></div></div></div>

<p>If we run this in the emulator and suspend the worker role in the middle of our important work, it exits right on cue, in the middle of the work.</p>

<p><b>Diagnostic Trace Output</b></p>
<div class="codebox"><div class="codeheader"><span>text</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb20529'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb20529','cb77055'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="text" id="cb20529" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1">Information: 000.1s - BasicWorker - Entry point called</li><li style="" class="li2">Information: 010.1s - BasicWorker - Starting some work</li><li style="" class="li1">Information: 020.1s - BasicWorker - Finished some work</li><li style="" class="li2">Information: 030.1s - BasicWorker - Starting some work</li><li style="" class="li1">Information: 040.1s - BasicWorker - Finished some work</li><li style="" class="li2">Information: 050.1s - BasicWorker - Starting some work</li><li style="" class="li1">Information: 056.1s - BasicWorker - OnStop</li></ol></div><div id="cb77055" style="display: none; color: red;"></div></div></div>

<p><i>note: I later added timestamps to the Trace output for readability</i></p>

<p>If this were a real worker role, we could have been doing just about anything in that step when it was killed. Is our system still in a good state?</p>

<h2>A Cancel-able Worker Role</h2>

<p>The base class for a WorkerRole is the RoleEntryPoint. As we saw above, it offers an OnStop method that will be called when the instance is suspended. More importantly, though, we are allowed to delay that OnStop method <a href="http://msdn.microsoft.com/en-us/library/microsoft.windowsazure.serviceruntime.roleentrypoint.onstop.aspx" title="RoleEntryPoint.OnStop, MSDN">up to 30 seconds</a> to finish up what we are working on.</p>

<p><i>Note: Early last year (2012) this was extended to 5 minutes, though it's not reflected in the documentation above.</i></p>

<p>The first change we want to make is to replace the while(true) construct with a method that we can <a href="http://msdn.microsoft.com/en-us/library/dd997364.aspx" title="Cancellation in Managed Threads, MSDN">cancel</a>. Using a <a href="http://msdn.microsoft.com/en-us/library/system.threading.cancellationtokensource.aspx" title="CancellationTokenSource, MSDN">CancellationTokenSource</a>, we can instead loop while that token is not cancelled.</p>

<div class="codebox"><div class="codeheader"><span>csharp</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb40760'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb40760','cb41804'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="csharp" id="cb40760" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1"><span style="color: #0600FF;">private</span> CancellationTokenSource _cancellationTokenSource;</li><li style="" class="li2">&nbsp;</li><li style="" class="li1"><span style="color: #0600FF;">public</span> <span style="color: #0600FF;">override</span> <span style="color: #0600FF;">void</span> Run<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span></li><li style="" class="li2"><span style="color: #000000;">&#123;</span></li><li style="" class="li1">&nbsp; &nbsp; Trace.<span style="color: #0000FF;">WriteLine</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;SafeWorker - Entry point called&quot;</span>, <span style="color: #808080;">&quot;Information&quot;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp; &nbsp; _cancellationTokenSource = <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> CancellationTokenSource<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li1">&nbsp; &nbsp; var token = _cancellationTokenSource.<span style="color: #0000FF;">Token</span>;</li><li style="" class="li2">&nbsp;</li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #0600FF;">while</span> <span style="color: #000000;">&#40;</span>!token.<span style="color: #0000FF;">IsCancellationRequested</span><span style="color: #000000;">&#41;</span></li><li style="" class="li2">&nbsp; &nbsp; <span style="color: #000000;">&#123;</span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; Trace.<span style="color: #0000FF;">WriteLine</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;SafeWorker - Starting some work&quot;</span>, <span style="color: #808080;">&quot;Information&quot;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; DoWork<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; Trace.<span style="color: #0000FF;">WriteLine</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;SafeWorker - Finished some work&quot;</span>, <span style="color: #808080;">&quot;Information&quot;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; token.<span style="color: #0000FF;">WaitHandle</span>.<span style="color: #0000FF;">WaitOne</span><span style="color: #000000;">&#40;</span><span style="color: #FF0000;">10000</span><span style="color: #000000;">&#41;</span>;&nbsp; &nbsp; <span style="color: #008080; font-style: italic;">// sleep 10s or exit early if cancellation is signalled</span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080; font-style: italic;">// ...</span></li></ol></div><div id="cb41804" style="display: none; color: red;"></div></div></div>

<p>Replacing the Thread.Sleep with a <a href="http://msdn.microsoft.com/en-us/library/cc189907.aspx" title="WaitOne, MSDN">WaitOne()</a> call will allow us to reduce the time to cancel. Unless it receives a signal (cancellation), the token will wait the specified number of milliseconds before continuing. Moving the WaitOne to the end ensures that if a cancellation is signaled, we won't pick up one last bit of work before exiting.</p>

<p>The other piece of the equation is making the OnStop wait until the we have safely exited the loop. We can achieve this by creating a "Safe to exit" WaitHandle that is only set after successfully exiting the loop. The OnStop will Cancel via the CancellationToken, then wait for the "Safe to exit" token to be set before returning.</p>

<div class="codebox"><div class="codeheader"><span>csharp</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb61262'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb61262','cb9940'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="csharp" id="cb61262" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1"><span style="color: #0600FF;">private</span> CancellationTokenSource _cancellationTokenSource;</li><li style="" class="li2"><span style="color: #0600FF;">private</span> ManualResetEvent _safeToExitHandle;</li><li style="" class="li1">&nbsp;</li><li style="" class="li2"><span style="color: #0600FF;">public</span> <span style="color: #0600FF;">override</span> <span style="color: #0600FF;">void</span> Run<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span></li><li style="" class="li1"><span style="color: #000000;">&#123;</span></li><li style="" class="li2">&nbsp; &nbsp; Trace.<span style="color: #0000FF;">WriteLine</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;SafeWorker - Entry point called&quot;</span>, <span style="color: #808080;">&quot;Information&quot;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li1">&nbsp; &nbsp; _cancellationTokenSource = <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> CancellationTokenSource<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp; &nbsp; _safeToExitHandle = <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> ManualResetEvent<span style="color: #000000;">&#40;</span><span style="color: #0600FF;">false</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li1">&nbsp; &nbsp; var token = _cancellationTokenSource.<span style="color: #0000FF;">Token</span>;</li><li style="" class="li2">&nbsp;</li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #0600FF;">while</span> <span style="color: #000000;">&#40;</span>!token.<span style="color: #0000FF;">IsCancellationRequested</span><span style="color: #000000;">&#41;</span></li><li style="" class="li2">&nbsp; &nbsp; <span style="color: #000000;">&#123;</span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; Trace.<span style="color: #0000FF;">WriteLine</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;SafeWorker - Starting some work&quot;</span>, <span style="color: #808080;">&quot;Information&quot;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; DoWork<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; Trace.<span style="color: #0000FF;">WriteLine</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;SafeWorker - Finished some work&quot;</span>, <span style="color: #808080;">&quot;Information&quot;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; token.<span style="color: #0000FF;">WaitHandle</span>.<span style="color: #0000FF;">WaitOne</span><span style="color: #000000;">&#40;</span><span style="color: #FF0000;">10000</span><span style="color: #000000;">&#41;</span>;&nbsp; &nbsp; <span style="color: #008080; font-style: italic;">// sleep 10s or exit early if cancellation is signalled</span></li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #000000;">&#125;</span></li><li style="" class="li2">&nbsp;</li><li style="" class="li1">&nbsp; &nbsp; Trace.<span style="color: #0000FF;">WriteLine</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;SafeWorker - Ready to exit&quot;</span>, <span style="color: #808080;">&quot;Information&quot;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp; &nbsp; _safeToExitHandle.<span style="color: #0000FF;">Set</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;&nbsp; &nbsp; <span style="color: #008080; font-style: italic;">// cleanly exited the main loop</span></li><li style="" class="li1"><span style="color: #000000;">&#125;</span></li><li style="" class="li2">&nbsp;</li><li style="" class="li1"><span style="color: #008080; font-style: italic;">// ...</span></li><li style="" class="li2">&nbsp;</li><li style="" class="li1"><span style="color: #0600FF;">public</span> <span style="color: #0600FF;">override</span> <span style="color: #0600FF;">void</span> OnStop<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span></li><li style="" class="li2"><span style="color: #000000;">&#123;</span></li><li style="" class="li1">&nbsp; &nbsp; Trace.<span style="color: #0000FF;">WriteLine</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;SafeWorker - OnStop Called&quot;</span>, <span style="color: #808080;">&quot;Information&quot;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp; &nbsp; _cancellationTokenSource.<span style="color: #0000FF;">Cancel</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li1">&nbsp; &nbsp; _safeToExitHandle.<span style="color: #0000FF;">WaitOne</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp; &nbsp; Trace.<span style="color: #0000FF;">WriteLine</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;SafeWorker - OnStop Complete, Exiting Safely&quot;</span>, <span style="color: #808080;">&quot;Information&quot;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li1"><span style="color: #000000;">&#125;</span></li></ol></div><div id="cb9940" style="display: none; color: red;"></div></div></div>

<p>Now if we run this like the BasicWorker above, hitting the Suspend button in the middle of the DoWork call, we see the system takes the time to exit out safely:</p>

<p><b>Diagnostic Trace Output</b></p>
<div class="codebox"><div class="codeheader"><span>text</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb24427'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb24427','cb35511'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="text" id="cb24427" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1">Information: 000.0s - SafeWorker - Entry point called</li><li style="" class="li2">Information: 000.1s - SafeWorker - Starting some work</li><li style="" class="li1">Information: 010.1s - SafeWorker - Finished some work</li><li style="" class="li2">Information: 020.1s - SafeWorker - Starting some work</li><li style="" class="li1">Information: 030.1s - SafeWorker - Finished some work</li><li style="" class="li2">Information: 040.1s - SafeWorker - Starting some work</li><li style="" class="li1">Information: 046.4s - SafeWorker - OnStop Called</li><li style="" class="li2">Information: 050.1s - SafeWorker - Finished some work</li><li style="" class="li1">Information: 050.1s - SafeWorker - Ready to exit</li><li style="" class="li2">Information: 050.1s - SafeWorker - OnStop Complete, Exiting Safely</li></ol></div><div id="cb35511" style="display: none; color: red;"></div></div></div>

<p><i>note: I later added timestamps to the Trace output for readability</i></p>

<p>We can see the OnStop call come in in the middle of our Starting some Work/Finished some work output, but instead of exiting immediately, the worker calmly finished up it's work and then announced it was ready to exit (by setting the _safeToExitHandle WaitHandle).</p>

<h2>Wrapping Up</h2>
<p>Letting your application die in the middle of an operation is typically not a good idea. </p>

<p>The example code for this post is available on github at <a href="https://github.com/tarwn/AzureWorkerRole_Cancellation" title="tarwn/AzureWorkerRole_Cancellation, GitHub">tarwn/AzureWorkerRole_Cancellation</a>. After finishing the code samples above, I went back and add seconds elapsed to the trace output message. I didn't update the code samples above because it would have only served to distract from the real code.</p>

<p>I haven't posted on Azure as much as I probably should have, given how much of my time I spend working with it. Expect to see more posts on this in the upcoming months.</p><div class="item_footer"><p><small><a href="http://blogs.lessthandot.com/index.php/DesktopDev/MSTech/azure-worker-role-exiting-safely">Original post</a> blogged on <a href="http://lessthandot.com/">LessThanDot</a>.</small></p></div>]]></content:encoded>
								<comments>http://blogs.lessthandot.com/index.php/DesktopDev/MSTech/azure-worker-role-exiting-safely#comments</comments>
			<wfw:commentRss>http://blogs.lessthandot.com/index.php/DesktopDev/?tempskin=_rss2&#38;disp=comments&#38;p=2090</wfw:commentRss>
		</item>
				<item>
			<title>Quality, Quality Assurance, and How Not To Do It</title>
			<link>http://blogs.lessthandot.com/index.php/ITProfessionals/ITProcesses/quality-quality-assurance-and-how</link>
			<pubDate>Mon, 04 Feb 2013 12:01:00 +0000</pubDate>			<dc:creator>Eli Weinstock-Herman (tarwn)</dc:creator>
			<category domain="main">IT Processes</category>			<guid isPermaLink="false">2067@http://blogs.lessthandot.com/</guid>
						<description>&lt;p&gt;The technical sphere seems to have very mixed definitions for the terms &quot;Quality&quot; and &quot;Quality Assurance&quot;. The other day I was reading a post by Devlin Liles (&lt;a href=&quot;http://devlinliles.com/&quot; title=&quot;DevlinLiles.com&quot;&gt;blog&lt;/a&gt;|&lt;a href=&quot;https://twitter.com/devlinliles&quot; title=&quot;@DevlinLiles on twitter&quot;&gt;twitter&lt;/a&gt;) in response to a presentation he had attended (&lt;a href=&quot;http://www.devlinliles.com/post/2013/01/31/Quality-Assurance-The-Team-Approach&quot; title=&quot;Quality Assurance&amp;#8211;The Team Approach&quot;&gt;Quality Assurance&amp;#8211;The Team Approach&lt;/a&gt;). While I agreed with a lot of his opinions, as I started to leave a comment I found myself sidetracked into examining the different (and in many cases, wrong) definitions we use for Quality and Quality Assurance.&lt;/p&gt;

&lt;h2&gt;Quality&lt;/h2&gt;
&lt;p&gt;Often in the software world, Quality seems to mean &quot;Does it work or not&quot;. Occasionally there is the idea of a &lt;a href=&quot;http://blogs.lessthandot.com/index.php/ITProfessionals/ProjectManagement/defining-done&quot; title=&quot;LessThanDot Blog - Defining What Done Means&quot;&gt;Definition of Done&lt;/a&gt;, and the definition of Quality includes additional documents, automated tests, formal communications, etc. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;b&gt;Dictionary.com&lt;/b&gt; - character with respect to fineness, or grade of excellence&lt;br /&gt;
&lt;b&gt;Merriam Webster&lt;/b&gt; - degree of excellence, superiority in kind&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If Quality is a scale of excellence, what level do we assign to &quot;it works&quot;? What grade do we get for &quot;I didn&#039;t find any broken bits&quot;? Why do we keep assuming &quot;it isn&#039;t obviously broken&quot; means we have achieved quality?&lt;/p&gt;

&lt;p&gt;I ran into &lt;a href=&quot;http://onquality.blogspot.com/2010/04/what-is-quality.html&quot; title=&quot;What is Quality? by Jimena Calfa&quot;&gt;this post&lt;/a&gt; that examines a number of different definitions of quality and refines them all into:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;1. A characteristic of a product or service that bears on its ability to satisfy and exceed* stated or implied customer needs, and thereby provide customer satisfaction.&lt;br /&gt;
2. Freedom from deficiencies.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Which is similar to my less formal definition of:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Quality is how well the product does what we said it would, from the customer&#039;s perspective&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Quality is a scale, not an on/off switch.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the product has defects (ie, broken bits), then we have Quality problems. &lt;/li&gt;
&lt;li&gt;If we cut features at the end of the development cycle and don&#039;t tell the customer, we have Quality problems. &lt;/li&gt;
&lt;li&gt;If we have a breakdown in communications to the customer while explaining what the product does, we have a Quality problem. &lt;/li&gt;
&lt;li&gt;If the customer has difficulty interacting with the product, we have Quality problems. &lt;/li&gt;
&lt;li&gt;If the product behaves inconsistently when the customer is using it, we have Quality problems. &lt;/li&gt;
&lt;li&gt;If we deviate from our industry standards without informing the customer, we have Quality problems. &lt;/li&gt;
&lt;li&gt;If we deviate from their industry standards without informing them, we have Quality problems.&lt;/li&gt;
&lt;li&gt;If we have to argue with the customer over whether we built what they asked for, we have Quality problems&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On a scale of &quot;it destroyed our business&quot; to &quot;it was generations beyond what we could have imagined&quot;, &quot;we didn&#039;t find any obvious bugs&quot; sits firmly at zero.&lt;/p&gt;

&lt;h2&gt;Quality Assurance&lt;/h2&gt;
&lt;p&gt;So after a rather long-winded definition of Quality, what about Quality Assurance?&lt;/p&gt;

&lt;p&gt;I&#039;m not a quality professional, but most of what I hear or read seems to be using the definition of Quality Assurance that means we have testers testing our product before delivery. Possibly with some automated tests. Possibly even with some automated tests that can be run by the developers (not to be confused with forms of testing that are the developer&#039;s responsibility).&lt;/p&gt;

&lt;p&gt;Sound about right?&lt;/p&gt;

&lt;p&gt;Except this is Quality Ensurance. Testing the mostly finished product is designed to &lt;u&gt;Ensure&lt;/u&gt; our product meets a specific standard of quality.&lt;/p&gt;

&lt;p&gt;Assurance is a proactive term, &quot;it will be good&quot; vs Ensure&#039;s &quot;we checked at the end and it was good&quot;. The purpose of Quality Assurance is to build confidence in the level of Quality (Assure) by driving improvements, so that improved Quality is a natural result. We Assure, are confidant of, better quality by helping it get cooked in from the start.&lt;/p&gt;

&lt;p&gt;We are all responsible for Quality, but Quality Assurance is responsible for improving the processes, tooling, environment, and business to increase the Quality of our output. Inspection at the end serves as a good first step, so we can gather data to drive improvements, but if this is all you are getting from your Quality Assurance efforts, then you don&#039;t actually have a Quality Assurance effort. &lt;/p&gt;

&lt;h2&gt;Devlin&#039;s Post&lt;/h2&gt;
&lt;p&gt;So back to &lt;a href=&quot;http://www.devlinliles.com/post/2013/01/31/Quality-Assurance-The-Team-Approach&quot; title=&quot;Quality Assurance&amp;#8211;The Team Approach&quot;&gt;Devlin&#039;s post&lt;/a&gt;. He listed a number of points from the presentation and his thoughts on them. While I didn&#039;t attend and am therefore missing some of the context, here are my thoughts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Risk Mitigation is the main job of QA&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Absolutely not. The job of QA is to improve our ability to build Quality in as we build the product. This may have the side effect of mitigating risk, but that is a natural outgrowth of building something that engenders greater satisfaction from it&#039;s purchaser.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;br /&gt;
2. Cost of finding bugs is higher as you get later in the deployment cycle, so we should incentivize finding bugs early because we saved that money.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Incentivising is one way to improve the ability to build Quality as close to the source as possible, so it passes the Quality Assurance definition above. However, I think incentivizing drives the wrong behavior. Even the most honest developer could choose to spend their time finding bugs instead of building the product. And at the end of the day, what we really want is fewer bugs created, which incentivizing could prevent us from improving towards.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. High Quality / Focus on Quality cost more money&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes, but only in the short term. Producing Quality products is taking the long view, thinking past the immediate contract or deal that is on the table. Measuring the effects can be difficult, but that doesn&#039;t mean they are nonexistent. How much would you pay to turn your customers into part of your marketing and sales teams? How much more productive is the team that is proud of what they build? How much less do you spend manually inspecting for Quality at the end of the process when it&#039;s built in early on? How much do you save with a better understanding of requirements as your building the product, rather than after you have delivered? What is the value of being able to deliver a product confidently instead of worrying the customer may not accept it? &lt;/p&gt;

&lt;p&gt;Technically, firing the quality team will also save you money. So will firing the development team. That doesn&#039;t make them good long term strategies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Unit Testing should be a task for each development task&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I feel the same as Devlin on this, if you&#039;re in an environment that doesn&#039;t include it as part of getting a task done, then, yes, it may be helpful to assign each task with a paired &quot;so the unit tests&quot; task until people get used to doing them together. But this isn&#039;t an end state, at some point there should be agreement that doing the tests is simply part of calling the work done.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5.There are Different Kinds of testers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here I am going to have to diverge from Devlin again, but I&#039;m pretty sure it&#039;s a context issue. I think the question of whether there are different types of testers depends on whether we are talking about types of tests or areas being tested. A manual tester at the end of our process is going to have very different skills then an experienced security tester, which will in turn be different than the skills of a usability tester.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Team Collaboration on testing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Again, this is an example of one type of improvement a Quality Assurance team could make in a business. This one may be more successful than the incentivising one above, but I think it&#039;s going to depend on the environment it&#039;s implemented in and, as such, isn&#039;t something I can comment on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8. QA is the Whole Team&amp;#8217;s responsibility.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I started out agreeing with Devlin, but I&#039;m going to have to revise my opinion. I think the idea of continuous improvement should be built into the whole team, so that everyone takes responsibility for improving their surroundings, processes, and selves. And I think this directly feeds Quality, because the improvements we are making should be improving the quality of things, either as measured by the customer (product quality) or our coworkers, management, or even cleaning staff. So in a perfect world, building in improvements to improve Quality is part of the individual team members responsibilities. &lt;/p&gt;

&lt;p&gt;However, I think there should still be someone who has overall responsibility for QA, either in the role of a manager or coach, to ensure that decisions are being made soundly on real data, ensure we aren&#039;t over-optimizing one portion of the business at the expense of another, and so on.&lt;/p&gt;

&lt;h2&gt;Thoughts?&lt;/h2&gt;
&lt;p&gt;A lot of people in the software world dislike Quality assurance, but I think this is because there are a lot of poor Quality Assurance efforts out there that never get past the manual test stage (and thus aren&#039;t actually assuring quality).&lt;/p&gt;

&lt;p&gt;Regardless, if &quot;It ain&#039;t broke&quot; is the highest measure of quality in your company, it may be time to recalibrate expectations.&lt;/p&gt;&lt;div class=&quot;item_footer&quot;&gt;&lt;p&gt;&lt;small&gt;&lt;a href=&quot;http://blogs.lessthandot.com/index.php/ITProfessionals/ITProcesses/quality-quality-assurance-and-how&quot;&gt;Original post&lt;/a&gt; blogged on &lt;a href=&quot;http://lessthandot.com/&quot;&gt;LessThanDot&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;/div&gt;</description>
			<content:encoded><![CDATA[<p>The technical sphere seems to have very mixed definitions for the terms "Quality" and "Quality Assurance". The other day I was reading a post by Devlin Liles (<a href="http://devlinliles.com/" title="DevlinLiles.com">blog</a>|<a href="https://twitter.com/devlinliles" title="@DevlinLiles on twitter">twitter</a>) in response to a presentation he had attended (<a href="http://www.devlinliles.com/post/2013/01/31/Quality-Assurance-The-Team-Approach" title="Quality Assurance&#8211;The Team Approach">Quality Assurance&#8211;The Team Approach</a>). While I agreed with a lot of his opinions, as I started to leave a comment I found myself sidetracked into examining the different (and in many cases, wrong) definitions we use for Quality and Quality Assurance.</p>

<h2>Quality</h2>
<p>Often in the software world, Quality seems to mean "Does it work or not". Occasionally there is the idea of a <a href="http://blogs.lessthandot.com/index.php/ITProfessionals/ProjectManagement/defining-done" title="LessThanDot Blog - Defining What Done Means">Definition of Done</a>, and the definition of Quality includes additional documents, automated tests, formal communications, etc. </p>

<blockquote>
<p><b>Dictionary.com</b> - character with respect to fineness, or grade of excellence<br />
<b>Merriam Webster</b> - degree of excellence, superiority in kind</p>
</blockquote>

<p>If Quality is a scale of excellence, what level do we assign to "it works"? What grade do we get for "I didn't find any broken bits"? Why do we keep assuming "it isn't obviously broken" means we have achieved quality?</p>

<p>I ran into <a href="http://onquality.blogspot.com/2010/04/what-is-quality.html" title="What is Quality? by Jimena Calfa">this post</a> that examines a number of different definitions of quality and refines them all into:</p>

<blockquote>
<p>1. A characteristic of a product or service that bears on its ability to satisfy and exceed* stated or implied customer needs, and thereby provide customer satisfaction.<br />
2. Freedom from deficiencies.</p>
</blockquote>

<p>Which is similar to my less formal definition of:</p>

<blockquote><p>Quality is how well the product does what we said it would, from the customer's perspective</p></blockquote>

<p>Quality is a scale, not an on/off switch.</p>

<ul>
<li>If the product has defects (ie, broken bits), then we have Quality problems. </li>
<li>If we cut features at the end of the development cycle and don't tell the customer, we have Quality problems. </li>
<li>If we have a breakdown in communications to the customer while explaining what the product does, we have a Quality problem. </li>
<li>If the customer has difficulty interacting with the product, we have Quality problems. </li>
<li>If the product behaves inconsistently when the customer is using it, we have Quality problems. </li>
<li>If we deviate from our industry standards without informing the customer, we have Quality problems. </li>
<li>If we deviate from their industry standards without informing them, we have Quality problems.</li>
<li>If we have to argue with the customer over whether we built what they asked for, we have Quality problems</li>
</ul>

<p>On a scale of "it destroyed our business" to "it was generations beyond what we could have imagined", "we didn't find any obvious bugs" sits firmly at zero.</p>

<h2>Quality Assurance</h2>
<p>So after a rather long-winded definition of Quality, what about Quality Assurance?</p>

<p>I'm not a quality professional, but most of what I hear or read seems to be using the definition of Quality Assurance that means we have testers testing our product before delivery. Possibly with some automated tests. Possibly even with some automated tests that can be run by the developers (not to be confused with forms of testing that are the developer's responsibility).</p>

<p>Sound about right?</p>

<p>Except this is Quality Ensurance. Testing the mostly finished product is designed to <u>Ensure</u> our product meets a specific standard of quality.</p>

<p>Assurance is a proactive term, "it will be good" vs Ensure's "we checked at the end and it was good". The purpose of Quality Assurance is to build confidence in the level of Quality (Assure) by driving improvements, so that improved Quality is a natural result. We Assure, are confidant of, better quality by helping it get cooked in from the start.</p>

<p>We are all responsible for Quality, but Quality Assurance is responsible for improving the processes, tooling, environment, and business to increase the Quality of our output. Inspection at the end serves as a good first step, so we can gather data to drive improvements, but if this is all you are getting from your Quality Assurance efforts, then you don't actually have a Quality Assurance effort. </p>

<h2>Devlin's Post</h2>
<p>So back to <a href="http://www.devlinliles.com/post/2013/01/31/Quality-Assurance-The-Team-Approach" title="Quality Assurance&#8211;The Team Approach">Devlin's post</a>. He listed a number of points from the presentation and his thoughts on them. While I didn't attend and am therefore missing some of the context, here are my thoughts.</p>

<p><strong>1. Risk Mitigation is the main job of QA</strong></p>

<p>Absolutely not. The job of QA is to improve our ability to build Quality in as we build the product. This may have the side effect of mitigating risk, but that is a natural outgrowth of building something that engenders greater satisfaction from it's purchaser.</p>

<p><strong><br />
2. Cost of finding bugs is higher as you get later in the deployment cycle, so we should incentivize finding bugs early because we saved that money.</strong></p>

<p>Incentivising is one way to improve the ability to build Quality as close to the source as possible, so it passes the Quality Assurance definition above. However, I think incentivizing drives the wrong behavior. Even the most honest developer could choose to spend their time finding bugs instead of building the product. And at the end of the day, what we really want is fewer bugs created, which incentivizing could prevent us from improving towards.</p>

<p><strong>3. High Quality / Focus on Quality cost more money</strong></p>

<p>Yes, but only in the short term. Producing Quality products is taking the long view, thinking past the immediate contract or deal that is on the table. Measuring the effects can be difficult, but that doesn't mean they are nonexistent. How much would you pay to turn your customers into part of your marketing and sales teams? How much more productive is the team that is proud of what they build? How much less do you spend manually inspecting for Quality at the end of the process when it's built in early on? How much do you save with a better understanding of requirements as your building the product, rather than after you have delivered? What is the value of being able to deliver a product confidently instead of worrying the customer may not accept it? </p>

<p>Technically, firing the quality team will also save you money. So will firing the development team. That doesn't make them good long term strategies.</p>

<p><strong>4. Unit Testing should be a task for each development task</strong></p>

<p>I feel the same as Devlin on this, if you're in an environment that doesn't include it as part of getting a task done, then, yes, it may be helpful to assign each task with a paired "so the unit tests" task until people get used to doing them together. But this isn't an end state, at some point there should be agreement that doing the tests is simply part of calling the work done.</p>

<p><strong>5.There are Different Kinds of testers</strong></p>

<p>Here I am going to have to diverge from Devlin again, but I'm pretty sure it's a context issue. I think the question of whether there are different types of testers depends on whether we are talking about types of tests or areas being tested. A manual tester at the end of our process is going to have very different skills then an experienced security tester, which will in turn be different than the skills of a usability tester.</p>

<p><strong>7. Team Collaboration on testing</strong></p>

<p>Again, this is an example of one type of improvement a Quality Assurance team could make in a business. This one may be more successful than the incentivising one above, but I think it's going to depend on the environment it's implemented in and, as such, isn't something I can comment on.</p>

<p><strong>8. QA is the Whole Team&#8217;s responsibility.</strong></p>

<p>I started out agreeing with Devlin, but I'm going to have to revise my opinion. I think the idea of continuous improvement should be built into the whole team, so that everyone takes responsibility for improving their surroundings, processes, and selves. And I think this directly feeds Quality, because the improvements we are making should be improving the quality of things, either as measured by the customer (product quality) or our coworkers, management, or even cleaning staff. So in a perfect world, building in improvements to improve Quality is part of the individual team members responsibilities. </p>

<p>However, I think there should still be someone who has overall responsibility for QA, either in the role of a manager or coach, to ensure that decisions are being made soundly on real data, ensure we aren't over-optimizing one portion of the business at the expense of another, and so on.</p>

<h2>Thoughts?</h2>
<p>A lot of people in the software world dislike Quality assurance, but I think this is because there are a lot of poor Quality Assurance efforts out there that never get past the manual test stage (and thus aren't actually assuring quality).</p>

<p>Regardless, if "It ain't broke" is the highest measure of quality in your company, it may be time to recalibrate expectations.</p><div class="item_footer"><p><small><a href="http://blogs.lessthandot.com/index.php/ITProfessionals/ITProcesses/quality-quality-assurance-and-how">Original post</a> blogged on <a href="http://lessthandot.com/">LessThanDot</a>.</small></p></div>]]></content:encoded>
								<comments>http://blogs.lessthandot.com/index.php/ITProfessionals/ITProcesses/quality-quality-assurance-and-how#comments</comments>
			<wfw:commentRss>http://blogs.lessthandot.com/index.php/ITProfessionals/?tempskin=_rss2&#38;disp=comments&#38;p=2067</wfw:commentRss>
		</item>
				<item>
			<title>Displaying .Net Build Warnings in TeamCity</title>
			<link>http://blogs.lessthandot.com/index.php/EnterpriseDev/application-lifecycle-management/displaying-net-build-warnings-in</link>
			<pubDate>Tue, 15 Jan 2013 13:41:00 +0000</pubDate>			<dc:creator>Eli Weinstock-Herman (tarwn)</dc:creator>
			<category domain="main">Application Lifecycle Management</category>			<guid isPermaLink="false">2023@http://blogs.lessthandot.com/</guid>
						<description>&lt;p&gt;I like it when I kick off a build and there aren&#039;t any warnings. Unfortunately I&#039;m forgetful and it&#039;s always easier to edit the code now then it is 3 months later (when I remember to look at the warnings). When I put together &lt;a href=&quot;http://wiki.lessthandot.com/index.php/Eli%27s_Continuous_Delivery_Project&quot; title=&quot;Wiki writeup on my Continuous Delivery project&quot;&gt;my sample Continuous Delivery project&lt;/a&gt;, I was using Jenkins, which provided plugins for capturing warnings. It was nice to have visual feedback when I added a new warning, see how many were outstanding, have a list of outstanding warnings available on demand, and when I had a few minutes and fixed some of them, positive feedback by watching the warning chart slowly go down.&lt;/p&gt;

&lt;p&gt;When I switch modes and work in &lt;a href=&quot;http://www.jetbrains.com/teamcity/&quot; title=&quot;TeamCity by JetBrains&quot;&gt;TeamCity&lt;/a&gt;, I miss having that information available, with no extra steps from me. Despite several searches, though, I was never able to find a plugin that duplicated that behavior I liked in the Jenkins plugin. Turns out that TeamCity makes it pretty easy to roll your own, with just a little bit of powershell and some built-in features.&lt;/p&gt;

&lt;p&gt;In this post I am going to cover capturing the warnings from an MSBuild build step, adding that warning count to the main dashboard, adding a statistics chart for the warning count over time, adding a condensed list to the end of the build log, adding the formatted list as a build artifact, and adding a custom report tab to report the warnings for each build. &lt;/p&gt;

&lt;p&gt;Because who doesn&#039;t need five different ways to see their warnings?&lt;/p&gt;

&lt;h2&gt;Capturing the Build Warnings&lt;/h2&gt;
&lt;p&gt;Since I am using MSBuild, the build warnings have a consistent pattern and MSBuild itself has an option to log out to a logger. We can add this attribute in either the build step or the Build Parameters. My preference is using the parameters of the build step in case I have multiple MSBuild calls in the build.&lt;/p&gt;

&lt;p&gt;Parameter to add to MSBuild: &lt;code class=&quot;codespan&quot;&gt;/l:FileLogger,Microsoft.Build.Engine;logfile=%BuildLogFilename%&lt;/code&gt;&lt;/p&gt;


&lt;div style=&quot;text-align: center; font-size: 90%; color: #666666; margin: .5em&quot;&gt;
&lt;img src=&quot;http://tiernok.com/LTDBlog/TeamCityBuildWarnings/MSBuildParameter.png&quot; alt=&quot;Adding the MS Build Parameter&quot; style=&quot;border: 1px solid #666666;&quot; /&gt;&lt;br /&gt;
Adding the MS Build Parameter
&lt;/div&gt;

&lt;p&gt;Each time MSBuild runs, it will log it&#039;s output to the specified file. We can use powershell to extract the warnings from the output, like so:&lt;/p&gt;

&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;powershell&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;powershell&quot; id=&quot;cb26744&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;Param(&lt;br /&gt;&amp;nbsp; &amp;nbsp; [parameter(Mandatory=$true)]&lt;br /&gt;&amp;nbsp; &amp;nbsp; [alias(&amp;quot;f&amp;quot;)]&lt;br /&gt;&amp;nbsp; &amp;nbsp; $FilePath&lt;br /&gt;)&lt;br /&gt;&amp;nbsp;&lt;br /&gt;$warnings = @(Get-Content -ErrorAction Stop $FilePath | &amp;nbsp; &amp;nbsp; &amp;nbsp; # Get the file content&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Where {$_ -match &#039;^.*warning CS.*$&#039;} | &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;# Extract lines that match warnings&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; %{ $_.trim() -replace &amp;quot;^\s*\d+&amp;gt;&amp;quot;,&amp;quot;&amp;quot; &amp;nbsp;} | &amp;nbsp; &amp;nbsp; &amp;nbsp;# Strip out any project number and caret prefixes&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; sort-object | Get-Unique -asString) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # remove duplicates by sorting and filtering for unique strings&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb49805&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Once we have the warnings extracted, we can move on to decide how we want them delivered. &lt;/p&gt;

&lt;p&gt;&lt;i&gt;Each section below will continue to add on to this script until it contains all the pieces we need to meet the display goals at the beginning.&lt;/i&gt;&lt;/p&gt;

&lt;h2&gt;Condensed Warning List in Build Log&lt;/h2&gt;
&lt;p&gt;The powershell script that is extracting warnings will need to run as a build step in the appropriate build configuration. This means that displaying a formatted list of warnings at the end of the build log is as simple as outputting that list from the powershell script we are building.&lt;/p&gt;

&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;powershell&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;powershell&quot; id=&quot;cb93272&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;$count = $warnings.Count&lt;br /&gt;Write-Host &amp;quot;MSBuild Warnings - $count warnings ===================================================&amp;quot;&lt;br /&gt;$warnings | % { Write-Host &amp;quot; * $_&amp;quot; }&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb47823&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will output a section at the bottom of the build log that contains our warnings, like so:&lt;/p&gt;

&lt;div style=&quot;text-align: center; font-size: 90%; color: #666666; margin: .5em&quot;&gt;
&lt;img src=&quot;http://tiernok.com/LTDBlog/TeamCityBuildWarnings/LogOutput.png&quot; alt=&quot;Warnings in the Bottom of a Build Log&quot; style=&quot;border: 1px solid #666666;&quot; /&gt;&lt;br /&gt;
Warnings in the Bottom of a Build Log
&lt;/div&gt;

&lt;p&gt;Which I suppose is fine, but doesn&#039;t really add that much value over the ones listed further up the log by MSBuild itself.&lt;/p&gt;

&lt;h2&gt;Condensed Warning List in Archived Text File&lt;/h2&gt;
&lt;p&gt;Now that I have formatted warnings, it&#039;s pretty easy to create a file with those warnings and archive it. First I&#039;ll update the script to take an output parameter and add some file output:&lt;/p&gt;

&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;powershell&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;powershell&quot; id=&quot;cb34858&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;Param(&lt;br /&gt;&amp;nbsp; &amp;nbsp; [parameter(Mandatory=$true)]&lt;br /&gt;&amp;nbsp; &amp;nbsp; [alias(&amp;quot;f&amp;quot;)]&lt;br /&gt;&amp;nbsp; &amp;nbsp; $FilePath,&lt;br /&gt;&amp;nbsp; &amp;nbsp; [parameter()]&lt;br /&gt;&amp;nbsp; &amp;nbsp; [alias(&amp;quot;o&amp;quot;)]&lt;br /&gt;&amp;nbsp; &amp;nbsp; $RawOutputPath,&lt;br /&gt;)&lt;br /&gt;&amp;nbsp;&lt;br /&gt;# ...&lt;br /&gt;&amp;nbsp;&lt;br /&gt;# file output&lt;br /&gt;if($RawOutputPath){&lt;br /&gt;&amp;nbsp; &amp;nbsp; $stream = [System.IO.StreamWriter] $RawOutputPath&lt;br /&gt;&amp;nbsp; &amp;nbsp; $stream.WriteLine(&amp;quot;Build Warnings&amp;quot;)&lt;br /&gt;&amp;nbsp; &amp;nbsp; $stream.WriteLine(&amp;quot;====================================&amp;quot;)&lt;br /&gt;&amp;nbsp; &amp;nbsp; $stream.WriteLine(&amp;quot;&amp;quot;)&lt;br /&gt;&amp;nbsp; &amp;nbsp; $warnings | % { $stream.WriteLine(&amp;quot; * $_&amp;quot;) }&lt;br /&gt;&amp;nbsp; &amp;nbsp; $stream.Close()&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb77757&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then I&#039;ll configure the project to capture that output file as an artifact:&lt;/p&gt;

&lt;div style=&quot;text-align: center; font-size: 90%; color: #666666; margin: .5em&quot;&gt;
&lt;img src=&quot;http://tiernok.com/LTDBlog/TeamCityBuildWarnings/ArtifactConfig_RawOutput.png&quot; alt=&quot;Artifact Configuration&quot; style=&quot;border: 1px solid #666666;&quot; /&gt;&lt;br /&gt;
Artifact Configuration
&lt;/div&gt;

&lt;p&gt;Et voila, the file shows up in my archived items:&lt;/p&gt;

&lt;div style=&quot;text-align: center; font-size: 90%; color: #666666; margin: .5em&quot;&gt;
&lt;img src=&quot;http://tiernok.com/LTDBlog/TeamCityBuildWarnings/Artifact_Display.png&quot; alt=&quot;List of archived items from a run&quot; style=&quot;border: 1px solid #666666;&quot; /&gt;&lt;br /&gt;
List of archived items from a run
&lt;/div&gt;

&lt;p&gt;And I have a clean, archived list of my warnings:&lt;/p&gt;

&lt;div style=&quot;text-align: center; font-size: 90%; color: #666666; margin: .5em&quot;&gt;
&lt;img src=&quot;http://tiernok.com/LTDBlog/TeamCityBuildWarnings/Artifact_File.png&quot; alt=&quot;Display of archived text file&quot; style=&quot;border: 1px solid #666666;&quot; /&gt;&lt;br /&gt;
Display of archived text file
&lt;/div&gt;

&lt;p&gt;But, really, we can do better.&lt;/p&gt;

&lt;h2&gt;Warning count in build status&lt;/h2&gt;
&lt;p&gt;Part of the goal was to be able to see the warning count change with no extra work, the best place I can think of to meet this is the final build status on each build.&lt;/p&gt;

&lt;p&gt;Before:&lt;/p&gt;

&lt;div style=&quot;text-align: center; font-size: 90%; color: #666666; margin: .5em&quot;&gt;
&lt;img src=&quot;http://tiernok.com/LTDBlog/TeamCityBuildWarnings/BuildStatusBefore.png&quot; alt=&quot;Build status on dashboard&quot; style=&quot;border: 1px solid #666666;&quot; /&gt;&lt;br /&gt;
Build status on dashboard
&lt;/div&gt;

&lt;p&gt;TeamCity provides support for &lt;a href=&quot;http://confluence.jetbrains.net/display/TCD7/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-ReportingBuildStatus&quot; title=&quot;TeamCity documentation for Build Script Interaction&quot;&gt;setting the build status from a build script&lt;/a&gt;. By adding some output to the powershell script, like so:&lt;/p&gt;

&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;powershell&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;powershell&quot; id=&quot;cb95240&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;#TeamCity output&lt;br /&gt;Write-Host &amp;quot;##teamcity[buildStatus text=&#039;{build.status.text}, Build warnings: $count&#039;]&amp;quot;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb45871&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Each successful build will also display the number of warnings that were captured.&lt;/p&gt;

&lt;div style=&quot;text-align: center; font-size: 90%; color: #666666; margin: .5em&quot;&gt;
&lt;img src=&quot;http://tiernok.com/LTDBlog/TeamCityBuildWarnings/BuildStatusAfter.png&quot; alt=&quot;Build status on dashboard, with warnings&quot; style=&quot;border: 1px solid #666666;&quot; /&gt;&lt;br /&gt;
Build status on dashboard, with warnings
&lt;/div&gt;

&lt;p&gt;Better, but what about historical values? And I still don&#039;t like that text file artifact.&lt;/p&gt;

&lt;h2&gt;Warning Count as a Custom Chart&lt;/h2&gt;
&lt;p&gt;TeamCity also provides the ability to add custom charts based on either built-in or &lt;a href=&quot;http://confluence.jetbrains.net/display/TCD7/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-ReportingBuildStatistics&quot; title=&quot;TeamCity documentation - reporting custom statistics&quot;&gt;custom statistics&lt;/a&gt;. Custom statistics are reported similar to the build status output above:&lt;/p&gt;

&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;powershell&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;powershell&quot; id=&quot;cb6924&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;Write-Host &amp;quot;##teamcity[buildStatisticValue key=&#039;buildWarnings&#039; value=&#039;$count&#039;]&amp;quot;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb74027&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Adding a &lt;a href=&quot;http://confluence.jetbrains.net/display/TCD7/Custom+Chart&quot; title=&quot;TeamCity documentation - Custom Statistics Charts&quot;&gt;custom chart&lt;/a&gt; requires us to dig into the configurations of TeamCity. I&#039;m going to add a chart that will be displayed for any build that provides the warning count number above, so I&#039;ll open the &lt;code class=&quot;codespan&quot;&gt;[teamCity data dir]/config/main-config.xml&lt;/code&gt; file and add the following section:&lt;/p&gt;

&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;powershell&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;powershell&quot; id=&quot;cb12402&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;&amp;lt;graph title=&amp;quot;Build Warnings&amp;quot; hideFilters=&amp;quot;showFailed&amp;quot; seriesTitle=&amp;quot;Warning&amp;quot; format=&amp;quot;&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;lt;valueType key=&amp;quot;buildWarnings&amp;quot; title=&amp;quot;Warnings&amp;quot;/&amp;gt;&lt;br /&gt;&amp;lt;/graph&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb35915&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will add a chart to the Statistics tab of the build. After a few builds this is what I have:&lt;/p&gt;

&lt;div style=&quot;text-align: center; font-size: 90%; color: #666666; margin: .5em&quot;&gt;
&lt;img src=&quot;http://tiernok.com/LTDBlog/TeamCityBuildWarnings/WarningChart.png&quot; alt=&quot;Build Warning Statistics&quot; style=&quot;border: 1px solid #666666;&quot; /&gt;&lt;br /&gt;
Build Warning Statistics
&lt;/div&gt;

&lt;p&gt;It probably would look better if I hadn&#039;t built with the same number of warnings each time, but you get the point. The mouse hover works just like the built-in charts, linking to the run status for the individual point.&lt;/p&gt;

&lt;p&gt;Ok, getting better, but I think we can take it one step further. &lt;/p&gt;

&lt;h2&gt;Adding a Custom Build Warnings Tab&lt;/h2&gt;
&lt;p&gt;So far we have improved methods of seeing the warning count and watching how it changes over time, but the actual list still leaves something to be desired. Luckily, TeamCity supports &lt;a href=&quot;http://confluence.jetbrains.net/display/TCD3/Including+Third-Party+Reports+in+the+Build+Results#IncludingThird-PartyReportsintheBuildResults-Tabs&quot; title=&quot;TeamCity documentation: Including third-party reports as the build-results tabs&quot;&gt;custom report tabs&lt;/a&gt; in the Build Results. This gives us an easily accessible place to put the warnings and, since it uses HTML, better formatting options than the text file.&lt;/p&gt;

&lt;p&gt;First I need to update the powershell script to output the HTML file. TeamCity will be picking up an entire folder for the report tab, so I could add some external CSS or image files for my report, but I&#039;ll leave that for another day.&lt;/p&gt;

&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;powershell&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;powershell&quot; id=&quot;cb10702&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;# html report output&lt;br /&gt;$check = Test-Path -PathType Container BuildWarningReport&lt;br /&gt;if($check -eq $false){&lt;br /&gt;&amp;nbsp; &amp;nbsp; New-Item &#039;BuildWarningReport&#039; -type Directory&lt;br /&gt;}&lt;br /&gt;$stream = [System.IO.StreamWriter] &amp;quot;BuildWarningReport/index.html&amp;quot;&lt;br /&gt;$stream.WriteLine(&amp;quot;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;$count Build Warnings&amp;lt;/h1&amp;gt;&amp;quot;)&lt;br /&gt;$stream.WriteLine(&amp;quot;&amp;lt;ul&amp;gt;&amp;quot;)&lt;br /&gt;$warnings | % { $stream.WriteLine(&amp;quot;&amp;lt;li&amp;gt;$_&amp;lt;/li&amp;gt;&amp;quot;) }&lt;br /&gt;$stream.WriteLine(&amp;quot;&amp;lt;/ul&amp;gt;&amp;quot;)&lt;br /&gt;$stream.WriteLine(&amp;quot;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&amp;quot;)&lt;br /&gt;$stream.Close()&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb41891&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I&#039;ve added HTML output to the script with a hardcoded output location that ensures the report directory exists before writing the index.html page. I&#039;ve hardcoded this value to reduce the amount of thinking &#039;ll need to do as I add this to other projects (keeps it consistent from output name to artifact setting to report tab configuration).&lt;/p&gt;

&lt;p&gt;The next step is to configure the project to capture the folder as an artifact:&lt;/p&gt;

&lt;div style=&quot;text-align: center; font-size: 90%; color: #666666; margin: .5em&quot;&gt;
&lt;img src=&quot;http://tiernok.com/LTDBlog/TeamCityBuildWarnings/ArtifactConfig_Report.png&quot; alt=&quot;Artifact configuration&quot; style=&quot;border: 1px solid #666666;&quot; /&gt;&lt;br /&gt;
Artifact configuration
&lt;/div&gt;

&lt;p&gt;Then the last step is to modify the TeamCity configuration to recognize that when I output archives like that, I want to treat them as a report. To do this I add the following chunk of XML to my &lt;code class=&quot;codespan&quot;&gt;[TeamCity data directory]/config/main-config.xml&lt;/code&gt; file (per the documentation link above):&lt;/p&gt;

&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;xml&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;xml&quot; id=&quot;cb47391&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;report-tab&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;title&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;Build Warnings&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;basePath&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;BuildWarningReport&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;startPage&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;index.html&amp;quot;&lt;/span&gt; &lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb11992&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And there we go, the custom report tab is available in the build results:&lt;/p&gt;

&lt;div style=&quot;text-align: center; font-size: 90%; color: #666666; margin: .5em&quot;&gt;
&lt;img src=&quot;http://tiernok.com/LTDBlog/TeamCityBuildWarnings/WarningsTab.png&quot; alt=&quot;Build Warnings tab in Run Results&quot; style=&quot;border: 1px solid #666666;&quot; /&gt;&lt;br /&gt;
Build Warnings tab in Run Results
&lt;/div&gt;

&lt;p&gt;Which takes us from no visibility into our warnings, to five different methods of viewing the information.&lt;/p&gt;

&lt;h2&gt;Wrap-up&lt;/h2&gt;
&lt;p&gt;From having to Ctrl+F through the build log all the way to plugin-level output in a few easy steps. After setting this up one time, the only pieces that needed to be repeated for additional builds are the addition of the /logger parameter for MSBuild and the powershell build step to extract the results, and capturing the artifact for the HTML page. All of the output is either built in to the script or applies to the whole server and is displayed whenever the statistics or archive are present in a build.&lt;/p&gt;

&lt;p&gt;Here is the finished script:&lt;/p&gt;
&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;powershell&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;powershell&quot; id=&quot;cb20504&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;Param(&lt;br /&gt;&amp;nbsp; &amp;nbsp; [parameter(Mandatory=$true)]&lt;br /&gt;&amp;nbsp; &amp;nbsp; [alias(&amp;quot;f&amp;quot;)]&lt;br /&gt;&amp;nbsp; &amp;nbsp; $FilePath,&lt;br /&gt;&amp;nbsp; &amp;nbsp; [parameter()]&lt;br /&gt;&amp;nbsp; &amp;nbsp; [alias(&amp;quot;o&amp;quot;)]&lt;br /&gt;&amp;nbsp; &amp;nbsp; $RawOutputPath&lt;br /&gt;)&lt;br /&gt;&amp;nbsp;&lt;br /&gt;$warnings = @(Get-Content -ErrorAction Stop $FilePath | &amp;nbsp; &amp;nbsp; &amp;nbsp; # Get the file content&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Where {$_ -match &#039;^.*warning CS.*$&#039;} | &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;# Extract lines that match warnings&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; %{ $_.trim() -replace &amp;quot;^\s*\d+&amp;gt;&amp;quot;,&amp;quot;&amp;quot; &amp;nbsp;} | &amp;nbsp; &amp;nbsp; &amp;nbsp;# Strip out any project number and caret prefixes&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; sort-object | Get-Unique -asString) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # remove duplicates by sorting and filtering for unique strings&lt;br /&gt;&amp;nbsp;&lt;br /&gt;$count = $warnings.Count&lt;br /&gt;&amp;nbsp;&lt;br /&gt;# raw output&lt;br /&gt;Write-Host &amp;quot;MSBuild Warnings - $count warnings ===================================================&amp;quot;&lt;br /&gt;$warnings | % { Write-Host &amp;quot; * $_&amp;quot; }&lt;br /&gt;&amp;nbsp;&lt;br /&gt;#TeamCity output&lt;br /&gt;Write-Host &amp;quot;##teamcity[buildStatus text=&#039;{build.status.text}, Build warnings: $count&#039;]&amp;quot;&lt;br /&gt;Write-Host &amp;quot;##teamcity[buildStatisticValue key=&#039;buildWarnings&#039; value=&#039;$count&#039;]&amp;quot;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;# file output&lt;br /&gt;if($RawOutputPath){&lt;br /&gt;&amp;nbsp; &amp;nbsp; $stream = [System.IO.StreamWriter] $RawOutputPath&lt;br /&gt;&amp;nbsp; &amp;nbsp; $stream.WriteLine(&amp;quot;Build Warnings&amp;quot;)&lt;br /&gt;&amp;nbsp; &amp;nbsp; $stream.WriteLine(&amp;quot;====================================&amp;quot;)&lt;br /&gt;&amp;nbsp; &amp;nbsp; $stream.WriteLine(&amp;quot;&amp;quot;)&lt;br /&gt;&amp;nbsp; &amp;nbsp; $warnings | % { $stream.WriteLine(&amp;quot; * $_&amp;quot;) }&lt;br /&gt;&amp;nbsp; &amp;nbsp; $stream.Close()&lt;br /&gt;}&lt;br /&gt;&amp;nbsp;&lt;br /&gt;# html report output&lt;br /&gt;$check = Test-Path -PathType Container BuildWarningReport&lt;br /&gt;if($check -eq $false){&lt;br /&gt;&amp;nbsp; &amp;nbsp; New-Item &#039;BuildWarningReport&#039; -type Directory&lt;br /&gt;}&lt;br /&gt;$stream = [System.IO.StreamWriter] &amp;quot;BuildWarningReport/index.html&amp;quot;&lt;br /&gt;$stream.WriteLine(&amp;quot;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;$count Build Warnings&amp;lt;/h1&amp;gt;&amp;quot;)&lt;br /&gt;$stream.WriteLine(&amp;quot;&amp;lt;ul&amp;gt;&amp;quot;)&lt;br /&gt;$warnings | % { $stream.WriteLine(&amp;quot;&amp;lt;li&amp;gt;$_&amp;lt;/li&amp;gt;&amp;quot;) }&lt;br /&gt;$stream.WriteLine(&amp;quot;&amp;lt;/ul&amp;gt;&amp;quot;)&lt;br /&gt;$stream.WriteLine(&amp;quot;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&amp;quot;)&lt;br /&gt;$stream.Close()&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb66287&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To recap, we started with some warning messages randomly scattered across the build log. We ended with the warning count automatically showing in the build status on the dashboard, a nice chart of the number over time, and three different ways to view the detailed list. I hope this proves useful to others as well, now I have to go and fix the sample warnings I added before I forget about them. &lt;img src=&quot;http://blogs.lessthandot.com/rsc/smilies/icon_smile.gif&quot; title=&quot;:)&quot; alt=&quot;:)&quot; class=&quot;middle&quot; width=&quot;15&quot; height=&quot;15&quot; /&gt;&lt;/p&gt;&lt;div class=&quot;item_footer&quot;&gt;&lt;p&gt;&lt;small&gt;&lt;a href=&quot;http://blogs.lessthandot.com/index.php/EnterpriseDev/application-lifecycle-management/displaying-net-build-warnings-in&quot;&gt;Original post&lt;/a&gt; blogged on &lt;a href=&quot;http://lessthandot.com/&quot;&gt;LessThanDot&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;/div&gt;</description>
			<content:encoded><![CDATA[<p>I like it when I kick off a build and there aren't any warnings. Unfortunately I'm forgetful and it's always easier to edit the code now then it is 3 months later (when I remember to look at the warnings). When I put together <a href="http://wiki.lessthandot.com/index.php/Eli%27s_Continuous_Delivery_Project" title="Wiki writeup on my Continuous Delivery project">my sample Continuous Delivery project</a>, I was using Jenkins, which provided plugins for capturing warnings. It was nice to have visual feedback when I added a new warning, see how many were outstanding, have a list of outstanding warnings available on demand, and when I had a few minutes and fixed some of them, positive feedback by watching the warning chart slowly go down.</p>

<p>When I switch modes and work in <a href="http://www.jetbrains.com/teamcity/" title="TeamCity by JetBrains">TeamCity</a>, I miss having that information available, with no extra steps from me. Despite several searches, though, I was never able to find a plugin that duplicated that behavior I liked in the Jenkins plugin. Turns out that TeamCity makes it pretty easy to roll your own, with just a little bit of powershell and some built-in features.</p>

<p>In this post I am going to cover capturing the warnings from an MSBuild build step, adding that warning count to the main dashboard, adding a statistics chart for the warning count over time, adding a condensed list to the end of the build log, adding the formatted list as a build artifact, and adding a custom report tab to report the warnings for each build. </p>

<p>Because who doesn't need five different ways to see their warnings?</p>

<h2>Capturing the Build Warnings</h2>
<p>Since I am using MSBuild, the build warnings have a consistent pattern and MSBuild itself has an option to log out to a logger. We can add this attribute in either the build step or the Build Parameters. My preference is using the parameters of the build step in case I have multiple MSBuild calls in the build.</p>

<p>Parameter to add to MSBuild: <code class="codespan">/l:FileLogger,Microsoft.Build.Engine;logfile=%BuildLogFilename%</code></p>


<div style="text-align: center; font-size: 90%; color: #666666; margin: .5em">
<img src="http://tiernok.com/LTDBlog/TeamCityBuildWarnings/MSBuildParameter.png" alt="Adding the MS Build Parameter" style="border: 1px solid #666666;" /><br />
Adding the MS Build Parameter
</div>

<p>Each time MSBuild runs, it will log it's output to the specified file. We can use powershell to extract the warnings from the output, like so:</p>

<div class="codebox"><div class="codeheader"><span>powershell</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb67078'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb67078','cb41246'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="powershell" id="cb67078" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1">Param(</li><li style="" class="li2">&nbsp; &nbsp; [parameter(Mandatory=$true)]</li><li style="" class="li1">&nbsp; &nbsp; [alias(&quot;f&quot;)]</li><li style="" class="li2">&nbsp; &nbsp; $FilePath</li><li style="" class="li1">)</li><li style="" class="li2">&nbsp;</li><li style="" class="li1">$warnings = @(Get-Content -ErrorAction Stop $FilePath | &nbsp; &nbsp; &nbsp; # Get the file content</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Where {$_ -match '^.*warning CS.*$'} | &nbsp; &nbsp; &nbsp; &nbsp;# Extract lines that match warnings</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; %{ $_.trim() -replace &quot;^\s*\d+&gt;&quot;,&quot;&quot; &nbsp;} | &nbsp; &nbsp; &nbsp;# Strip out any project number and caret prefixes</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sort-object | Get-Unique -asString) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # remove duplicates by sorting and filtering for unique strings</li></ol></div><div id="cb41246" style="display: none; color: red;"></div></div></div>

<p>Once we have the warnings extracted, we can move on to decide how we want them delivered. </p>

<p><i>Each section below will continue to add on to this script until it contains all the pieces we need to meet the display goals at the beginning.</i></p>

<h2>Condensed Warning List in Build Log</h2>
<p>The powershell script that is extracting warnings will need to run as a build step in the appropriate build configuration. This means that displaying a formatted list of warnings at the end of the build log is as simple as outputting that list from the powershell script we are building.</p>

<div class="codebox"><div class="codeheader"><span>powershell</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb20903'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb20903','cb2321'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="powershell" id="cb20903" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1">$count = $warnings.Count</li><li style="" class="li2">Write-Host &quot;MSBuild Warnings - $count warnings ===================================================&quot;</li><li style="" class="li1">$warnings | % { Write-Host &quot; * $_&quot; }</li></ol></div><div id="cb2321" style="display: none; color: red;"></div></div></div>

<p>This will output a section at the bottom of the build log that contains our warnings, like so:</p>

<div style="text-align: center; font-size: 90%; color: #666666; margin: .5em">
<img src="http://tiernok.com/LTDBlog/TeamCityBuildWarnings/LogOutput.png" alt="Warnings in the Bottom of a Build Log" style="border: 1px solid #666666;" /><br />
Warnings in the Bottom of a Build Log
</div>

<p>Which I suppose is fine, but doesn't really add that much value over the ones listed further up the log by MSBuild itself.</p>

<h2>Condensed Warning List in Archived Text File</h2>
<p>Now that I have formatted warnings, it's pretty easy to create a file with those warnings and archive it. First I'll update the script to take an output parameter and add some file output:</p>

<div class="codebox"><div class="codeheader"><span>powershell</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb32223'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb32223','cb54419'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="powershell" id="cb32223" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1">Param(</li><li style="" class="li2">&nbsp; &nbsp; [parameter(Mandatory=$true)]</li><li style="" class="li1">&nbsp; &nbsp; [alias(&quot;f&quot;)]</li><li style="" class="li2">&nbsp; &nbsp; $FilePath,</li><li style="" class="li1">&nbsp; &nbsp; [parameter()]</li><li style="" class="li2">&nbsp; &nbsp; [alias(&quot;o&quot;)]</li><li style="" class="li1">&nbsp; &nbsp; $RawOutputPath,</li><li style="" class="li2">)</li><li style="" class="li1">&nbsp;</li><li style="" class="li2"># ...</li><li style="" class="li1">&nbsp;</li><li style="" class="li2"># file output</li><li style="" class="li1">if($RawOutputPath){</li><li style="" class="li2">&nbsp; &nbsp; $stream = [System.IO.StreamWriter] $RawOutputPath</li><li style="" class="li1">&nbsp; &nbsp; $stream.WriteLine(&quot;Build Warnings&quot;)</li><li style="" class="li2">&nbsp; &nbsp; $stream.WriteLine(&quot;====================================&quot;)</li><li style="" class="li1">&nbsp; &nbsp; $stream.WriteLine(&quot;&quot;)</li><li style="" class="li2">&nbsp; &nbsp; $warnings | % { $stream.WriteLine(&quot; * $_&quot;) }</li><li style="" class="li1">&nbsp; &nbsp; $stream.Close()</li><li style="" class="li2">}</li></ol></div><div id="cb54419" style="display: none; color: red;"></div></div></div>

<p>Then I'll configure the project to capture that output file as an artifact:</p>

<div style="text-align: center; font-size: 90%; color: #666666; margin: .5em">
<img src="http://tiernok.com/LTDBlog/TeamCityBuildWarnings/ArtifactConfig_RawOutput.png" alt="Artifact Configuration" style="border: 1px solid #666666;" /><br />
Artifact Configuration
</div>

<p>Et voila, the file shows up in my archived items:</p>

<div style="text-align: center; font-size: 90%; color: #666666; margin: .5em">
<img src="http://tiernok.com/LTDBlog/TeamCityBuildWarnings/Artifact_Display.png" alt="List of archived items from a run" style="border: 1px solid #666666;" /><br />
List of archived items from a run
</div>

<p>And I have a clean, archived list of my warnings:</p>

<div style="text-align: center; font-size: 90%; color: #666666; margin: .5em">
<img src="http://tiernok.com/LTDBlog/TeamCityBuildWarnings/Artifact_File.png" alt="Display of archived text file" style="border: 1px solid #666666;" /><br />
Display of archived text file
</div>

<p>But, really, we can do better.</p>

<h2>Warning count in build status</h2>
<p>Part of the goal was to be able to see the warning count change with no extra work, the best place I can think of to meet this is the final build status on each build.</p>

<p>Before:</p>

<div style="text-align: center; font-size: 90%; color: #666666; margin: .5em">
<img src="http://tiernok.com/LTDBlog/TeamCityBuildWarnings/BuildStatusBefore.png" alt="Build status on dashboard" style="border: 1px solid #666666;" /><br />
Build status on dashboard
</div>

<p>TeamCity provides support for <a href="http://confluence.jetbrains.net/display/TCD7/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-ReportingBuildStatus" title="TeamCity documentation for Build Script Interaction">setting the build status from a build script</a>. By adding some output to the powershell script, like so:</p>

<div class="codebox"><div class="codeheader"><span>powershell</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb27531'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb27531','cb6255'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="powershell" id="cb27531" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1">#TeamCity output</li><li style="" class="li2">Write-Host &quot;##teamcity[buildStatus text='{build.status.text}, Build warnings: $count']&quot;</li></ol></div><div id="cb6255" style="display: none; color: red;"></div></div></div>

<p>Each successful build will also display the number of warnings that were captured.</p>

<div style="text-align: center; font-size: 90%; color: #666666; margin: .5em">
<img src="http://tiernok.com/LTDBlog/TeamCityBuildWarnings/BuildStatusAfter.png" alt="Build status on dashboard, with warnings" style="border: 1px solid #666666;" /><br />
Build status on dashboard, with warnings
</div>

<p>Better, but what about historical values? And I still don't like that text file artifact.</p>

<h2>Warning Count as a Custom Chart</h2>
<p>TeamCity also provides the ability to add custom charts based on either built-in or <a href="http://confluence.jetbrains.net/display/TCD7/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-ReportingBuildStatistics" title="TeamCity documentation - reporting custom statistics">custom statistics</a>. Custom statistics are reported similar to the build status output above:</p>

<div class="codebox"><div class="codeheader"><span>powershell</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb22733'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb22733','cb34867'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="powershell" id="cb22733" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1">Write-Host &quot;##teamcity[buildStatisticValue key='buildWarnings' value='$count']&quot;</li></ol></div><div id="cb34867" style="display: none; color: red;"></div></div></div>

<p>Adding a <a href="http://confluence.jetbrains.net/display/TCD7/Custom+Chart" title="TeamCity documentation - Custom Statistics Charts">custom chart</a> requires us to dig into the configurations of TeamCity. I'm going to add a chart that will be displayed for any build that provides the warning count number above, so I'll open the <code class="codespan">[teamCity data dir]/config/main-config.xml</code> file and add the following section:</p>

<div class="codebox"><div class="codeheader"><span>powershell</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb27795'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb27795','cb5714'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="powershell" id="cb27795" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1">&lt;graph title=&quot;Build Warnings&quot; hideFilters=&quot;showFailed&quot; seriesTitle=&quot;Warning&quot; format=&quot;&quot;&gt;</li><li style="" class="li2">&nbsp; &nbsp; &lt;valueType key=&quot;buildWarnings&quot; title=&quot;Warnings&quot;/&gt;</li><li style="" class="li1">&lt;/graph&gt;</li></ol></div><div id="cb5714" style="display: none; color: red;"></div></div></div>

<p>This will add a chart to the Statistics tab of the build. After a few builds this is what I have:</p>

<div style="text-align: center; font-size: 90%; color: #666666; margin: .5em">
<img src="http://tiernok.com/LTDBlog/TeamCityBuildWarnings/WarningChart.png" alt="Build Warning Statistics" style="border: 1px solid #666666;" /><br />
Build Warning Statistics
</div>

<p>It probably would look better if I hadn't built with the same number of warnings each time, but you get the point. The mouse hover works just like the built-in charts, linking to the run status for the individual point.</p>

<p>Ok, getting better, but I think we can take it one step further. </p>

<h2>Adding a Custom Build Warnings Tab</h2>
<p>So far we have improved methods of seeing the warning count and watching how it changes over time, but the actual list still leaves something to be desired. Luckily, TeamCity supports <a href="http://confluence.jetbrains.net/display/TCD3/Including+Third-Party+Reports+in+the+Build+Results#IncludingThird-PartyReportsintheBuildResults-Tabs" title="TeamCity documentation: Including third-party reports as the build-results tabs">custom report tabs</a> in the Build Results. This gives us an easily accessible place to put the warnings and, since it uses HTML, better formatting options than the text file.</p>

<p>First I need to update the powershell script to output the HTML file. TeamCity will be picking up an entire folder for the report tab, so I could add some external CSS or image files for my report, but I'll leave that for another day.</p>

<div class="codebox"><div class="codeheader"><span>powershell</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb23304'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb23304','cb4114'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="powershell" id="cb23304" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1"># html report output</li><li style="" class="li2">$check = Test-Path -PathType Container BuildWarningReport</li><li style="" class="li1">if($check -eq $false){</li><li style="" class="li2">&nbsp; &nbsp; New-Item 'BuildWarningReport' -type Directory</li><li style="" class="li1">}</li><li style="" class="li2">$stream = [System.IO.StreamWriter] &quot;BuildWarningReport/index.html&quot;</li><li style="" class="li1">$stream.WriteLine(&quot;&lt;html&gt;&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;h1&gt;$count Build Warnings&lt;/h1&gt;&quot;)</li><li style="" class="li2">$stream.WriteLine(&quot;&lt;ul&gt;&quot;)</li><li style="" class="li1">$warnings | % { $stream.WriteLine(&quot;&lt;li&gt;$_&lt;/li&gt;&quot;) }</li><li style="" class="li2">$stream.WriteLine(&quot;&lt;/ul&gt;&quot;)</li><li style="" class="li1">$stream.WriteLine(&quot;&lt;/body&gt;&lt;/html&gt;&quot;)</li><li style="" class="li2">$stream.Close()</li></ol></div><div id="cb4114" style="display: none; color: red;"></div></div></div>

<p>I've added HTML output to the script with a hardcoded output location that ensures the report directory exists before writing the index.html page. I've hardcoded this value to reduce the amount of thinking 'll need to do as I add this to other projects (keeps it consistent from output name to artifact setting to report tab configuration).</p>

<p>The next step is to configure the project to capture the folder as an artifact:</p>

<div style="text-align: center; font-size: 90%; color: #666666; margin: .5em">
<img src="http://tiernok.com/LTDBlog/TeamCityBuildWarnings/ArtifactConfig_Report.png" alt="Artifact configuration" style="border: 1px solid #666666;" /><br />
Artifact configuration
</div>

<p>Then the last step is to modify the TeamCity configuration to recognize that when I output archives like that, I want to treat them as a report. To do this I add the following chunk of XML to my <code class="codespan">[TeamCity data directory]/config/main-config.xml</code> file (per the documentation link above):</p>

<div class="codebox"><div class="codeheader"><span>xml</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb46329'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb46329','cb74417'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="xml" id="cb46329" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;report-tab</span> <span style="color: #000066;">title</span>=<span style="color: #ff0000;">&quot;Build Warnings&quot;</span> <span style="color: #000066;">basePath</span>=<span style="color: #ff0000;">&quot;BuildWarningReport&quot;</span> <span style="color: #000066;">startPage</span>=<span style="color: #ff0000;">&quot;index.html&quot;</span> <span style="font-weight: bold; color: black;">/&gt;</span></span></li></ol></div><div id="cb74417" style="display: none; color: red;"></div></div></div>

<p>And there we go, the custom report tab is available in the build results:</p>

<div style="text-align: center; font-size: 90%; color: #666666; margin: .5em">
<img src="http://tiernok.com/LTDBlog/TeamCityBuildWarnings/WarningsTab.png" alt="Build Warnings tab in Run Results" style="border: 1px solid #666666;" /><br />
Build Warnings tab in Run Results
</div>

<p>Which takes us from no visibility into our warnings, to five different methods of viewing the information.</p>

<h2>Wrap-up</h2>
<p>From having to Ctrl+F through the build log all the way to plugin-level output in a few easy steps. After setting this up one time, the only pieces that needed to be repeated for additional builds are the addition of the /logger parameter for MSBuild and the powershell build step to extract the results, and capturing the artifact for the HTML page. All of the output is either built in to the script or applies to the whole server and is displayed whenever the statistics or archive are present in a build.</p>

<p>Here is the finished script:</p>
<div class="codebox"><div class="codeheader"><span>powershell</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb82208'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb82208','cb42017'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="powershell" id="cb82208" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1">Param(</li><li style="" class="li2">&nbsp; &nbsp; [parameter(Mandatory=$true)]</li><li style="" class="li1">&nbsp; &nbsp; [alias(&quot;f&quot;)]</li><li style="" class="li2">&nbsp; &nbsp; $FilePath,</li><li style="" class="li1">&nbsp; &nbsp; [parameter()]</li><li style="" class="li2">&nbsp; &nbsp; [alias(&quot;o&quot;)]</li><li style="" class="li1">&nbsp; &nbsp; $RawOutputPath</li><li style="" class="li2">)</li><li style="" class="li1">&nbsp;</li><li style="" class="li2">$warnings = @(Get-Content -ErrorAction Stop $FilePath | &nbsp; &nbsp; &nbsp; # Get the file content</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Where {$_ -match '^.*warning CS.*$'} | &nbsp; &nbsp; &nbsp; &nbsp;# Extract lines that match warnings</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; %{ $_.trim() -replace &quot;^\s*\d+&gt;&quot;,&quot;&quot; &nbsp;} | &nbsp; &nbsp; &nbsp;# Strip out any project number and caret prefixes</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sort-object | Get-Unique -asString) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # remove duplicates by sorting and filtering for unique strings</li><li style="" class="li2">&nbsp;</li><li style="" class="li1">$count = $warnings.Count</li><li style="" class="li2">&nbsp;</li><li style="" class="li1"># raw output</li><li style="" class="li2">Write-Host &quot;MSBuild Warnings - $count warnings ===================================================&quot;</li><li style="" class="li1">$warnings | % { Write-Host &quot; * $_&quot; }</li><li style="" class="li2">&nbsp;</li><li style="" class="li1">#TeamCity output</li><li style="" class="li2">Write-Host &quot;##teamcity[buildStatus text='{build.status.text}, Build warnings: $count']&quot;</li><li style="" class="li1">Write-Host &quot;##teamcity[buildStatisticValue key='buildWarnings' value='$count']&quot;</li><li style="" class="li2">&nbsp;</li><li style="" class="li1"># file output</li><li style="" class="li2">if($RawOutputPath){</li><li style="" class="li1">&nbsp; &nbsp; $stream = [System.IO.StreamWriter] $RawOutputPath</li><li style="" class="li2">&nbsp; &nbsp; $stream.WriteLine(&quot;Build Warnings&quot;)</li><li style="" class="li1">&nbsp; &nbsp; $stream.WriteLine(&quot;====================================&quot;)</li><li style="" class="li2">&nbsp; &nbsp; $stream.WriteLine(&quot;&quot;)</li><li style="" class="li1">&nbsp; &nbsp; $warnings | % { $stream.WriteLine(&quot; * $_&quot;) }</li><li style="" class="li2">&nbsp; &nbsp; $stream.Close()</li><li style="" class="li1">}</li><li style="" class="li2">&nbsp;</li><li style="" class="li1"># html report output</li><li style="" class="li2">$check = Test-Path -PathType Container BuildWarningReport</li><li style="" class="li1">if($check -eq $false){</li><li style="" class="li2">&nbsp; &nbsp; New-Item 'BuildWarningReport' -type Directory</li><li style="" class="li1">}</li><li style="" class="li2">$stream = [System.IO.StreamWriter] &quot;BuildWarningReport/index.html&quot;</li><li style="" class="li1">$stream.WriteLine(&quot;&lt;html&gt;&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;h1&gt;$count Build Warnings&lt;/h1&gt;&quot;)</li><li style="" class="li2">$stream.WriteLine(&quot;&lt;ul&gt;&quot;)</li><li style="" class="li1">$warnings | % { $stream.WriteLine(&quot;&lt;li&gt;$_&lt;/li&gt;&quot;) }</li><li style="" class="li2">$stream.WriteLine(&quot;&lt;/ul&gt;&quot;)</li><li style="" class="li1">$stream.WriteLine(&quot;&lt;/body&gt;&lt;/html&gt;&quot;)</li><li style="" class="li2">$stream.Close()</li></ol></div><div id="cb42017" style="display: none; color: red;"></div></div></div>

<p>To recap, we started with some warning messages randomly scattered across the build log. We ended with the warning count automatically showing in the build status on the dashboard, a nice chart of the number over time, and three different ways to view the detailed list. I hope this proves useful to others as well, now I have to go and fix the sample warnings I added before I forget about them. <img src="http://blogs.lessthandot.com/rsc/smilies/icon_smile.gif" title=":)" alt=":)" class="middle" width="15" height="15" /></p><div class="item_footer"><p><small><a href="http://blogs.lessthandot.com/index.php/EnterpriseDev/application-lifecycle-management/displaying-net-build-warnings-in">Original post</a> blogged on <a href="http://lessthandot.com/">LessThanDot</a>.</small></p></div>]]></content:encoded>
								<comments>http://blogs.lessthandot.com/index.php/EnterpriseDev/application-lifecycle-management/displaying-net-build-warnings-in#comments</comments>
			<wfw:commentRss>http://blogs.lessthandot.com/index.php/EnterpriseDev/?tempskin=_rss2&#38;disp=comments&#38;p=2023</wfw:commentRss>
		</item>
				<item>
			<title>Testing the Not-So-Testable HttpWebResponse</title>
			<link>http://blogs.lessthandot.com/index.php/DesktopDev/MSTech/CSharp/testing-httpwebresponse</link>
			<pubDate>Mon, 10 Dec 2012 14:56:00 +0000</pubDate>			<dc:creator>Eli Weinstock-Herman (tarwn)</dc:creator>
			<category domain="alt">Microsoft Technologies</category>
<category domain="main">C#</category>			<guid isPermaLink="false">1932@http://blogs.lessthandot.com/</guid>
						<description>&lt;p&gt;Recently I was working on a library to consume a REST API without exposing any of the specifics to the rest of the application. Implementing a common interface and set of custom exceptions was easy enough, but exercising the internal logic was going to be tough. &lt;/p&gt;

&lt;p&gt;While I could use the live REST API to verify the general logic worked, I had limited options when it came to the full range of HTTP responses and communication failures. Add in the impact those live API calls would have on my build process performance, the occasional failures of my build due the imperfections of talking to a live service, and the overhead of maintaining separation between my test and live data in that service...what I really had on my hands was the beginning of years of random, painful maintenance.&lt;/p&gt;

&lt;p&gt;If only I could mock WebRequest and have it return carefully crafted responses to test my code with, all without ever touching the real network.&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/system.net.httpwebresponse.aspx&quot; title=&quot;HttpWebResponse on MSDN&quot;&gt;MSDN&lt;/a&gt;: You should never directly create an instance of the HttpWebResponse class.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Hmm, ok, maybe not.&lt;/p&gt;

&lt;p&gt;Despite having done this search before, this time around I uncovered a couple posts that helped me find a solution to this whole mess. Although not before I left some helpful feedback on the MSDN page about the difference between opinion and documentation.&lt;/p&gt;

&lt;p&gt;Yep, making friends.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;The source code for this post is located on github, with the sample service implementation and test projects: &lt;a href=&quot;https://github.com/tarwn/TestableHttpWebResponse&quot; title=&quot;tarwn/TestableHttpWebResponse on github&quot;&gt;tarwn/TestableHttpWebResponse&lt;/a&gt;&lt;/i&gt;&lt;/p&gt;

&lt;h2&gt;Let&#039;s Start with the Tests&lt;/h2&gt;
&lt;p&gt;I&#039;ve created a sample service implementation with two API call implementations. Each one builds a WebRequest, executes it, and analyzes the response. A retry policy wraps around the request execution, evaluating exceptions to determine whether to retry or map them to a local exception type to be rethrown.&lt;/p&gt;

&lt;p&gt;Here is an example of one of those calls and the synchronous method it uses internally:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;TestableHttpWebResponse.Sample/SampleService.cs&lt;/b&gt;&lt;/p&gt;
&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;csharp&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;csharp&quot; id=&quot;cb45764&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;&lt;span style=&quot;color: #0600FF;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #FF0000;&quot;&gt;class&lt;/span&gt; SampleService&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #008080; font-style: italic;&quot;&gt;// ...&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF;&quot;&gt;public&lt;/span&gt; ServiceResponse ListRemoteStuff&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;string&lt;/span&gt; operation&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; var uri = &lt;a href=&quot;http://www.google.com/search?q=new+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;new&lt;/span&gt;&lt;/a&gt; Uri&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;_baseUri, operation&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; var request = WebRequest.&lt;span style=&quot;color: #0000FF;&quot;&gt;Create&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;uri&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; request.&lt;span style=&quot;color: #0000FF;&quot;&gt;Headers&lt;/span&gt;.&lt;span style=&quot;color: #0000FF;&quot;&gt;Add&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;version&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;123-awesome&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF;&quot;&gt;return&lt;/span&gt; SendRequest&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;request&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #008080; font-style: italic;&quot;&gt;// ...&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF;&quot;&gt;private&lt;/span&gt; ServiceResponse SendRequest&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;WebRequest request&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF;&quot;&gt;return&lt;/span&gt; _retryPolicy.&lt;span style=&quot;color: #0000FF;&quot;&gt;ExecuteAction&lt;/span&gt;&amp;lt;ServiceResponse&amp;gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt; =&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF;&quot;&gt;try&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; var response = &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;HttpWebResponse&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;request.&lt;span style=&quot;color: #0000FF;&quot;&gt;GetResponse&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; var reader = &lt;a href=&quot;http://www.google.com/search?q=new+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;new&lt;/span&gt;&lt;/a&gt; StreamReader&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;response.&lt;span style=&quot;color: #0000FF;&quot;&gt;GetResponseStream&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; var message = reader.&lt;span style=&quot;color: #0000FF;&quot;&gt;ReadToEnd&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF;&quot;&gt;return&lt;/span&gt; &lt;a href=&quot;http://www.google.com/search?q=new+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;new&lt;/span&gt;&lt;/a&gt; ServiceResponse&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt; IsSuccess = &lt;span style=&quot;color: #0600FF;&quot;&gt;true&lt;/span&gt;, Message = message &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF;&quot;&gt;catch&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;WebException we&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF;&quot;&gt;throw&lt;/span&gt; MappedException&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;we&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #008080; font-style: italic;&quot;&gt;// ...&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb63785&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Testing a method like this typically requires an integration test against the live service. With the provided TestableHttpWebResponse and TestableWebRequest, however, we can set up an expected request and response and verify the service reacts appropriately.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;1: Register the TestableWebRequestCreateFactory&lt;/b&gt;&lt;br /&gt;
WebRequest.Create(&lt;i&gt;uri&lt;/i&gt;) uses a factory to produce the relevant WebRequest instance of a Uri, based on the prefix. So first things first, lets register a new prefix and a factory to serve up requests:&lt;/p&gt;

&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;csharp&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;csharp&quot; id=&quot;cb43433&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#91;&lt;/span&gt;TestFixtureSetUp&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#93;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #0600FF;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #0600FF;&quot;&gt;void&lt;/span&gt; TestFixtureSetup&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; WebRequest.&lt;span style=&quot;color: #0000FF;&quot;&gt;RegisterPrefix&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;test&amp;quot;&lt;/span&gt;, TestableWebRequestCreateFactory.&lt;span style=&quot;color: #0000FF;&quot;&gt;GetFactory&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb43029&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;TestableWebRequestCreateFactory.GetFactory() exposes a singleton that can be referenced from any of the tests in this class. When the WebRequest object receives a Uri starting with &quot;test://&quot;, it will call the associated factory, giving us the opportunity to respond with a Request object of our choosing.&lt;/p&gt;

&lt;p&gt;A common base URI will prove helpful as we write the tests:&lt;/p&gt;

&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;csharp&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;csharp&quot; id=&quot;cb4308&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;&lt;span style=&quot;color: #0600FF;&quot;&gt;public&lt;/span&gt; Uri BaseUri &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt; get &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt; &lt;span style=&quot;color: #0600FF;&quot;&gt;return&lt;/span&gt; &lt;a href=&quot;http://www.google.com/search?q=new+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;new&lt;/span&gt;&lt;/a&gt; Uri&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;test://mydomain.com/api/&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb33793&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;b&gt;2: Building a Test&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;The easiest test to start with is one that will test the &quot;happy path&quot; where our API call receives a 200 Success response. &lt;/p&gt;

&lt;p&gt;First we need to set up the request:&lt;/p&gt;

&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;csharp&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;csharp&quot; id=&quot;cb14280&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;var operation = &lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;ListOfStuff&amp;quot;&lt;/span&gt;;&lt;br /&gt;var expectedRequest = &lt;a href=&quot;http://www.google.com/search?q=new+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;new&lt;/span&gt;&lt;/a&gt; TestableWebRequest&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;a href=&quot;http://www.google.com/search?q=new+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;new&lt;/span&gt;&lt;/a&gt; Uri&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;BaseUri, operation&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb65172&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Next we need to set up the response the request will return when it is executed:&lt;/p&gt;

&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;csharp&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;csharp&quot; id=&quot;cb35401&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;expectedRequest.&lt;span style=&quot;color: #0000FF;&quot;&gt;EnqueueResponse&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;HttpStatusCode.&lt;span style=&quot;color: #0000FF;&quot;&gt;OK&lt;/span&gt;, &lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;Success&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;Even More Success&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #0600FF;&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb86999&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And then add it to the Factory so it will be available when WebRequest calls it:&lt;/p&gt;

&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;csharp&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;csharp&quot; id=&quot;cb1292&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;TestableWebRequestCreateFactory.&lt;span style=&quot;color: #0000FF;&quot;&gt;GetFactory&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;.&lt;span style=&quot;color: #0000FF;&quot;&gt;AddRequest&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;expectedRequest&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb6724&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Put all of this together and we have:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;TestableHttpWebResponse.Sample.Tests/SampleServiceTests.cs&lt;/b&gt;&lt;/p&gt;
&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;csharp&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;csharp&quot; id=&quot;cb76977&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#91;&lt;/span&gt;Test&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#93;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #0600FF;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #0600FF;&quot;&gt;void&lt;/span&gt; ListRemoteStuff_ValidRequest_ReturnsSuccessfulResponse&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; var operation = &lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;ListOfStuff&amp;quot;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; var expectedRequest = &lt;a href=&quot;http://www.google.com/search?q=new+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;new&lt;/span&gt;&lt;/a&gt; TestableWebRequest&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;a href=&quot;http://www.google.com/search?q=new+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;new&lt;/span&gt;&lt;/a&gt; Uri&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;BaseUri, operation&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; expectedRequest.&lt;span style=&quot;color: #0000FF;&quot;&gt;EnqueueResponse&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;HttpStatusCode.&lt;span style=&quot;color: #0000FF;&quot;&gt;OK&lt;/span&gt;, &lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;Success&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;Even More Success&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #0600FF;&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; TestableWebRequestCreateFactory.&lt;span style=&quot;color: #0000FF;&quot;&gt;GetFactory&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;.&lt;span style=&quot;color: #0000FF;&quot;&gt;AddRequest&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;expectedRequest&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; var service = &lt;a href=&quot;http://www.google.com/search?q=new+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;new&lt;/span&gt;&lt;/a&gt; SampleService&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;BaseUri&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; var response = service.&lt;span style=&quot;color: #0000FF;&quot;&gt;ListRemoteStuff&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;operation&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Assert.&lt;span style=&quot;color: #0000FF;&quot;&gt;IsTrue&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;response.&lt;span style=&quot;color: #0000FF;&quot;&gt;IsSuccess&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb52692&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This exercises the entire successful path of the operation without any additional abstractions in our API code or reliance on external communications and services.&lt;/p&gt;

&lt;h2&gt;Testing Http Status Codes&lt;/h2&gt;

&lt;p&gt;Another tricky part of testing a service is figuring out how to test HTTP codes other then the success case. &lt;/p&gt;

&lt;p&gt;The sample service maps received Protocol Errors (401, 404, etc) to a local exception so the code consuming this library doesn&#039;t have to know how to parse WebExceptions. &lt;/p&gt;

&lt;p&gt;&lt;b&gt;TestableHttpWebResponse.Sample/SampleService.cs&lt;/b&gt;&lt;/p&gt;
&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;csharp&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;csharp&quot; id=&quot;cb84562&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;&lt;span style=&quot;color: #0600FF;&quot;&gt;private&lt;/span&gt; Exception MappedException&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;WebException we&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #008080; font-style: italic;&quot;&gt;// map to custom exceptions&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;we.&lt;span style=&quot;color: #0000FF;&quot;&gt;Status&lt;/span&gt; == WebExceptionStatus.&lt;span style=&quot;color: #0000FF;&quot;&gt;ProtocolError&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; var reader = &lt;a href=&quot;http://www.google.com/search?q=new+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;new&lt;/span&gt;&lt;/a&gt; StreamReader&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;we.&lt;span style=&quot;color: #0000FF;&quot;&gt;Response&lt;/span&gt;.&lt;span style=&quot;color: #0000FF;&quot;&gt;GetResponseStream&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; var message = reader.&lt;span style=&quot;color: #0000FF;&quot;&gt;ReadToEnd&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; var httpResponse = &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;HttpWebResponse&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;we.&lt;span style=&quot;color: #0000FF;&quot;&gt;Response&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF;&quot;&gt;switch&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;httpResponse.&lt;span style=&quot;color: #0000FF;&quot;&gt;StatusCode&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF;&quot;&gt;case&lt;/span&gt; HttpStatusCode.&lt;span style=&quot;color: #0000FF;&quot;&gt;NotFound&lt;/span&gt;:&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;httpResponse.&lt;span style=&quot;color: #0000FF;&quot;&gt;StatusDescription&lt;/span&gt;.&lt;span style=&quot;color: #0000FF;&quot;&gt;Contains&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;Dohicky&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF;&quot;&gt;return&lt;/span&gt; &lt;a href=&quot;http://www.google.com/search?q=new+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;new&lt;/span&gt;&lt;/a&gt; DohickyNotFoundException&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;message, we&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF;&quot;&gt;else&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF;&quot;&gt;return&lt;/span&gt; &lt;a href=&quot;http://www.google.com/search?q=new+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;new&lt;/span&gt;&lt;/a&gt; GenericNotFoundException&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;message, we&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF;&quot;&gt;default&lt;/span&gt;:&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF;&quot;&gt;return&lt;/span&gt; &lt;a href=&quot;http://www.google.com/search?q=new+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;new&lt;/span&gt;&lt;/a&gt; ExampleOfAnotherUsefulException&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;message, we&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF;&quot;&gt;else&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF;&quot;&gt;return&lt;/span&gt; &lt;a href=&quot;http://www.google.com/search?q=new+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;new&lt;/span&gt;&lt;/a&gt; SampleServiceOutageException&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;we&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb75143&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Exercising the mapping logic is going to require the WebRequest to receive a WebException. Let&#039;s make that happen.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Yes, I know a HEAD request will break this, that&#039;s why it&#039;s called &quot;sample&quot; code &lt;img src=&quot;http://blogs.lessthandot.com/rsc/smilies/icon_smile.gif&quot; title=&quot;:)&quot; alt=&quot;:)&quot; class=&quot;middle&quot; width=&quot;15&quot; height=&quot;15&quot; /&gt;&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;In the first test, we used the EnqueueResponse method of the TestableWebRequest to set up a 200 Success response. It&#039;s just as simple to return a 404 Http code with the expected message and request body:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;TestableHttpWebResponse.Sample.Tests/SampleServiceTests.cs&lt;/b&gt;&lt;/p&gt;
&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;csharp&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;csharp&quot; id=&quot;cb67708&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;expectedRequest.&lt;span style=&quot;color: #0000FF;&quot;&gt;EnqueueResponse&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;HttpStatusCode.&lt;span style=&quot;color: #0000FF;&quot;&gt;NotFound&lt;/span&gt;, &lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;Dohicky not found&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;I couldn&#039;t find your dohicky because I don&#039;t like you&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #0600FF;&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb3632&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Which allows us to create the ExpectedException test:&lt;/p&gt;

&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;csharp&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;csharp&quot; id=&quot;cb42108&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#91;&lt;/span&gt;Test&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#93;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#91;&lt;/span&gt;ExpectedException&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;a href=&quot;http://www.google.com/search?q=typeof+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;typeof&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;DohickyNotFoundException&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#93;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #0600FF;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #0600FF;&quot;&gt;void&lt;/span&gt; ListRemoteStuff_404DohickeyNotFound_ThrowsDohickeyNotFoundException&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; var operation = &lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;ListOfStuff&amp;quot;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; var expectedRequest = &lt;a href=&quot;http://www.google.com/search?q=new+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;new&lt;/span&gt;&lt;/a&gt; TestableWebRequest&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;a href=&quot;http://www.google.com/search?q=new+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;new&lt;/span&gt;&lt;/a&gt; Uri&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;BaseUri, operation&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; expectedRequest.&lt;span style=&quot;color: #0000FF;&quot;&gt;EnqueueResponse&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;HttpStatusCode.&lt;span style=&quot;color: #0000FF;&quot;&gt;NotFound&lt;/span&gt;, &lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;Dohicky not found&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;I couldn&#039;t find your dohicky because I don&#039;t like you&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #0600FF;&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; TestableWebRequestCreateFactory.&lt;span style=&quot;color: #0000FF;&quot;&gt;GetFactory&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;.&lt;span style=&quot;color: #0000FF;&quot;&gt;AddRequest&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;expectedRequest&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; var service = &lt;a href=&quot;http://www.google.com/search?q=new+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;new&lt;/span&gt;&lt;/a&gt; SampleService&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;BaseUri&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; var response = service.&lt;span style=&quot;color: #0000FF;&quot;&gt;ListRemoteStuff&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;operation&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #008080; font-style: italic;&quot;&gt;// expect exception&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb91598&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2&gt;Testing Other WebExceptions&lt;/h2&gt;

&lt;p&gt;What about connection failures? Well there is another version of the EnqueueResponse method that allows us to queue up an exception to be returned from the Request, like so:&lt;/p&gt;

&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;csharp&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;csharp&quot; id=&quot;cb16253&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;expectedRequest.&lt;span style=&quot;color: #0000FF;&quot;&gt;EnqueueResponse&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;a href=&quot;http://www.google.com/search?q=new+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;new&lt;/span&gt;&lt;/a&gt; WebException&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;I&#039;m broke!&amp;quot;&lt;/span&gt;, WebExceptionStatus.&lt;span style=&quot;color: #0000FF;&quot;&gt;ConnectFailure&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb26360&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Just like the previous test, we can use that response to put together a full test&lt;/p&gt;

&lt;p&gt;&lt;b&gt;TestableHttpWebResponse.Sample.Tests/SampleServiceTests.cs&lt;/b&gt;&lt;/p&gt;
&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;csharp&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;csharp&quot; id=&quot;cb60260&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#91;&lt;/span&gt;Test&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#93;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#91;&lt;/span&gt;ExpectedException&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;a href=&quot;http://www.google.com/search?q=typeof+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;typeof&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;SampleServiceOutageException&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#93;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #0600FF;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #0600FF;&quot;&gt;void&lt;/span&gt; ListRemoteStuff_ServiceOutage_ThrowsSampleServiceOutage&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; var operation = &lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;ListOfStuff&amp;quot;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; var expectedRequest = &lt;a href=&quot;http://www.google.com/search?q=new+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;new&lt;/span&gt;&lt;/a&gt; TestableWebRequest&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;a href=&quot;http://www.google.com/search?q=new+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;new&lt;/span&gt;&lt;/a&gt; Uri&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;BaseUri, operation&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; expectedRequest.&lt;span style=&quot;color: #0000FF;&quot;&gt;EnqueueResponse&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;a href=&quot;http://www.google.com/search?q=new+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;new&lt;/span&gt;&lt;/a&gt; WebException&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;I&#039;m broke!&amp;quot;&lt;/span&gt;, WebExceptionStatus.&lt;span style=&quot;color: #0000FF;&quot;&gt;ConnectFailure&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; TestableWebRequestCreateFactory.&lt;span style=&quot;color: #0000FF;&quot;&gt;GetFactory&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;.&lt;span style=&quot;color: #0000FF;&quot;&gt;AddRequest&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;expectedRequest&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; var service = &lt;a href=&quot;http://www.google.com/search?q=new+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;new&lt;/span&gt;&lt;/a&gt; SampleService&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;BaseUri&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; var response = service.&lt;span style=&quot;color: #0000FF;&quot;&gt;ListRemoteStuff&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;operation&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #008080; font-style: italic;&quot;&gt;// expect exception&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb51637&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2&gt;Testing the Retry Policy&lt;/h2&gt;

&lt;p&gt;Retry policies are trickier, in that they need to be able to execute a Request multiple times and receive new responses. By enqueueing (sp?) multiple responses on the request, we can exercise the retry policy:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;TestableHttpWebResponse.Sample.Tests/SampleServiceTests.cs&lt;/b&gt;&lt;/p&gt;
&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;csharp&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;csharp&quot; id=&quot;cb24544&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#91;&lt;/span&gt;Test&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#93;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #0600FF;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #0600FF;&quot;&gt;void&lt;/span&gt; ListRemoteStuff_TimeoutOccurs_TruesASecondTime&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; var operation = &lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;ListOfStuff&amp;quot;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; var expectedRequest = &lt;a href=&quot;http://www.google.com/search?q=new+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;new&lt;/span&gt;&lt;/a&gt; TestableWebRequest&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;a href=&quot;http://www.google.com/search?q=new+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;new&lt;/span&gt;&lt;/a&gt; Uri&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;BaseUri, operation&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; expectedRequest.&lt;span style=&quot;color: #0000FF;&quot;&gt;EnqueueResponse&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;a href=&quot;http://www.google.com/search?q=new+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;new&lt;/span&gt;&lt;/a&gt; TimeoutException&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;took too long, so sorry&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;.&lt;span style=&quot;color: #0000FF;&quot;&gt;EnqueueResponse&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;HttpStatusCode.&lt;span style=&quot;color: #0000FF;&quot;&gt;OK&lt;/span&gt;, &lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;All Good&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;Nothing to see, please move along&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #0600FF;&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; TestableWebRequestCreateFactory.&lt;span style=&quot;color: #0000FF;&quot;&gt;GetFactory&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;.&lt;span style=&quot;color: #0000FF;&quot;&gt;AddRequest&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;expectedRequest&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; var service = &lt;a href=&quot;http://www.google.com/search?q=new+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;new&lt;/span&gt;&lt;/a&gt; SampleService&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;BaseUri&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; var response = service.&lt;span style=&quot;color: #0000FF;&quot;&gt;ListRemoteStuff&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;operation&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Assert.&lt;span style=&quot;color: #0000FF;&quot;&gt;AreEqual&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;quot;Nothing to see, please move along&amp;quot;&lt;/span&gt;, response.&lt;span style=&quot;color: #0000FF;&quot;&gt;Message&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb98922&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And there we have it, all the various flavors of an HttpWebRequest.&lt;/p&gt;

&lt;h2&gt;The Testable Classes&lt;/h2&gt;
&lt;p&gt;The Testable classes are still under construction. At the time of this post they support the functionality above as well as the ability to set and verify Request Headers and write and verify the Request stream contents (upload). Currently the asynchronous methods (BeginGetResponse/EndGetResponse) are not implemented, but I&#039;ll be adding those soon along with SampleService calls that exercise those via TPL and async/await logic. I&#039;ll also be looking through WebRequest for other properties or methods I haven&#039;t imlpemented yet to see what&#039;s useful.&lt;/p&gt;

&lt;p&gt;Hopefully others will find this useful as well.&lt;/p&gt;&lt;div class=&quot;item_footer&quot;&gt;&lt;p&gt;&lt;small&gt;&lt;a href=&quot;http://blogs.lessthandot.com/index.php/DesktopDev/MSTech/CSharp/testing-httpwebresponse&quot;&gt;Original post&lt;/a&gt; blogged on &lt;a href=&quot;http://lessthandot.com/&quot;&gt;LessThanDot&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;/div&gt;</description>
			<content:encoded><![CDATA[<p>Recently I was working on a library to consume a REST API without exposing any of the specifics to the rest of the application. Implementing a common interface and set of custom exceptions was easy enough, but exercising the internal logic was going to be tough. </p>

<p>While I could use the live REST API to verify the general logic worked, I had limited options when it came to the full range of HTTP responses and communication failures. Add in the impact those live API calls would have on my build process performance, the occasional failures of my build due the imperfections of talking to a live service, and the overhead of maintaining separation between my test and live data in that service...what I really had on my hands was the beginning of years of random, painful maintenance.</p>

<p>If only I could mock WebRequest and have it return carefully crafted responses to test my code with, all without ever touching the real network.</p>

<blockquote><p><a href="http://msdn.microsoft.com/en-us/library/system.net.httpwebresponse.aspx" title="HttpWebResponse on MSDN">MSDN</a>: You should never directly create an instance of the HttpWebResponse class.</p></blockquote>

<p>Hmm, ok, maybe not.</p>

<p>Despite having done this search before, this time around I uncovered a couple posts that helped me find a solution to this whole mess. Although not before I left some helpful feedback on the MSDN page about the difference between opinion and documentation.</p>

<p>Yep, making friends.</p>

<p><i>The source code for this post is located on github, with the sample service implementation and test projects: <a href="https://github.com/tarwn/TestableHttpWebResponse" title="tarwn/TestableHttpWebResponse on github">tarwn/TestableHttpWebResponse</a></i></p>

<h2>Let's Start with the Tests</h2>
<p>I've created a sample service implementation with two API call implementations. Each one builds a WebRequest, executes it, and analyzes the response. A retry policy wraps around the request execution, evaluating exceptions to determine whether to retry or map them to a local exception type to be rethrown.</p>

<p>Here is an example of one of those calls and the synchronous method it uses internally:</p>

<p><b>TestableHttpWebResponse.Sample/SampleService.cs</b></p>
<div class="codebox"><div class="codeheader"><span>csharp</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb90360'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb90360','cb71250'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="csharp" id="cb90360" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1"><span style="color: #0600FF;">public</span> <span style="color: #FF0000;">class</span> SampleService</li><li style="" class="li2"><span style="color: #000000;">&#123;</span></li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #008080; font-style: italic;">// ...</span></li><li style="" class="li2">&nbsp;</li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #0600FF;">public</span> ServiceResponse ListRemoteStuff<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span> operation<span style="color: #000000;">&#41;</span></li><li style="" class="li2">&nbsp; &nbsp; <span style="color: #000000;">&#123;</span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; var uri = <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> Uri<span style="color: #000000;">&#40;</span>_baseUri, operation<span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; var request = WebRequest.<span style="color: #0000FF;">Create</span><span style="color: #000000;">&#40;</span>uri<span style="color: #000000;">&#41;</span>;</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; request.<span style="color: #0000FF;">Headers</span>.<span style="color: #0000FF;">Add</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;version&quot;</span>, <span style="color: #808080;">&quot;123-awesome&quot;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> SendRequest<span style="color: #000000;">&#40;</span>request<span style="color: #000000;">&#41;</span>;</li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #000000;">&#125;</span></li><li style="" class="li2">&nbsp; &nbsp; </li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #008080; font-style: italic;">// ...</span></li><li style="" class="li2">&nbsp;</li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #0600FF;">private</span> ServiceResponse SendRequest<span style="color: #000000;">&#40;</span>WebRequest request<span style="color: #000000;">&#41;</span></li><li style="" class="li2">&nbsp; &nbsp; <span style="color: #000000;">&#123;</span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> _retryPolicy.<span style="color: #0000FF;">ExecuteAction</span>&lt;ServiceResponse&gt;<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> =&gt;</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">try</span></li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var response = <span style="color: #000000;">&#40;</span>HttpWebResponse<span style="color: #000000;">&#41;</span>request.<span style="color: #0000FF;">GetResponse</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var reader = <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> StreamReader<span style="color: #000000;">&#40;</span>response.<span style="color: #0000FF;">GetResponseStream</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var message = reader.<span style="color: #0000FF;">ReadToEnd</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> ServiceResponse<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span> IsSuccess = <span style="color: #0600FF;">true</span>, Message = message <span style="color: #000000;">&#125;</span>;</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span></li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">catch</span> <span style="color: #000000;">&#40;</span>WebException we<span style="color: #000000;">&#41;</span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span></li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">throw</span> MappedException<span style="color: #000000;">&#40;</span>we<span style="color: #000000;">&#41;</span>;</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span></li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #000000;">&#125;</span></li><li style="" class="li2">&nbsp;</li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #008080; font-style: italic;">// ...</span></li><li style="" class="li2"><span style="color: #000000;">&#125;</span></li></ol></div><div id="cb71250" style="display: none; color: red;"></div></div></div>

<p>Testing a method like this typically requires an integration test against the live service. With the provided TestableHttpWebResponse and TestableWebRequest, however, we can set up an expected request and response and verify the service reacts appropriately.</p>

<p><b>1: Register the TestableWebRequestCreateFactory</b><br />
WebRequest.Create(<i>uri</i>) uses a factory to produce the relevant WebRequest instance of a Uri, based on the prefix. So first things first, lets register a new prefix and a factory to serve up requests:</p>

<div class="codebox"><div class="codeheader"><span>csharp</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb60864'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb60864','cb1607'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="csharp" id="cb60864" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1"><span style="color: #000000;">&#91;</span>TestFixtureSetUp<span style="color: #000000;">&#93;</span></li><li style="" class="li2"><span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> TestFixtureSetup<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span></li><li style="" class="li1"><span style="color: #000000;">&#123;</span></li><li style="" class="li2">&nbsp; &nbsp; WebRequest.<span style="color: #0000FF;">RegisterPrefix</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;test&quot;</span>, TestableWebRequestCreateFactory.<span style="color: #0000FF;">GetFactory</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li1"><span style="color: #000000;">&#125;</span></li></ol></div><div id="cb1607" style="display: none; color: red;"></div></div></div>

<p>TestableWebRequestCreateFactory.GetFactory() exposes a singleton that can be referenced from any of the tests in this class. When the WebRequest object receives a Uri starting with "test://", it will call the associated factory, giving us the opportunity to respond with a Request object of our choosing.</p>

<p>A common base URI will prove helpful as we write the tests:</p>

<div class="codebox"><div class="codeheader"><span>csharp</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb72718'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb72718','cb36119'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="csharp" id="cb72718" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1"><span style="color: #0600FF;">public</span> Uri BaseUri <span style="color: #000000;">&#123;</span> get <span style="color: #000000;">&#123;</span> <span style="color: #0600FF;">return</span> <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> Uri<span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;test://mydomain.com/api/&quot;</span><span style="color: #000000;">&#41;</span>; <span style="color: #000000;">&#125;</span> <span style="color: #000000;">&#125;</span></li></ol></div><div id="cb36119" style="display: none; color: red;"></div></div></div>

<p><b>2: Building a Test</b></p>

<p>The easiest test to start with is one that will test the "happy path" where our API call receives a 200 Success response. </p>

<p>First we need to set up the request:</p>

<div class="codebox"><div class="codeheader"><span>csharp</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb71323'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb71323','cb89978'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="csharp" id="cb71323" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1">var operation = <span style="color: #808080;">&quot;ListOfStuff&quot;</span>;</li><li style="" class="li2">var expectedRequest = <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> TestableWebRequest<span style="color: #000000;">&#40;</span><a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> Uri<span style="color: #000000;">&#40;</span>BaseUri, operation<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>;</li></ol></div><div id="cb89978" style="display: none; color: red;"></div></div></div>

<p>Next we need to set up the response the request will return when it is executed:</p>

<div class="codebox"><div class="codeheader"><span>csharp</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb51400'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb51400','cb77838'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="csharp" id="cb51400" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1">expectedRequest.<span style="color: #0000FF;">EnqueueResponse</span><span style="color: #000000;">&#40;</span>HttpStatusCode.<span style="color: #0000FF;">OK</span>, <span style="color: #808080;">&quot;Success&quot;</span>, <span style="color: #808080;">&quot;Even More Success&quot;</span>, <span style="color: #0600FF;">false</span><span style="color: #000000;">&#41;</span>;</li></ol></div><div id="cb77838" style="display: none; color: red;"></div></div></div>

<p>And then add it to the Factory so it will be available when WebRequest calls it:</p>

<div class="codebox"><div class="codeheader"><span>csharp</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb98165'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb98165','cb15015'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="csharp" id="cb98165" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1">TestableWebRequestCreateFactory.<span style="color: #0000FF;">GetFactory</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">AddRequest</span><span style="color: #000000;">&#40;</span>expectedRequest<span style="color: #000000;">&#41;</span>;</li></ol></div><div id="cb15015" style="display: none; color: red;"></div></div></div>

<p>Put all of this together and we have:</p>

<p><b>TestableHttpWebResponse.Sample.Tests/SampleServiceTests.cs</b></p>
<div class="codebox"><div class="codeheader"><span>csharp</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb19069'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb19069','cb66965'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="csharp" id="cb19069" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1"><span style="color: #000000;">&#91;</span>Test<span style="color: #000000;">&#93;</span></li><li style="" class="li2"><span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> ListRemoteStuff_ValidRequest_ReturnsSuccessfulResponse<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span></li><li style="" class="li1"><span style="color: #000000;">&#123;</span></li><li style="" class="li2">&nbsp; &nbsp; var operation = <span style="color: #808080;">&quot;ListOfStuff&quot;</span>;</li><li style="" class="li1">&nbsp; &nbsp; var expectedRequest = <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> TestableWebRequest<span style="color: #000000;">&#40;</span><a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> Uri<span style="color: #000000;">&#40;</span>BaseUri, operation<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp; &nbsp; expectedRequest.<span style="color: #0000FF;">EnqueueResponse</span><span style="color: #000000;">&#40;</span>HttpStatusCode.<span style="color: #0000FF;">OK</span>, <span style="color: #808080;">&quot;Success&quot;</span>, <span style="color: #808080;">&quot;Even More Success&quot;</span>, <span style="color: #0600FF;">false</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li1">&nbsp; &nbsp; TestableWebRequestCreateFactory.<span style="color: #0000FF;">GetFactory</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">AddRequest</span><span style="color: #000000;">&#40;</span>expectedRequest<span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp; &nbsp; var service = <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> SampleService<span style="color: #000000;">&#40;</span>BaseUri<span style="color: #000000;">&#41;</span>;</li><li style="" class="li1">&nbsp;</li><li style="" class="li2">&nbsp; &nbsp; var response = service.<span style="color: #0000FF;">ListRemoteStuff</span><span style="color: #000000;">&#40;</span>operation<span style="color: #000000;">&#41;</span>;</li><li style="" class="li1">&nbsp;</li><li style="" class="li2">&nbsp; &nbsp; Assert.<span style="color: #0000FF;">IsTrue</span><span style="color: #000000;">&#40;</span>response.<span style="color: #0000FF;">IsSuccess</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li1"><span style="color: #000000;">&#125;</span></li></ol></div><div id="cb66965" style="display: none; color: red;"></div></div></div>

<p>This exercises the entire successful path of the operation without any additional abstractions in our API code or reliance on external communications and services.</p>

<h2>Testing Http Status Codes</h2>

<p>Another tricky part of testing a service is figuring out how to test HTTP codes other then the success case. </p>

<p>The sample service maps received Protocol Errors (401, 404, etc) to a local exception so the code consuming this library doesn't have to know how to parse WebExceptions. </p>

<p><b>TestableHttpWebResponse.Sample/SampleService.cs</b></p>
<div class="codebox"><div class="codeheader"><span>csharp</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb23889'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb23889','cb12621'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="csharp" id="cb23889" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1"><span style="color: #0600FF;">private</span> Exception MappedException<span style="color: #000000;">&#40;</span>WebException we<span style="color: #000000;">&#41;</span></li><li style="" class="li2"><span style="color: #000000;">&#123;</span></li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #008080; font-style: italic;">// map to custom exceptions</span></li><li style="" class="li2">&nbsp; &nbsp; <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>we.<span style="color: #0000FF;">Status</span> == WebExceptionStatus.<span style="color: #0000FF;">ProtocolError</span><span style="color: #000000;">&#41;</span></li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #000000;">&#123;</span></li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; var reader = <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> StreamReader<span style="color: #000000;">&#40;</span>we.<span style="color: #0000FF;">Response</span>.<span style="color: #0000FF;">GetResponseStream</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; var message = reader.<span style="color: #0000FF;">ReadToEnd</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; var httpResponse = <span style="color: #000000;">&#40;</span>HttpWebResponse<span style="color: #000000;">&#41;</span>we.<span style="color: #0000FF;">Response</span>;</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">switch</span> <span style="color: #000000;">&#40;</span>httpResponse.<span style="color: #0000FF;">StatusCode</span><span style="color: #000000;">&#41;</span></li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">case</span> HttpStatusCode.<span style="color: #0000FF;">NotFound</span>:</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>httpResponse.<span style="color: #0000FF;">StatusDescription</span>.<span style="color: #0000FF;">Contains</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;Dohicky&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> DohickyNotFoundException<span style="color: #000000;">&#40;</span>message, we<span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">else</span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> GenericNotFoundException<span style="color: #000000;">&#40;</span>message, we<span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">default</span>:</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> ExampleOfAnotherUsefulException<span style="color: #000000;">&#40;</span>message, we<span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span></li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #000000;">&#125;</span></li><li style="" class="li2">&nbsp; &nbsp; <span style="color: #0600FF;">else</span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> SampleServiceOutageException<span style="color: #000000;">&#40;</span>we<span style="color: #000000;">&#41;</span>;</li><li style="" class="li2"><span style="color: #000000;">&#125;</span></li></ol></div><div id="cb12621" style="display: none; color: red;"></div></div></div>

<p>Exercising the mapping logic is going to require the WebRequest to receive a WebException. Let's make that happen.</p>

<p><i>Yes, I know a HEAD request will break this, that's why it's called "sample" code <img src="http://blogs.lessthandot.com/rsc/smilies/icon_smile.gif" title=":)" alt=":)" class="middle" width="15" height="15" /></i></p>

<p>In the first test, we used the EnqueueResponse method of the TestableWebRequest to set up a 200 Success response. It's just as simple to return a 404 Http code with the expected message and request body:</p>

<p><b>TestableHttpWebResponse.Sample.Tests/SampleServiceTests.cs</b></p>
<div class="codebox"><div class="codeheader"><span>csharp</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb84252'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb84252','cb68662'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="csharp" id="cb84252" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1">expectedRequest.<span style="color: #0000FF;">EnqueueResponse</span><span style="color: #000000;">&#40;</span>HttpStatusCode.<span style="color: #0000FF;">NotFound</span>, <span style="color: #808080;">&quot;Dohicky not found&quot;</span>, <span style="color: #808080;">&quot;I couldn't find your dohicky because I don't like you&quot;</span>, <span style="color: #0600FF;">true</span><span style="color: #000000;">&#41;</span>;</li></ol></div><div id="cb68662" style="display: none; color: red;"></div></div></div>

<p>Which allows us to create the ExpectedException test:</p>

<div class="codebox"><div class="codeheader"><span>csharp</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb35384'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb35384','cb98183'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="csharp" id="cb35384" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1"><span style="color: #000000;">&#91;</span>Test<span style="color: #000000;">&#93;</span></li><li style="" class="li2"><span style="color: #000000;">&#91;</span>ExpectedException<span style="color: #000000;">&#40;</span><a href="http://www.google.com/search?q=typeof+msdn.microsoft.com"><span style="color: #008000;">typeof</span></a><span style="color: #000000;">&#40;</span>DohickyNotFoundException<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span></li><li style="" class="li1"><span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> ListRemoteStuff_404DohickeyNotFound_ThrowsDohickeyNotFoundException<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span></li><li style="" class="li2"><span style="color: #000000;">&#123;</span></li><li style="" class="li1">&nbsp; &nbsp; var operation = <span style="color: #808080;">&quot;ListOfStuff&quot;</span>;</li><li style="" class="li2">&nbsp; &nbsp; var expectedRequest = <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> TestableWebRequest<span style="color: #000000;">&#40;</span><a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> Uri<span style="color: #000000;">&#40;</span>BaseUri, operation<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li1">&nbsp; &nbsp; expectedRequest.<span style="color: #0000FF;">EnqueueResponse</span><span style="color: #000000;">&#40;</span>HttpStatusCode.<span style="color: #0000FF;">NotFound</span>, <span style="color: #808080;">&quot;Dohicky not found&quot;</span>, <span style="color: #808080;">&quot;I couldn't find your dohicky because I don't like you&quot;</span>, <span style="color: #0600FF;">true</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp; &nbsp; TestableWebRequestCreateFactory.<span style="color: #0000FF;">GetFactory</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">AddRequest</span><span style="color: #000000;">&#40;</span>expectedRequest<span style="color: #000000;">&#41;</span>;</li><li style="" class="li1">&nbsp; &nbsp; var service = <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> SampleService<span style="color: #000000;">&#40;</span>BaseUri<span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp;</li><li style="" class="li1">&nbsp; &nbsp; var response = service.<span style="color: #0000FF;">ListRemoteStuff</span><span style="color: #000000;">&#40;</span>operation<span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp;</li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #008080; font-style: italic;">// expect exception</span></li><li style="" class="li2"><span style="color: #000000;">&#125;</span></li></ol></div><div id="cb98183" style="display: none; color: red;"></div></div></div>

<h2>Testing Other WebExceptions</h2>

<p>What about connection failures? Well there is another version of the EnqueueResponse method that allows us to queue up an exception to be returned from the Request, like so:</p>

<div class="codebox"><div class="codeheader"><span>csharp</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb38662'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb38662','cb60800'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="csharp" id="cb38662" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1">expectedRequest.<span style="color: #0000FF;">EnqueueResponse</span><span style="color: #000000;">&#40;</span><a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> WebException<span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;I'm broke!&quot;</span>, WebExceptionStatus.<span style="color: #0000FF;">ConnectFailure</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>;</li></ol></div><div id="cb60800" style="display: none; color: red;"></div></div></div>

<p>Just like the previous test, we can use that response to put together a full test</p>

<p><b>TestableHttpWebResponse.Sample.Tests/SampleServiceTests.cs</b></p>
<div class="codebox"><div class="codeheader"><span>csharp</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb31790'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb31790','cb1800'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="csharp" id="cb31790" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1"><span style="color: #000000;">&#91;</span>Test<span style="color: #000000;">&#93;</span></li><li style="" class="li2"><span style="color: #000000;">&#91;</span>ExpectedException<span style="color: #000000;">&#40;</span><a href="http://www.google.com/search?q=typeof+msdn.microsoft.com"><span style="color: #008000;">typeof</span></a><span style="color: #000000;">&#40;</span>SampleServiceOutageException<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span></li><li style="" class="li1"><span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> ListRemoteStuff_ServiceOutage_ThrowsSampleServiceOutage<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span></li><li style="" class="li2"><span style="color: #000000;">&#123;</span></li><li style="" class="li1">&nbsp; &nbsp; var operation = <span style="color: #808080;">&quot;ListOfStuff&quot;</span>;</li><li style="" class="li2">&nbsp; &nbsp; var expectedRequest = <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> TestableWebRequest<span style="color: #000000;">&#40;</span><a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> Uri<span style="color: #000000;">&#40;</span>BaseUri, operation<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li1">&nbsp; &nbsp; expectedRequest.<span style="color: #0000FF;">EnqueueResponse</span><span style="color: #000000;">&#40;</span><a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> WebException<span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;I'm broke!&quot;</span>, WebExceptionStatus.<span style="color: #0000FF;">ConnectFailure</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp; &nbsp; TestableWebRequestCreateFactory.<span style="color: #0000FF;">GetFactory</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">AddRequest</span><span style="color: #000000;">&#40;</span>expectedRequest<span style="color: #000000;">&#41;</span>;</li><li style="" class="li1">&nbsp; &nbsp; var service = <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> SampleService<span style="color: #000000;">&#40;</span>BaseUri<span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp;</li><li style="" class="li1">&nbsp; &nbsp; var response = service.<span style="color: #0000FF;">ListRemoteStuff</span><span style="color: #000000;">&#40;</span>operation<span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp;</li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #008080; font-style: italic;">// expect exception</span></li><li style="" class="li2"><span style="color: #000000;">&#125;</span></li></ol></div><div id="cb1800" style="display: none; color: red;"></div></div></div>

<h2>Testing the Retry Policy</h2>

<p>Retry policies are trickier, in that they need to be able to execute a Request multiple times and receive new responses. By enqueueing (sp?) multiple responses on the request, we can exercise the retry policy:</p>

<p><b>TestableHttpWebResponse.Sample.Tests/SampleServiceTests.cs</b></p>
<div class="codebox"><div class="codeheader"><span>csharp</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb89517'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb89517','cb91997'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="csharp" id="cb89517" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1"><span style="color: #000000;">&#91;</span>Test<span style="color: #000000;">&#93;</span></li><li style="" class="li2"><span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> ListRemoteStuff_TimeoutOccurs_TruesASecondTime<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span></li><li style="" class="li1"><span style="color: #000000;">&#123;</span></li><li style="" class="li2">&nbsp; &nbsp; var operation = <span style="color: #808080;">&quot;ListOfStuff&quot;</span>;</li><li style="" class="li1">&nbsp; &nbsp; var expectedRequest = <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> TestableWebRequest<span style="color: #000000;">&#40;</span><a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> Uri<span style="color: #000000;">&#40;</span>BaseUri, operation<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp; &nbsp; expectedRequest.<span style="color: #0000FF;">EnqueueResponse</span><span style="color: #000000;">&#40;</span><a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> TimeoutException<span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;took too long, so sorry&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.<span style="color: #0000FF;">EnqueueResponse</span><span style="color: #000000;">&#40;</span>HttpStatusCode.<span style="color: #0000FF;">OK</span>, <span style="color: #808080;">&quot;All Good&quot;</span>, <span style="color: #808080;">&quot;Nothing to see, please move along&quot;</span>, <span style="color: #0600FF;">false</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp; &nbsp; TestableWebRequestCreateFactory.<span style="color: #0000FF;">GetFactory</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">AddRequest</span><span style="color: #000000;">&#40;</span>expectedRequest<span style="color: #000000;">&#41;</span>;</li><li style="" class="li1">&nbsp; &nbsp; var service = <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> SampleService<span style="color: #000000;">&#40;</span>BaseUri<span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp;</li><li style="" class="li1">&nbsp; &nbsp; var response = service.<span style="color: #0000FF;">ListRemoteStuff</span><span style="color: #000000;">&#40;</span>operation<span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp;</li><li style="" class="li1">&nbsp; &nbsp; Assert.<span style="color: #0000FF;">AreEqual</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;Nothing to see, please move along&quot;</span>, response.<span style="color: #0000FF;">Message</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li2"><span style="color: #000000;">&#125;</span></li></ol></div><div id="cb91997" style="display: none; color: red;"></div></div></div>

<p>And there we have it, all the various flavors of an HttpWebRequest.</p>

<h2>The Testable Classes</h2>
<p>The Testable classes are still under construction. At the time of this post they support the functionality above as well as the ability to set and verify Request Headers and write and verify the Request stream contents (upload). Currently the asynchronous methods (BeginGetResponse/EndGetResponse) are not implemented, but I'll be adding those soon along with SampleService calls that exercise those via TPL and async/await logic. I'll also be looking through WebRequest for other properties or methods I haven't imlpemented yet to see what's useful.</p>

<p>Hopefully others will find this useful as well.</p><div class="item_footer"><p><small><a href="http://blogs.lessthandot.com/index.php/DesktopDev/MSTech/CSharp/testing-httpwebresponse">Original post</a> blogged on <a href="http://lessthandot.com/">LessThanDot</a>.</small></p></div>]]></content:encoded>
								<comments>http://blogs.lessthandot.com/index.php/DesktopDev/MSTech/CSharp/testing-httpwebresponse#comments</comments>
			<wfw:commentRss>http://blogs.lessthandot.com/index.php/DesktopDev/?tempskin=_rss2&#38;disp=comments&#38;p=1932</wfw:commentRss>
		</item>
				<item>
			<title>Scalability is Easy! (To Get Wrong)</title>
			<link>http://blogs.lessthandot.com/index.php/Architect/DesigningSoftware/scalability-is-easy-to-get</link>
			<pubDate>Wed, 05 Dec 2012 12:50:00 +0000</pubDate>			<dc:creator>Eli Weinstock-Herman (tarwn)</dc:creator>
			<category domain="main">Designing Software</category>			<guid isPermaLink="false">1923@http://blogs.lessthandot.com/</guid>
						<description>&lt;p&gt;Scalability is easy, provided you don&#039;t need it to work.&lt;/p&gt;

&lt;p&gt;Probably the number one failure of system scaling is when people dive right in and start building. No baselines, limited measurements, no analysis, just a hypothesis and a whole lot of late nights tweaking the system. With extra complexity comes extra costs, from the initial development through more expensive maintenance. Scale poorly and not only do we take on those extra complexity costs, but also the more obvious additional costs of the actual implementation (new servers, more resources, etc).&lt;/p&gt;

&lt;h2&gt;The Somewhat Contrived Example&lt;/h2&gt;

&lt;p&gt;Recently I&#039;ve been working on a system to simulate parallelizing workloads, specifically workloads that depend on external resources with rate or load thresholds. Let&#039;s use it to look at a somewhat contrived example.&lt;/p&gt;

&lt;div style=&quot;background-color: #eeeeee; padding: 1em; margin: 1em;&quot;&gt;
Note: For this post, the simulated &quot;service&quot; has a 100 request/minute limit and throttles individual clients for 15 second windows. Individual operations consist of 50ms of local processing and a single service request that has 50ms of latency and 100 ms for processing and response time. Similar results can be achieved with more realistic batch sizes and rates, the smaller values just allow me to more quickly produce samples for the blog post.
&lt;/div&gt;

&lt;p&gt;So the backstory is that I have a batch process that is running more and more slowly as we take on larger and more frequent workloads. &lt;/p&gt;

&lt;p&gt;I start by testing the batch process locally so I can see how slow it is before I make changes.&lt;/p&gt;

&lt;div style=&quot;text-align: center; font-size: .8em; color: #666666&quot;&gt;
	&lt;img src=&quot;http://tiernok.com/LTDBlog/Scalability/Graph_01.png&quot; alt=&quot;Graph - 1 Client, 60 Requests, 100rpm Limit&quot; /&gt;&lt;br /&gt;
	1 Client, 60 Requests, 100rpm
&lt;/div&gt;

&lt;p&gt;Locally it runs pretty quickly, but I&#039;m betting that parallelizing the process will give me a significant increase in speed.&lt;/p&gt;

&lt;div style=&quot;text-align: center; font-size: .8em; color: #666666&quot;&gt;
	&lt;img src=&quot;http://tiernok.com/LTDBlog/Scalability/Graph_02.png&quot; alt=&quot;Graph - 1 Client vs 30 Clients, 60 Requests, 100rpm Limit&quot; /&gt;&lt;br /&gt;
	1 Client vs 30 Clients, 60 Requests, 100rpm
&lt;/div&gt;

&lt;p&gt;Look how well that performance improved, I achieved better than a 6x improvement in performance. My job here is done. &lt;/p&gt;

&lt;p&gt;Except when I try to push this to production, I start getting a lot of errors. &lt;/p&gt;

&lt;div style=&quot;text-align: center; font-size: .8em; color: #666666&quot;&gt;
	&lt;img src=&quot;http://tiernok.com/LTDBlog/Scalability/Graph_03.png&quot; alt=&quot;Graph - 30 Clients, 300 Requests, 100rpm - 67% Failure Rate&quot; /&gt;&lt;br /&gt;
	30 Clients, 300 Requests, 100rpm - 67% Failure Rate
&lt;/div&gt;

&lt;p&gt;As it turns out, the external API my process saves the data to has a rate limit. When I exceed the allowable rate, I&#039;m throttled for a short period of time. Any requests I make during that throttle period are returned with errors indicating I&#039;m throttled.&lt;/p&gt;

&lt;p&gt;Hmm. Luckily there are a number of common patterns available to retry these types of failures. I&#039;ll add an exponential back-off retry pattern so that when I get throttled my service will retry failed requests at slower rates until the service un-throttles me. While I&#039;ve found plenty of code examples online, none of them seem to have recommendations, so I&#039;ll just use one of the sample settings they provide.&lt;/p&gt;

&lt;div style=&quot;text-align: center; font-size: .8em; color: #666666&quot;&gt;
	&lt;img src=&quot;http://tiernok.com/LTDBlog/Scalability/Graph_04.png&quot; alt=&quot;Graph - 30 Clients, 300 Requests, 100rpm, Retry Policy #1 - 7% Failure Rate&quot; /&gt;&lt;br /&gt;
	30 Clients, 300 Requests, 100rpm, Retry Policy #1 - 7% Failure Rate
&lt;/div&gt;

&lt;p&gt;Hmm, better. My failure rate has gone way down. What if I tweak the values?&lt;/p&gt;

&lt;div style=&quot;text-align: center; font-size: .8em; color: #666666&quot;&gt;
	&lt;img src=&quot;http://tiernok.com/LTDBlog/Scalability/Graph_05.png&quot; alt=&quot;Graph - 30 Clients, 300 Requests, 100rpm, Retry Policy #2 - 29% Failure Rate&quot; /&gt;&lt;br /&gt;
	30 Clients, 300 Requests, 100rpm, Retry Policy #2 - 29% Failure Rate
&lt;/div&gt;

&lt;p&gt;Oh, that was bad, I obviously was on the right track before. What if I just extend the retry amount a bit to try and knock out the last bit of errors. &lt;/p&gt;

&lt;div style=&quot;text-align: center; font-size: .8em; color: #666666&quot;&gt;
	&lt;img src=&quot;http://tiernok.com/LTDBlog/Scalability/Graph_06.png&quot; alt=&quot;Graph - 30 Clients, 300 Requests, 100rpm, Retry Policy #1B - 0% Failure Rate&quot; /&gt;&lt;br /&gt;
	30 Clients, 300 Requests, 100rpm, Retry Policy #1B - 0% Failure Rate
&lt;/div&gt;

&lt;p&gt;Ok, perfect. Now I have a system that is more than 6 times faster than the original, can be easily extended by throwing more workers at it, and is actually in a better position to handle occasional slow downs from my 3rd-party service. &lt;/p&gt;

&lt;p&gt;Success!&lt;/p&gt;

&lt;h2&gt;Where I Went Wrong&lt;/h2&gt;
&lt;p&gt;Ok, so maybe not. Over the course of my little story I went wrong in a number of places. Even though this was a contrived example, I&#039;ve watched very similar scenarios play out in a number of different organizations with real systems.&lt;/p&gt;

&lt;h3&gt;The Bottleneck&lt;/h3&gt;
&lt;p&gt;The first and most critical problem was that I didn&#039;t actually locate the bottleneck in my process, I simply tried to do more of the same. The &lt;a href=&quot;http://en.wikipedia.org/wiki/Theory_of_constraints&quot; title=&quot;Theory of Constraints at Wikipedia&quot;&gt;Theory of Constraints&lt;/a&gt; tells us that we can improve the rate of a process by identifying and exploiting the constraints. &lt;/p&gt;

&lt;p&gt;In this system, the constraint looked like it was the sequential execution of the tasks, but in reality the constraint was the time it took to call the 3rd-party API. Had we identified that bottleneck before starting, we could have approached the problem differently.&lt;/p&gt;

&lt;div style=&quot;text-align: center; font-size: .8em; color: #666666&quot;&gt;
	&lt;img src=&quot;http://tiernok.com/LTDBlog/Scalability/ProcessChange.png&quot; alt=&quot;Process - Alternative Design&quot; /&gt;&lt;br /&gt;
	Process - Alternative Design
&lt;/div&gt;

&lt;p&gt;Rather than the parallel complexity, we can modify how the tasks are executed to try and take advantage of knowing where our bottleneck is. If the API allowed us to submit several requests in a batch, this redesign would net us several orders of magnitude improvement. Another option would be to run the results of the local processing into a queue and submit requests from there at a slow trickle, using only a percentage of our API limit so as not to disrupt any other real-time operations or batch processing the system supports. Another option we could take advantage of is not starting any of our expensive 3rd-party communications until we know that the entire job can actually be processed successfully through our local process.&lt;/p&gt;

&lt;p&gt;Identifying the constraint unlocks the ability to turn the problem on it&#039;s head and achieve higher improvements, typically by orders of magnitude.&lt;/p&gt;

&lt;h3&gt;The Math Error&lt;/h3&gt;
&lt;p&gt;I concluded the scenario above by assuming I had found a good solution that also had a lot of headroom. Unfortunately what I actually did was find the ceiling. I have tuned the retry policy to 30 parallel systems, increasing that number could easily destabilize it further and cause more errors or delays. The headroom is, in fact, an illusion.&lt;/p&gt;

&lt;h3&gt;The Evolving Assumption&lt;/h3&gt;
&lt;p&gt;Somewhere along the way I found 30 clients to be a great improvement and didn&#039;t test other options. Then I made some assumptions about a retry policy. Then I tweaked that retry policy until the error rate disappeared. My assumptions made sense at the time, so I never questioned where they were leading me.&lt;/p&gt;

&lt;p&gt;When I found a winning combination for my retry rate, I didn&#039;t realize I was missing other, better options:&lt;/p&gt;

&lt;div style=&quot;text-align: center; font-size: .8em; color: #666666&quot;&gt;
	&lt;img src=&quot;http://tiernok.com/LTDBlog/Scalability/Graph_07.png&quot; alt=&quot;Graph - 30 Clients, 300 Requests, 100rpm, Retry Policy #1B vs 4A-C&quot; /&gt;&lt;br /&gt;
	30 Clients, 300 Requests, 100rpm, Retry Policy #1B vs 4A-C
&lt;/div&gt;

&lt;p&gt;What&#039;s worse, is that trail of assumptions along the way was never re-validated. I concluded with a 6.5x improvement, but is that still accurate?&lt;/p&gt;

&lt;div style=&quot;text-align: center; font-size: .8em; color: #666666&quot;&gt;
	&lt;img src=&quot;http://tiernok.com/LTDBlog/Scalability/Graph_08.png&quot; alt=&quot;Graph - 1-50 Clients, 300 Requests, 100rpm, Retry Policy #1B&quot; /&gt;&lt;br /&gt;
	1-50 Clients, 300 Requests, 100rpm, Retry Policy #1B
&lt;/div&gt;

&lt;p&gt;When I run the same settings on a range of 1 to 50 clients, we can see that I lost that original 6x improvement along the way. All I have managed to do is add complexity and some very explicit costs for those additional systems.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Note: What happened to retry policy #3? Well originally 1B was actually named 3, then I decided to update the name halfway through the post but was too lazy to update all of the completed images. Oh well.&lt;/i&gt;&lt;/p&gt;

&lt;h2&gt;Scaling the Wrong Thing&lt;/h2&gt;
&lt;p&gt;This post used fairly small numbers, had I applied a larger workload, higher throughput rates, different throttling windows, the whole problem would have turned out differently. &lt;/p&gt;

&lt;p&gt;When we set out to make a system scale, we need to identify the real scenarios we are trying to scale for and the bottlenecks that stand in our way. Blindly performance tuning can look like an improvement, but is really just a poor short term investment that often entrenches the current performance problems even more deeply. There are a lot of questions that should be asked about the intended result, responsiveness fo the system, other operations it has to support while under load, potential overlap of that load, the type of load, etc. The patterns for one system may have relevance for another, but could just as easily be completely incorrect.&lt;/p&gt;

&lt;p&gt;How hard it is to scale a system is going to depend on a lot of factors. Getting it wrong just happens to be the easiest option.&lt;/p&gt;&lt;div class=&quot;item_footer&quot;&gt;&lt;p&gt;&lt;small&gt;&lt;a href=&quot;http://blogs.lessthandot.com/index.php/Architect/DesigningSoftware/scalability-is-easy-to-get&quot;&gt;Original post&lt;/a&gt; blogged on &lt;a href=&quot;http://lessthandot.com/&quot;&gt;LessThanDot&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;/div&gt;</description>
			<content:encoded><![CDATA[<p>Scalability is easy, provided you don't need it to work.</p>

<p>Probably the number one failure of system scaling is when people dive right in and start building. No baselines, limited measurements, no analysis, just a hypothesis and a whole lot of late nights tweaking the system. With extra complexity comes extra costs, from the initial development through more expensive maintenance. Scale poorly and not only do we take on those extra complexity costs, but also the more obvious additional costs of the actual implementation (new servers, more resources, etc).</p>

<h2>The Somewhat Contrived Example</h2>

<p>Recently I've been working on a system to simulate parallelizing workloads, specifically workloads that depend on external resources with rate or load thresholds. Let's use it to look at a somewhat contrived example.</p>

<div style="background-color: #eeeeee; padding: 1em; margin: 1em;">
Note: For this post, the simulated "service" has a 100 request/minute limit and throttles individual clients for 15 second windows. Individual operations consist of 50ms of local processing and a single service request that has 50ms of latency and 100 ms for processing and response time. Similar results can be achieved with more realistic batch sizes and rates, the smaller values just allow me to more quickly produce samples for the blog post.
</div>

<p>So the backstory is that I have a batch process that is running more and more slowly as we take on larger and more frequent workloads. </p>

<p>I start by testing the batch process locally so I can see how slow it is before I make changes.</p>

<div style="text-align: center; font-size: .8em; color: #666666">
	<img src="http://tiernok.com/LTDBlog/Scalability/Graph_01.png" alt="Graph - 1 Client, 60 Requests, 100rpm Limit" /><br />
	1 Client, 60 Requests, 100rpm
</div>

<p>Locally it runs pretty quickly, but I'm betting that parallelizing the process will give me a significant increase in speed.</p>

<div style="text-align: center; font-size: .8em; color: #666666">
	<img src="http://tiernok.com/LTDBlog/Scalability/Graph_02.png" alt="Graph - 1 Client vs 30 Clients, 60 Requests, 100rpm Limit" /><br />
	1 Client vs 30 Clients, 60 Requests, 100rpm
</div>

<p>Look how well that performance improved, I achieved better than a 6x improvement in performance. My job here is done. </p>

<p>Except when I try to push this to production, I start getting a lot of errors. </p>

<div style="text-align: center; font-size: .8em; color: #666666">
	<img src="http://tiernok.com/LTDBlog/Scalability/Graph_03.png" alt="Graph - 30 Clients, 300 Requests, 100rpm - 67% Failure Rate" /><br />
	30 Clients, 300 Requests, 100rpm - 67% Failure Rate
</div>

<p>As it turns out, the external API my process saves the data to has a rate limit. When I exceed the allowable rate, I'm throttled for a short period of time. Any requests I make during that throttle period are returned with errors indicating I'm throttled.</p>

<p>Hmm. Luckily there are a number of common patterns available to retry these types of failures. I'll add an exponential back-off retry pattern so that when I get throttled my service will retry failed requests at slower rates until the service un-throttles me. While I've found plenty of code examples online, none of them seem to have recommendations, so I'll just use one of the sample settings they provide.</p>

<div style="text-align: center; font-size: .8em; color: #666666">
	<img src="http://tiernok.com/LTDBlog/Scalability/Graph_04.png" alt="Graph - 30 Clients, 300 Requests, 100rpm, Retry Policy #1 - 7% Failure Rate" /><br />
	30 Clients, 300 Requests, 100rpm, Retry Policy #1 - 7% Failure Rate
</div>

<p>Hmm, better. My failure rate has gone way down. What if I tweak the values?</p>

<div style="text-align: center; font-size: .8em; color: #666666">
	<img src="http://tiernok.com/LTDBlog/Scalability/Graph_05.png" alt="Graph - 30 Clients, 300 Requests, 100rpm, Retry Policy #2 - 29% Failure Rate" /><br />
	30 Clients, 300 Requests, 100rpm, Retry Policy #2 - 29% Failure Rate
</div>

<p>Oh, that was bad, I obviously was on the right track before. What if I just extend the retry amount a bit to try and knock out the last bit of errors. </p>

<div style="text-align: center; font-size: .8em; color: #666666">
	<img src="http://tiernok.com/LTDBlog/Scalability/Graph_06.png" alt="Graph - 30 Clients, 300 Requests, 100rpm, Retry Policy #1B - 0% Failure Rate" /><br />
	30 Clients, 300 Requests, 100rpm, Retry Policy #1B - 0% Failure Rate
</div>

<p>Ok, perfect. Now I have a system that is more than 6 times faster than the original, can be easily extended by throwing more workers at it, and is actually in a better position to handle occasional slow downs from my 3rd-party service. </p>

<p>Success!</p>

<h2>Where I Went Wrong</h2>
<p>Ok, so maybe not. Over the course of my little story I went wrong in a number of places. Even though this was a contrived example, I've watched very similar scenarios play out in a number of different organizations with real systems.</p>

<h3>The Bottleneck</h3>
<p>The first and most critical problem was that I didn't actually locate the bottleneck in my process, I simply tried to do more of the same. The <a href="http://en.wikipedia.org/wiki/Theory_of_constraints" title="Theory of Constraints at Wikipedia">Theory of Constraints</a> tells us that we can improve the rate of a process by identifying and exploiting the constraints. </p>

<p>In this system, the constraint looked like it was the sequential execution of the tasks, but in reality the constraint was the time it took to call the 3rd-party API. Had we identified that bottleneck before starting, we could have approached the problem differently.</p>

<div style="text-align: center; font-size: .8em; color: #666666">
	<img src="http://tiernok.com/LTDBlog/Scalability/ProcessChange.png" alt="Process - Alternative Design" /><br />
	Process - Alternative Design
</div>

<p>Rather than the parallel complexity, we can modify how the tasks are executed to try and take advantage of knowing where our bottleneck is. If the API allowed us to submit several requests in a batch, this redesign would net us several orders of magnitude improvement. Another option would be to run the results of the local processing into a queue and submit requests from there at a slow trickle, using only a percentage of our API limit so as not to disrupt any other real-time operations or batch processing the system supports. Another option we could take advantage of is not starting any of our expensive 3rd-party communications until we know that the entire job can actually be processed successfully through our local process.</p>

<p>Identifying the constraint unlocks the ability to turn the problem on it's head and achieve higher improvements, typically by orders of magnitude.</p>

<h3>The Math Error</h3>
<p>I concluded the scenario above by assuming I had found a good solution that also had a lot of headroom. Unfortunately what I actually did was find the ceiling. I have tuned the retry policy to 30 parallel systems, increasing that number could easily destabilize it further and cause more errors or delays. The headroom is, in fact, an illusion.</p>

<h3>The Evolving Assumption</h3>
<p>Somewhere along the way I found 30 clients to be a great improvement and didn't test other options. Then I made some assumptions about a retry policy. Then I tweaked that retry policy until the error rate disappeared. My assumptions made sense at the time, so I never questioned where they were leading me.</p>

<p>When I found a winning combination for my retry rate, I didn't realize I was missing other, better options:</p>

<div style="text-align: center; font-size: .8em; color: #666666">
	<img src="http://tiernok.com/LTDBlog/Scalability/Graph_07.png" alt="Graph - 30 Clients, 300 Requests, 100rpm, Retry Policy #1B vs 4A-C" /><br />
	30 Clients, 300 Requests, 100rpm, Retry Policy #1B vs 4A-C
</div>

<p>What's worse, is that trail of assumptions along the way was never re-validated. I concluded with a 6.5x improvement, but is that still accurate?</p>

<div style="text-align: center; font-size: .8em; color: #666666">
	<img src="http://tiernok.com/LTDBlog/Scalability/Graph_08.png" alt="Graph - 1-50 Clients, 300 Requests, 100rpm, Retry Policy #1B" /><br />
	1-50 Clients, 300 Requests, 100rpm, Retry Policy #1B
</div>

<p>When I run the same settings on a range of 1 to 50 clients, we can see that I lost that original 6x improvement along the way. All I have managed to do is add complexity and some very explicit costs for those additional systems.</p>

<p><i>Note: What happened to retry policy #3? Well originally 1B was actually named 3, then I decided to update the name halfway through the post but was too lazy to update all of the completed images. Oh well.</i></p>

<h2>Scaling the Wrong Thing</h2>
<p>This post used fairly small numbers, had I applied a larger workload, higher throughput rates, different throttling windows, the whole problem would have turned out differently. </p>

<p>When we set out to make a system scale, we need to identify the real scenarios we are trying to scale for and the bottlenecks that stand in our way. Blindly performance tuning can look like an improvement, but is really just a poor short term investment that often entrenches the current performance problems even more deeply. There are a lot of questions that should be asked about the intended result, responsiveness fo the system, other operations it has to support while under load, potential overlap of that load, the type of load, etc. The patterns for one system may have relevance for another, but could just as easily be completely incorrect.</p>

<p>How hard it is to scale a system is going to depend on a lot of factors. Getting it wrong just happens to be the easiest option.</p><div class="item_footer"><p><small><a href="http://blogs.lessthandot.com/index.php/Architect/DesigningSoftware/scalability-is-easy-to-get">Original post</a> blogged on <a href="http://lessthandot.com/">LessThanDot</a>.</small></p></div>]]></content:encoded>
								<comments>http://blogs.lessthandot.com/index.php/Architect/DesigningSoftware/scalability-is-easy-to-get#comments</comments>
			<wfw:commentRss>http://blogs.lessthandot.com/index.php/Architect/?tempskin=_rss2&#38;disp=comments&#38;p=1923</wfw:commentRss>
		</item>
				<item>
			<title>Converting a .Net Console Project to an Azure Worker Role Project</title>
			<link>http://blogs.lessthandot.com/index.php/DesktopDev/MSTech/converting-a-net-console-project</link>
			<pubDate>Wed, 07 Nov 2012 11:28:00 +0000</pubDate>			<dc:creator>Eli Weinstock-Herman (tarwn)</dc:creator>
			<category domain="main">Microsoft Technologies</category>			<guid isPermaLink="false">1886@http://blogs.lessthandot.com/</guid>
						<description>&lt;p&gt;So lets say you&#039;re building a worker role for Azure, but started it out as a Console app for faster local debugging. It comes time to deploy it to Azure for the first time, but there&#039;s no option to convert a Console application to a Worker Role project. We could copy all the code into a new project, but then we not only lose our faster debugging but also the history of commits we have made against the project. &lt;/p&gt;

&lt;p&gt;Luckily converting the existing Console project to be deployable as an Azure Worker Role project is fairly easy.&lt;/p&gt;

&lt;p&gt;For the purposes of this post, I have created a solution with an Existing Console project, an Azure Cloud Project, and an Existing Azure Worker Role project (we have to have at least one to create the Azure Cloud Project, it can be deleted later).&lt;/p&gt;

&lt;div class=&quot;font-size: 85%; color: #666666; text-align: center&quot;&gt;
&lt;img src=&quot;http://tiernok.com/LTDBlog/AzureWorkerRole/awr_01.png&quot; alt=&quot;Solution Explorer&quot; /&gt;&lt;br /&gt;
Solution Explorer view of the Sample Solution
&lt;/div&gt;

&lt;p&gt;If we right click the Azure &quot;Roles&quot; folder, the option to use an existing Worker Role project is not available. Visual Studio enables or disables this option automatically, based on whether we have any assignable projects in the solution that aren&#039;t already associated with the Azure project.&lt;/p&gt;

&lt;div class=&quot;font-size: 85%; color: #666666; text-align: center&quot;&gt;
&lt;img src=&quot;http://tiernok.com/LTDBlog/AzureWorkerRole/awr_02.png&quot; alt=&quot;Add Role menu options&quot; /&gt;&lt;br /&gt;
&quot;Worker Role Project in Solution&quot; is Disabled
&lt;/div&gt;

&lt;p&gt;The first thing we want to do is add a RoleEntryPoint to the console application. To keep this simple, I&#039;m going to convert the Program class to serve as the RoleEntryPoint also.&lt;/p&gt;

&lt;p&gt;To add the RoleEntryPoint class, I need to first add some azure references. I&#039;m using Azure 1.8, so this means I&#039;ll need the following 4 references:&lt;/p&gt;

&lt;div class=&quot;font-size: 85%; color: #666666; text-align: center&quot;&gt;
&lt;img src=&quot;http://tiernok.com/LTDBlog/AzureWorkerRole/awr_03.png&quot; alt=&quot;Assembly References Dialog&quot; /&gt;&lt;br /&gt;
Adding WindowsAzure References
&lt;/div&gt;

&lt;p&gt;&lt;i&gt;Note: The Storage SDK version number for Azure SDK 1.8 is 2.0. I suspect they chose to do this because they made a number of significant changes in the storage library that were not backwards compatible with 1.7.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Note #2: I noticed that if you add a new worker role through Visual Studio, it uses StorageClient 1.7 still despite this being SDK 1.8. This may be a requirement from the Azure Diagnostics assembly, Diagnostics uses StorageClient and may still be a version behind. I would test this theory, but getting Diagnostics working properly tends to be somewhat painful.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;After adding the references, we can then add RoleEntryPoint inheritance to the Program. New Worker Roles have two methods they override from RoleEntryPoint, but the important one is Run (and why this isn&#039;t abstract, I couldn&#039;t tell you). &lt;/p&gt;

&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;csharp&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;csharp&quot; id=&quot;cb86376&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;&lt;span style=&quot;color: #0600FF;&quot;&gt;namespace&lt;/span&gt; ExistingConsoleApplication&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #FF0000;&quot;&gt;class&lt;/span&gt; Program : RoleEntryPoint&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF;&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color: #0600FF;&quot;&gt;void&lt;/span&gt; Main&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#93;&lt;/span&gt; args&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #008080; font-style: italic;&quot;&gt;/* Console entry point */&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; var ibl = &lt;a href=&quot;http://www.google.com/search?q=new+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;new&lt;/span&gt;&lt;/a&gt; InterestingBusinessLogic&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ibl.&lt;span style=&quot;color: #0000FF;&quot;&gt;DoStuff&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Console.&lt;span style=&quot;color: #0000FF;&quot;&gt;Read&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #0600FF;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #0600FF;&quot;&gt;override&lt;/span&gt; &lt;span style=&quot;color: #0600FF;&quot;&gt;void&lt;/span&gt; Run&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&amp;nbsp; &lt;span style=&quot;color: #008080; font-style: italic;&quot;&gt;/* Worker Role entry point */&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; var ibl = &lt;a href=&quot;http://www.google.com/search?q=new+msdn.microsoft.com&quot;&gt;&lt;span style=&quot;color: #008000;&quot;&gt;new&lt;/span&gt;&lt;/a&gt; InterestingBusinessLogic&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ibl.&lt;span style=&quot;color: #0000FF;&quot;&gt;DoStuff&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb68727&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The last thing we need to do is add some information to the project file. I can open the file in Visual Studio by right clicking and selecting &quot;Unload Project&quot;, then right clicking again and selecting &quot;Edit &lt;i&gt;project name&lt;/i&gt;&quot;. In the Property Group I need to add a single property named &quot;RoleType&quot; to identify this as a Worker (see the last entry):&lt;/p&gt;

&lt;div class=&quot;codebox&quot;&gt;&lt;div class=&quot;codeheader&quot;&gt;Code: &lt;span&gt;xml&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;codeholder&quot;&gt;&lt;div class=&quot;xml&quot; id=&quot;cb87974&quot; style=&quot;display: block; color: rgb(0, 0, 0);&quot;&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;PropertyGroup&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;Configuration&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;Condition&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot; &#039;$(Configuration)&#039; == &#039;&#039; &amp;quot;&lt;/span&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;Debug&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/Configuration&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;Platform&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;Condition&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot; &#039;$(Platform)&#039; == &#039;&#039; &amp;quot;&lt;/span&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;AnyCPU&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/Platform&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;ProjectGuid&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;{4B7C48CB-9899-47D0-95AB-2FD3C3B739CF}&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/ProjectGuid&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;OutputType&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;Exe&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/OutputType&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;AppDesignerFolder&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;Properties&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/AppDesignerFolder&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;RootNamespace&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;ExistingConsoleApplication&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/RootNamespace&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;AssemblyName&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;ExistingConsoleApplication&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/AssemblyName&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;TargetFrameworkVersion&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;v4.5&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/TargetFrameworkVersion&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;FileAlignment&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;512&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/FileAlignment&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;RoleType&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;Worker&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/RoleType&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;lt;/PropertyGroup&lt;span style=&quot;font-weight: bold; color: black;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id=&quot;cb37519&quot; style=&quot;display: none; color: red;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Save and reload the project, and now when we right click on the Azure Cloud Project Roles, the option to associate and existing project is available.&lt;/p&gt;

&lt;div class=&quot;font-size: 85%; color: #666666; text-align: center&quot;&gt;
&lt;img src=&quot;http://tiernok.com/LTDBlog/AzureWorkerRole/awr_04.png&quot; alt=&quot;Add Role menu options&quot; /&gt;&lt;br /&gt;
&quot;Worker Role Project in Solution&quot; is Available Now
&lt;/div&gt;

&lt;p&gt;After adding the project, we can now run it either as a local console application or in the computer emulator as an emulated worker role.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Note: Don&#039;t forget that the compute emulator must run in elevated administrator mode.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;And there you have it, a Console project promoted to Azure Worker Role, preserving any history of commits that were made against the project and still runnable as either a console application or as a worker role.&lt;/p&gt;&lt;div class=&quot;item_footer&quot;&gt;&lt;p&gt;&lt;small&gt;&lt;a href=&quot;http://blogs.lessthandot.com/index.php/DesktopDev/MSTech/converting-a-net-console-project&quot;&gt;Original post&lt;/a&gt; blogged on &lt;a href=&quot;http://lessthandot.com/&quot;&gt;LessThanDot&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;/div&gt;</description>
			<content:encoded><![CDATA[<p>So lets say you're building a worker role for Azure, but started it out as a Console app for faster local debugging. It comes time to deploy it to Azure for the first time, but there's no option to convert a Console application to a Worker Role project. We could copy all the code into a new project, but then we not only lose our faster debugging but also the history of commits we have made against the project. </p>

<p>Luckily converting the existing Console project to be deployable as an Azure Worker Role project is fairly easy.</p>

<p>For the purposes of this post, I have created a solution with an Existing Console project, an Azure Cloud Project, and an Existing Azure Worker Role project (we have to have at least one to create the Azure Cloud Project, it can be deleted later).</p>

<div class="font-size: 85%; color: #666666; text-align: center">
<img src="http://tiernok.com/LTDBlog/AzureWorkerRole/awr_01.png" alt="Solution Explorer" /><br />
Solution Explorer view of the Sample Solution
</div>

<p>If we right click the Azure "Roles" folder, the option to use an existing Worker Role project is not available. Visual Studio enables or disables this option automatically, based on whether we have any assignable projects in the solution that aren't already associated with the Azure project.</p>

<div class="font-size: 85%; color: #666666; text-align: center">
<img src="http://tiernok.com/LTDBlog/AzureWorkerRole/awr_02.png" alt="Add Role menu options" /><br />
"Worker Role Project in Solution" is Disabled
</div>

<p>The first thing we want to do is add a RoleEntryPoint to the console application. To keep this simple, I'm going to convert the Program class to serve as the RoleEntryPoint also.</p>

<p>To add the RoleEntryPoint class, I need to first add some azure references. I'm using Azure 1.8, so this means I'll need the following 4 references:</p>

<div class="font-size: 85%; color: #666666; text-align: center">
<img src="http://tiernok.com/LTDBlog/AzureWorkerRole/awr_03.png" alt="Assembly References Dialog" /><br />
Adding WindowsAzure References
</div>

<p><i>Note: The Storage SDK version number for Azure SDK 1.8 is 2.0. I suspect they chose to do this because they made a number of significant changes in the storage library that were not backwards compatible with 1.7.</i></p>

<p><i>Note #2: I noticed that if you add a new worker role through Visual Studio, it uses StorageClient 1.7 still despite this being SDK 1.8. This may be a requirement from the Azure Diagnostics assembly, Diagnostics uses StorageClient and may still be a version behind. I would test this theory, but getting Diagnostics working properly tends to be somewhat painful.</i></p>

<p>After adding the references, we can then add RoleEntryPoint inheritance to the Program. New Worker Roles have two methods they override from RoleEntryPoint, but the important one is Run (and why this isn't abstract, I couldn't tell you). </p>

<div class="codebox"><div class="codeheader"><span>csharp</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb48632'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb48632','cb30531'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="csharp" id="cb48632" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1"><span style="color: #0600FF;">namespace</span> ExistingConsoleApplication</li><li style="" class="li2"><span style="color: #000000;">&#123;</span></li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">class</span> Program : RoleEntryPoint</li><li style="" class="li2">&nbsp; &nbsp; <span style="color: #000000;">&#123;</span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">static</span> <span style="color: #0600FF;">void</span> Main<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span><span style="color: #000000;">&#91;</span><span style="color: #000000;">&#93;</span> args<span style="color: #000000;">&#41;</span>&nbsp;<span style="color: #008080; font-style: italic;">/* Console entry point */</span></li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var ibl = <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> InterestingBusinessLogic<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ibl.<span style="color: #0000FF;">DoStuff</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li1">&nbsp;</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console.<span style="color: #0000FF;">Read</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span></li><li style="" class="li2">&nbsp;</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">override</span> <span style="color: #0600FF;">void</span> Run<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>&nbsp; <span style="color: #008080; font-style: italic;">/* Worker Role entry point */</span></li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span></li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var ibl = <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> InterestingBusinessLogic<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ibl.<span style="color: #0000FF;">DoStuff</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;</li><li style="" class="li1">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span></li><li style="" class="li2">&nbsp; &nbsp; <span style="color: #000000;">&#125;</span></li><li style="" class="li1"><span style="color: #000000;">&#125;</span></li></ol></div><div id="cb30531" style="display: none; color: red;"></div></div></div>

<p>The last thing we need to do is add some information to the project file. I can open the file in Visual Studio by right clicking and selecting "Unload Project", then right clicking again and selecting "Edit <i>project name</i>". In the Property Group I need to add a single property named "RoleType" to identify this as a Worker (see the last entry):</p>

<div class="codebox"><div class="codeheader"><span>xml</span><div class="codebox_javascript_links"><a href="http://blogs.lessthandot.com" onclick="linenumberOnOff('cb36788'); return false;">Line number Off</a> | <a href="http://blogs.lessthandot.com#" onclick="expandCode('cb36788','cb50246'); return false;">Hide</a> | <a href="http://blogs.lessthandot.com#" onclick="selectCode(this); return false;">Select all</a></div></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><div class="xml" id="cb36788" style="display: block; color: rgb(0, 0, 0);"><ol><li style="" class="li1"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;PropertyGroup<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li2">&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Configuration</span> <span style="color: #000066;">Condition</span>=<span style="color: #ff0000;">&quot; '$(Configuration)' == '' &quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span>Debug<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Configuration<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Platform</span> <span style="color: #000066;">Condition</span>=<span style="color: #ff0000;">&quot; '$(Platform)' == '' &quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span>AnyCPU<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Platform<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li2">&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;ProjectGuid<span style="font-weight: bold; color: black;">&gt;</span></span></span>{4B7C48CB-9899-47D0-95AB-2FD3C3B739CF}<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/ProjectGuid<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;OutputType<span style="font-weight: bold; color: black;">&gt;</span></span></span>Exe<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/OutputType<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li2">&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;AppDesignerFolder<span style="font-weight: bold; color: black;">&gt;</span></span></span>Properties<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/AppDesignerFolder<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;RootNamespace<span style="font-weight: bold; color: black;">&gt;</span></span></span>ExistingConsoleApplication<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/RootNamespace<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li2">&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;AssemblyName<span style="font-weight: bold; color: black;">&gt;</span></span></span>ExistingConsoleApplication<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/AssemblyName<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;TargetFrameworkVersion<span style="font-weight: bold; color: black;">&gt;</span></span></span>v4.5<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/TargetFrameworkVersion<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li2">&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;FileAlignment<span style="font-weight: bold; color: black;">&gt;</span></span></span>512<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/FileAlignment<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li1">&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;RoleType<span style="font-weight: bold; color: black;">&gt;</span></span></span>Worker<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/RoleType<span style="font-weight: bold; color: black;">&gt;</span></span></span></li><li style="" class="li2"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/PropertyGroup<span style="font-weight: bold; color: black;">&gt;</span></span></span></li></ol></div><div id="cb50246" style="display: none; color: red;"></div></div></div>

<p>Save and reload the project, and now when we right click on the Azure Cloud Project Roles, the option to associate and existing project is available.</p>

<div class="font-size: 85%; color: #666666; text-align: center">
<img src="http://tiernok.com/LTDBlog/AzureWorkerRole/awr_04.png" alt="Add Role menu options" /><br />
"Worker Role Project in Solution" is Available Now
</div>

<p>After adding the project, we can now run it either as a local console application or in the computer emulator as an emulated worker role.</p>

<p><i>Note: Don't forget that the compute emulator must run in elevated administrator mode.</i></p>

<p>And there you have it, a Console project promoted to Azure Worker Role, preserving any history of commits that were made against the project and still runnable as either a console application or as a worker role.</p><div class="item_footer"><p><small><a href="http://blogs.lessthandot.com/index.php/DesktopDev/MSTech/converting-a-net-console-project">Original post</a> blogged on <a href="http://lessthandot.com/">LessThanDot</a>.</small></p></div>]]></content:encoded>
								<comments>http://blogs.lessthandot.com/index.php/DesktopDev/MSTech/converting-a-net-console-project#comments</comments>
			<wfw:commentRss>http://blogs.lessthandot.com/index.php/DesktopDev/?tempskin=_rss2&#38;disp=comments&#38;p=1886</wfw:commentRss>
		</item>
				<item>
			<title>Hiding Outages is a Short Term Game</title>
			<link>http://blogs.lessthandot.com/index.php/ITProfessionals/RunningMyBusiness/hiding-outages-is-a-short</link>
			<pubDate>Mon, 29 Oct 2012 17:32:00 +0000</pubDate>			<dc:creator>Eli Weinstock-Herman (tarwn)</dc:creator>
			<category domain="alt">IT Service Management</category>
<category domain="main">Running My Own IT Business</category>			<guid isPermaLink="false">1878@http://blogs.lessthandot.com/</guid>
						<description>&lt;p&gt;&lt;strong&gt;5:20 PM&lt;/strong&gt; on Saturday night, looking for the correct size air filter at the local superstore. My phone dings and chirps, as I receive almost simultaneous email and twitter alerts; our production application can&#039;t talk to it&#039;s database. As a SaaS company, it rolls downhill. An unexpected outage with our application means an unexpected service outage for our customers. Time to head home and start troubleshooting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5:45 PM&lt;/strong&gt;. After logging into the service provider dashboard, I find that the database services tab is completely non-functional. Attempts to connect to the database from home also fails. Various other troubleshooting directions are followed and also meet in failure.&lt;/p&gt;

&lt;p&gt;And then some scheduled jobs in our development and staging environments kick off and also report database timeouts. It&#039;s getting increasingly unlikely that this is us, time to contact support.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6.45 PM&lt;/strong&gt;. Calling support leaves me in a hold queue that is experiencing &quot;longer than normal call volume&quot;. Maybe this isn&#039;t just me? I check the service status page and everything is green. Still waiting on hold. I check twitter and don&#039;t see any mentions. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7:10 PM&lt;/strong&gt;. Lets check the public forums...ah, there&#039;s a few other people with this problem. I add my own personal story so we can help flesh out the picture of what&#039;s going on. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7:15 PM&lt;/strong&gt;. 30 minutes into the hold queue and I just got transferred to a ringing phone. After seeing the forum post, I suspect I&#039;ll end up getting a canned &quot;We know there&#039;s a problem, we don&#039;t know what it is or when it will be fixed, thank you for all your money&quot; speech. So I&#039;m a little surprised when after two minutes of ringing the phone simply goes dead. &lt;/p&gt;

&lt;p&gt;By now I&#039;ve added a few tweets to twitter with the appropriate tags, started looking at the SLA information for the service, and generally just continue to waste my evening in front of the computer instead of spending time with my wife and two year old. &lt;/p&gt;

&lt;p&gt;And time passes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8:10 PM&lt;/strong&gt;. I&#039;ve been refreshing the status dashboard every 10 minutes since I first opened it but this is the first change. Red notifications show up, along with hourly messages going back in time to 5:11 PM. I add a note to the forum and a tweet for anyone else waiting for some word from our service provider. The messages are fairly generic and innocuous, admitting that some customers may experience outages with given services and regions. We apologize for the inconvenience.&lt;/p&gt;

&lt;p&gt;We couldn&#039;t be bothered to provide an update for 3 hours, but we apologize for the inconvenience.&lt;/p&gt;

&lt;p&gt;Your business has been down for three hours and there was no official announcement you could point your customers to, but we apologize for the inconvenience.&lt;/p&gt;

&lt;h2&gt;Admit Your Service Outages?&lt;/h2&gt;
&lt;p&gt;I would bet we have all worked with companies or products that go to great pains not to announce bugs or outages to their end users. After all, admitting an outage means that the people that didn&#039;t get affected will know about it too, and that looks bad.&lt;/p&gt;

&lt;p&gt;Maybe we&#039;re afraid of upsetting users that weren&#039;t online at the time, of losing customers, of warning off potential users, of providing inside information to our competitors, or getting negative press.&lt;/p&gt;

&lt;h3&gt;Been There...&lt;/h3&gt;

&lt;p&gt;I once worked with a manager that screened each outage email, broadcasting only the ones that he felt were important enough to be forwarded, which tended to be none of them. Our service levels improved amazingly in the short term. Unfortunately since we weren&#039;t keeping our users informed, each outage took longer to correct as we also fielded calls from end users thinking it was just a problem with their system. Which meant our mean time to fix outages went down and affected more people. Which meant that the overall public consensus of our service level got poorer, especially as people realized we were simply not reporting our outages anymore. &lt;/p&gt;

&lt;p&gt;We lost credibility. Our service levels were reduced to levels we had worked years to raise them from. The trust our end users extended to us was heavily impacted. &lt;/p&gt;

&lt;p&gt;Before that slow slide back into the mud, we had originally climbed out by being open about our outages. Every outage had been announced, often before we had a fix identified, with follow-ups when information was available. Users trusted us more because they could see us jumping on problems, hear us being honest and open with them, and see the problems getting taken care of. We didn&#039;t have to tell them how much things were improving, they saw it. &lt;/p&gt;

&lt;p&gt;But we stopped admitting our outages, and for a short time we looked even better. Then we looked far, far worse.&lt;/p&gt;

&lt;h3&gt;Pretending Doesn&#039;t Make It So&lt;/h3&gt;
&lt;p&gt;Hiding bad news to protect your image is a short term loan with major long term costs. Your statistics are broken, so justifying and performing root cause analysis is that much harder. You are limited in what you can ask or discuss with your customers, because each one has to be treated as a potential leak. Your support services are put under a lot of strain and probably built with a higher focus on cost reduction than quality of service.&lt;/p&gt;

&lt;p&gt;In short, all of the energy you are spending to look awesome is actually moving you further away and unlikely to be fooling your end users.&lt;/p&gt;

&lt;h2&gt;Back to Saturday Night&lt;/h2&gt;

&lt;p&gt;Saturday night, a well known service provider had an outage that shut down our business for 3 hours and 31 minutes. &lt;/p&gt;

&lt;p&gt;For 3 hours we were in the dark and then, when an update was provided, it was backdated to look like we had been kept in the loop the whole time. Countless hours were wasted as we and many other customers tried troubleshooting a problem that wasn&#039;t in our systems. The support center was overloaded (or just not responding). And at the end of the night a degree of credibility and trust was thrown away.&lt;/p&gt;

&lt;p&gt;Someone had an opportunity to shine, and instead chose to make a bad situation that much worse.&lt;/p&gt;&lt;div class=&quot;item_footer&quot;&gt;&lt;p&gt;&lt;small&gt;&lt;a href=&quot;http://blogs.lessthandot.com/index.php/ITProfessionals/RunningMyBusiness/hiding-outages-is-a-short&quot;&gt;Original post&lt;/a&gt; blogged on &lt;a href=&quot;http://lessthandot.com/&quot;&gt;LessThanDot&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;/div&gt;</description>
			<content:encoded><![CDATA[<p><strong>5:20 PM</strong> on Saturday night, looking for the correct size air filter at the local superstore. My phone dings and chirps, as I receive almost simultaneous email and twitter alerts; our production application can't talk to it's database. As a SaaS company, it rolls downhill. An unexpected outage with our application means an unexpected service outage for our customers. Time to head home and start troubleshooting.</p>

<p><strong>5:45 PM</strong>. After logging into the service provider dashboard, I find that the database services tab is completely non-functional. Attempts to connect to the database from home also fails. Various other troubleshooting directions are followed and also meet in failure.</p>

<p>And then some scheduled jobs in our development and staging environments kick off and also report database timeouts. It's getting increasingly unlikely that this is us, time to contact support.</p>

<p><strong>6.45 PM</strong>. Calling support leaves me in a hold queue that is experiencing "longer than normal call volume". Maybe this isn't just me? I check the service status page and everything is green. Still waiting on hold. I check twitter and don't see any mentions. </p>

<p><strong>7:10 PM</strong>. Lets check the public forums...ah, there's a few other people with this problem. I add my own personal story so we can help flesh out the picture of what's going on. </p>

<p><strong>7:15 PM</strong>. 30 minutes into the hold queue and I just got transferred to a ringing phone. After seeing the forum post, I suspect I'll end up getting a canned "We know there's a problem, we don't know what it is or when it will be fixed, thank you for all your money" speech. So I'm a little surprised when after two minutes of ringing the phone simply goes dead. </p>

<p>By now I've added a few tweets to twitter with the appropriate tags, started looking at the SLA information for the service, and generally just continue to waste my evening in front of the computer instead of spending time with my wife and two year old. </p>

<p>And time passes.</p>

<p><strong>8:10 PM</strong>. I've been refreshing the status dashboard every 10 minutes since I first opened it but this is the first change. Red notifications show up, along with hourly messages going back in time to 5:11 PM. I add a note to the forum and a tweet for anyone else waiting for some word from our service provider. The messages are fairly generic and innocuous, admitting that some customers may experience outages with given services and regions. We apologize for the inconvenience.</p>

<p>We couldn't be bothered to provide an update for 3 hours, but we apologize for the inconvenience.</p>

<p>Your business has been down for three hours and there was no official announcement you could point your customers to, but we apologize for the inconvenience.</p>

<h2>Admit Your Service Outages?</h2>
<p>I would bet we have all worked with companies or products that go to great pains not to announce bugs or outages to their end users. After all, admitting an outage means that the people that didn't get affected will know about it too, and that looks bad.</p>

<p>Maybe we're afraid of upsetting users that weren't online at the time, of losing customers, of warning off potential users, of providing inside information to our competitors, or getting negative press.</p>

<h3>Been There...</h3>

<p>I once worked with a manager that screened each outage email, broadcasting only the ones that he felt were important enough to be forwarded, which tended to be none of them. Our service levels improved amazingly in the short term. Unfortunately since we weren't keeping our users informed, each outage took longer to correct as we also fielded calls from end users thinking it was just a problem with their system. Which meant our mean time to fix outages went down and affected more people. Which meant that the overall public consensus of our service level got poorer, especially as people realized we were simply not reporting our outages anymore. </p>

<p>We lost credibility. Our service levels were reduced to levels we had worked years to raise them from. The trust our end users extended to us was heavily impacted. </p>

<p>Before that slow slide back into the mud, we had originally climbed out by being open about our outages. Every outage had been announced, often before we had a fix identified, with follow-ups when information was available. Users trusted us more because they could see us jumping on problems, hear us being honest and open with them, and see the problems getting taken care of. We didn't have to tell them how much things were improving, they saw it. </p>

<p>But we stopped admitting our outages, and for a short time we looked even better. Then we looked far, far worse.</p>

<h3>Pretending Doesn't Make It So</h3>
<p>Hiding bad news to protect your image is a short term loan with major long term costs. Your statistics are broken, so justifying and performing root cause analysis is that much harder. You are limited in what you can ask or discuss with your customers, because each one has to be treated as a potential leak. Your support services are put under a lot of strain and probably built with a higher focus on cost reduction than quality of service.</p>

<p>In short, all of the energy you are spending to look awesome is actually moving you further away and unlikely to be fooling your end users.</p>

<h2>Back to Saturday Night</h2>

<p>Saturday night, a well known service provider had an outage that shut down our business for 3 hours and 31 minutes. </p>

<p>For 3 hours we were in the dark and then, when an update was provided, it was backdated to look like we had been kept in the loop the whole time. Countless hours were wasted as we and many other customers tried troubleshooting a problem that wasn't in our systems. The support center was overloaded (or just not responding). And at the end of the night a degree of credibility and trust was thrown away.</p>

<p>Someone had an opportunity to shine, and instead chose to make a bad situation that much worse.</p><div class="item_footer"><p><small><a href="http://blogs.lessthandot.com/index.php/ITProfessionals/RunningMyBusiness/hiding-outages-is-a-short">Original post</a> blogged on <a href="http://lessthandot.com/">LessThanDot</a>.</small></p></div>]]></content:encoded>
								<comments>http://blogs.lessthandot.com/index.php/ITProfessionals/RunningMyBusiness/hiding-outages-is-a-short#comments</comments>
			<wfw:commentRss>http://blogs.lessthandot.com/index.php/ITProfessionals/?tempskin=_rss2&#38;disp=comments&#38;p=1878</wfw:commentRss>
		</item>
			</channel>
</rss>
