Friday, July 16, 2010

Getting the Content-Type from your Registry

For Episode 19 of the Cloud Cover show, Steve and I discussed the importance of setting the Content-Type on your blobs in Windows Azure blob storage.  This was was especially important for Silverlight clients.  I mentioned that there was a way to look up a Content Type from your registry as opposed to hardcoding a list.  The code is actually pretty simple.  I pulled this from some code I had lying around that does uploads. 

Here it is:

private static string GetContentType(string file)
{
	string contentType = "application/octet-stream";
	string fileExt = System.IO.Path.GetExtension(file).ToLowerInvariant();
	RegistryKey fileExtKey = Registry.ClassesRoot.OpenSubKey(fileExt);
	if (fileExtKey != null && fileExtKey.GetValue("Content Type") != null)
	{
		contentType = fileExtKey.GetValue("Content Type").ToString();
	}
	return contentType;
}

Thursday, July 08, 2010

Measure What Matters

I remember when I was in consulting some years ago now.  At the time, I was a fairly senior technical resource and I had a pretty wide variety of clients and scenarios under my belt.  I was... experienced.

Anyhow, as a consultant it is pretty common to be interviewed by your potential client before arriving.  Clients don't like to have total n00bs on the job if they are paying consulting rates.  I used to have a number of these sort of interviews before being accepted to work on a project.

Even though I forget exactly now which client it was that interviewed me, I still remember the interview.  At the time, .NET 1.1 was the norm and 2.0 was in beta or so.  I was interviewing for a technical position on corporate account - architect or senior dev, if I recall correctly.  The customer got me on a conference call and I breezed through the background portion of the interview.  Next came the 'technical' interview.  I apparently got some young buck, fresh from his MSCD.NET exam that decided to test me on .NET trivia.  After answering a number of general .NET questions correctly, he asked me two questions that stick in my mind:

  • What does 'private internal' mean?
  • If you were to throw a custom exception in .NET, how would you do it?

Now, I said at the time that I wasn't sure on the first one and that I thought it might be both private and internal visibility.  The interviewer delighted in telling me it was private OR internal (the UNION of the two).  For the next question, I said I would simply derive from Exception and do what I needed.  The interviewer again (with 'Aha!' in his voice) told me that (of course) I should derive from ApplicationException.

I was passed over for the role for not being technical enough.

Now, in retrospect, it is laughable.  First, you only need to be told once what something means in order for it to stick.  Next, it turns out I was right on the second one.  The interviewer was so caught up on catching me on what I didn't know that he never considered if it mattered.  To this day, I have never seen a single instance of using "private internal" on anything - ever.  Furthermore, he ignored the fact that I had a vast amount of experience in his industry and had demonstrated enough .NET knowledge to determine I wasn't joking when I said I had coded in it.

It would have been much better to ask meaningful questions that actually test what matters (in this case systems thinking):

  • When and why would you use a private and internal visible declaration - a.k.a. 'private internal'?
  • Why would you throw a custom exception in .NET?  When do you throw exceptions?

Those kinds of questions get much deeper into the psyche of the developer and let you understand what kind of developer you are dealing with.

I contrast this with my Microsoft interview.  I had one of the most intimidating interviews ever with Vittorio.  He asked me (paraphrasing), "How would you design Twitter?  Take some time and think about it - trivial answers without consideration will not bode well for you".  It was beautiful in hindsight.  I got to tell him about the architectural considerations that I thought mattered and in broad strokes what I thought about.  It must have worked - we are now on the same team and he is a good colleague and friend.  Had he asked me about advanced threading or WCF bindings, I might not have 'passed' his exam.  Turns out that those topics don't matter for the job.  He asked exactly what did matter - could I think about systems as a whole and I did I have enough understanding of the pieces?

Next time you interview someone, make sure you measure what matters.

Friday, June 11, 2010

PowerScripting Podcast

Last week, I had the opportunity to talk with Hal and Jonathan on the PowerScripting podcast about Windows Azure.  It was a fun chat - lots on Windows Azure, a bit on the WASM cmdlets and MMC, and it revealed my favorite comic book character.

Listen to it now.

Friday, May 28, 2010

Hosting WCF in Windows Azure

This post is a bit overdue:  Steve threatened to blog it himself, so I figured I should get moving.  In one of our Cloud Cover episodes, we covered how to host WCF services in Windows Azure.  I showed how to host both publically accessible ones as well as how to host internal WCF services that are only visible within a hosted service.

In order to host an internal WCF Service, you need to setup an internal endpoint and use inter-role communication.  The difference between doing this and hosting an external WCF service on an input endpoint is mainly in the fact that internal endpoints are not load-balanced, while input endpoints are hooked to the load-balancer.

Hosting an Internal WCF Service

Here you can see how simple it is to actually get the internal WCF service up and listening.  Notice that the only thing that is different is that the base address I pass to my ServiceHost contains the internal endpoint I created.  Since the port and IP address I am running on is not known until runtime, you have to create the host and pass this information in dynamically.

public override bool OnStart()
{
    // Set the maximum number of concurrent connections 
    ServicePointManager.DefaultConnectionLimit = 12;
    DiagnosticMonitor.Start("DiagnosticsConnectionString");
    // For information on handling configuration changes
    // see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.
    RoleEnvironment.Changing += RoleEnvironmentChanging;
    StartWCFService();
    return base.OnStart();
}
private void StartWCFService()
{
    var baseAddress = String.Format(
        "net.tcp://{0}",
        RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["EchoService"].IPEndpoint
        );
    var host = new ServiceHost(typeof(EchoService), new Uri(baseAddress));
    host.AddServiceEndpoint(typeof(IEchoService), new NetTcpBinding(SecurityMode.None), "echo");
    host.Open();
}

Consuming the Internal WCF Service

From another role in my hosted service, I want to actually consume this service.  From my code-behind, this was all the code I needed to actually call the service.

protected void Button1_Click(object sender, EventArgs e)
{
    var factory = new ChannelFactory<WorkerHost.IEchoService>(new NetTcpBinding(SecurityMode.None));
    var channel = factory.CreateChannel(GetRandomEndpoint());
    Label1.Text = channel.Echo(TextBox1.Text);
}
private EndpointAddress GetRandomEndpoint()
{
    var endpoints = RoleEnvironment.Roles["WorkerHost"].Instances
        .Select(i => i.InstanceEndpoints["EchoService"])
        .ToArray();
    var r = new Random(DateTime.Now.Millisecond);
    return new EndpointAddress(
        String.Format(
            "net.tcp://{0}/echo",
            endpoints[r.Next(endpoints.Count() - 1)].IPEndpoint)
            );
}

The only bit of magic here was querying the fabric to determine all the endpoints in the WorkerHost role that implemented the EchoService endpoint and routing a request to one of them randomly.  You don't have to route requests randomly per se, but I did this because internal endpoints are not load-balanced.  I wanted to distribute the load evenly over each of my WorkerHost instances.

One tip that I found out is that there is no need to cache the IPEndpoint information you find.  It is already cached in the API call.  However, you may want to cache your ChannelFactory according to best practices (unlike me).

Hosting Public WCF Services

This is all pretty easy as well.  The only trick to this is that you need to apply a new behavior that knows how to deal with the load balancer for proper MEX endpoint generation.  Additionally, you need to include a class attribute on your service to deal with an address filter mismatch issue.  This is pretty well documented along with links to download the QFE that contains the behavior patch out on the WCF Azure Samples project on Code Gallery in Known Issues. Jim Nakashima actually posted about this the other day as well in detail on his blog as well, so I won't dig into this again here.

Lastly, if you just want the code from the show, have at it!

Monday, May 10, 2010

Windows Azure MMC v2 Released

I am happy to announce the public release of the Windows Azure MMC - May Release.  It is a very significant upgrade to the previous version on Code Gallery.  So much, in fact, I tend to unofficially call it v2 (it has been called the May Release on Code Gallery).  In addition to all-new and faster storage browsing capabilities, we have added service management as well as diagnostics support.  We have also rebuilt the tool from the ground up to support extensibility.  You can replace or supplement our table viewers, log viewers, and diagnostics tooling with your own creation.

This update has been in the pipeline for a very long time.  It was actually finished and ready to go in late January.  Given the amount of code however that we had to invest to produce this tool, we had to go through a lengthy legal review and produce a new EULA.  As such, you may notice that we are no longer offering the source code in this release to the MMC snap-in itself.  Included in this release is the source for the WASM cmdlets, but not for the MMC or the default plugins.  In the future, we hope to be able to release the source code in its entirety.

 

Features At A Glance:

 

hosted_services Hosted Services Upload / configure / control / upgrade / swap / remove Windows Azure application deployments
diagnostics Diagnostics Configure instrumentation for Windows Azure applications (diagnostics) per source (perf counters, file based, app logs, infrastructure logs, event logs).   Transfer the diagnostic data on-demand or scheduled.

View / Analyze / Export to Excel and Clear instrumentation results.

certificates Certificates Upload / manage certificates for Windows Azure applications
storage_services Storage Services Configure Storage Services for Windows Azure applications
blobs BLOBs and Containers Add / Upload / Download / Remove BLOBs and Containers and connect to multiple storage accounts
queues Queues Add / Purge / Delete Windows Azure Queues
tables Tables Query and delete Windows Azure Tables
extensibility Extensibility Create plugins for rich diagnostics data visualization (e.g. add your own visualizer for performance counters). Create plugins for table viewers and editors or add completely new modules!  Plugin Engine uses MEF (extensibility framework) to easily add functionality.

powershell PowerShell-based backend The backend is based on PowerShell cmdlets. If you don't like our UI, you can still use the underlying cmdlets and script out anything we do

 

How To Get Started:

There are so many features and updates in this release that I have prepared a very quick 15-min screencast on the features and how to get started managing your services and diagnostics in Windows Azure today!

Wednesday, April 21, 2010

Last Week of Parental Leave

I have been largely offline for the last 3 weeks because I have been on parental leave (again).  I was lucky enough to have another baby girl last December right around Christmas.  Working for Microsoft, this means that within the first year, you can take 4 weeks off to be at home with your new baby.  It is a terrific benefit.  Hence, for the last 3 weeks I have been largely caring for my youngest alone while her older sister is at daycare.  What a unique bonding experience - it is something that has been wonderful.

Priya 

Sisters

Anyhow, I will be back to work next week and I know that I will miss my time here.  It has gone by far too fast.

Thursday, March 04, 2010

Calculating the Size of Your SQL Azure Database

In Episode 3 of Cloud Cover, I mentioned the tip of the week was how to measure your database size in SQL Azure.  Here is the exact queries you can run to do it:

select
      sum(reserved_page_count) * 8.0 / 1024
from
      sys.dm_db_partition_stats
GO

select
      sys.objects.name, sum(reserved_page_count) * 8.0 / 1024
from
      sys.dm_db_partition_stats, sys.objects
where
      sys.dm_db_partition_stats.object_id = sys.objects.object_id

group by sys.objects.name

The first one will give you the size of your database in MB and the second one will do the same, but break it out for each object in your database.

Hat tip to David Robinson and Tony Petrossian on the SQL Azure team for the query.

Wednesday, February 17, 2010

WASM Cmdlets Updated

image

I am happy to announce the updated release of the Windows Azure Service Management (WASM) Cmdlets for PowerShell today. With these cmdlets you can effectively automate and manage all your services in Windows Azure. Specifically,

  • Deploy new Hosted Services
    • Automatically upload your packages from the file system to blob storage.
  • Upgrade your services
    • Choose between automatic or manual rolling upgrades
    • Swap between staging and production environments
  • Remove your Hosted Services
    • Automatically pull down your services at the end of the day to stop billing. This is a critical need for test and development environments.
  • Manage your Storage accounts
    • Retrieve or regenerate your storage keys
  • Manage your Certificates
    • Deploy certificates from your Windows store or the local filesystem
  • Configure your Diagnostics
    • Remotely configure the event sources you wish to monitor (Event Logs, Tracing, IIS Logs, Performance Counters and more)
  • Transfer your Diagnostics Information
    • Schedule your transfers or Transfer on Demand.

clip_image003

Why did we build this?

The WASM cmdlets were built to unblock adoption for many of our customers as well as serve as a common underpinning to our labs and internal tooling. There was an immediate demand for an automation API that would fit into the standard toolset for IT Pros. Given the adoption and penetration of PowerShell, we determined that cmdlets focused on this core audience would be the most effective way forward. Furthermore, since PowerShell is a full scripting language with complete access to .NET, this allows these cmdlets to be used as the basis for very complicated deployment and automation scripts as part of the application lifecycle.

How can you use them?

Every call to the Service Management API requires an X509 certificate and the subscription ID for the account. To get started, you need to upload a valid certificate to the portal and have it installed locally to your workstation. If you are unfamiliar with how to do this, you can follow the procedure outlined on the Windows Azure Channel9 Learning Center here.

Here are a few examples of how to use the cmdlets for a variety of common tasks:

Common Setup

Each script referenced below will refer to the following variables:

Add-PSSnapin AzureManagementToolsSnapIn

#get your local certificate for authentication

$cert = Get-Item cert:\CurrentUser\My\<YourThumbPrint>

#subID from portal

$sub = 'c9f9b345-7ff5-4eba-9d58-0cea5793050c'

#your service name (without .cloudapp.net)

$service = 'yourservice'

#path to package (can also be http: address in blob storage)

$package = "D:\deploy\MyPackage.cspkg"

#configuration file

$config = "D:\deploy\ServiceConfiguration.cscfg"

 

Listing My Hosted Services

Get-HostedServices -SubscriptionId $sub -Certificate $cert

 

View Production Service Status

Get-HostedService $service -SubscriptionId $sub -Certificate $cert |

Get-Deployment 'Production' |

select RoleInstanceList -ExpandProperty RoleInstanceList |

ft InstanceName, InstanceStatus -GroupBy RoleName

 

Creating a new deployment

#Create a new Deployment

Get-HostedService $service -SubscriptionId $sub -Certificate $cert |

New-Deployment -Slot Production -Package $package -Configuration $config -Label 'v1' |

Get-OperationStatus -WaitToComplete

#Set the service to 'Running'

Get-HostedService $service -SubscriptionId $sub -Certificate $cert |

Get-Deployment 'Production'|

Set-DeploymentStatus 'Running' |

Get-OperationStatus -WaitToComplete

 

Removing a deployment

#Ensure that the service is first in Suspended mode

Get-HostedService $service -SubscriptionId $sub -Certificate $cert |

Get-Deployment 'Production'|

Set-DeploymentStatus 'Suspended' |

Get-OperationStatus -WaitToComplete |

#Remove the deployment

Get-HostedService $service -SubscriptionId $sub -Certificate $cert |

Get-Deployment 'Production'|

Remove-Deployment

 

Upgrading a single Role

Get-HostedService $servicename -Certificate $cert -SubscriptionId $sub |

Get-Deployment -Slot Production |

Set-Deployment -mode Auto -roleName 'WebRole1' -package $package -label 'v1.2' |

Get-OperationStatus -WaitToComplete

 

Adding a local certificate

$deploycert = Get-Item cert:\CurrentUser\My\CBF145B628EA06685419AEDBB1EEE78805B135A2

Get-HostedService $service -SubscriptionId $sub -Certificate $cert |

Add-Certificate -CertificateToDeploy $deploycert |

Get-OperationStatus -WaitToComplete

 

Configuring Diagnostics - Adding a Performance Counter to All Running Instances

#get storage account name and key

$storage = "yourstorageaccount"

$key = (Get-StorageKeys -ServiceName $storage -Certificate $cert `

    -SubscriptionId $sub).Primary

 

$deployId = (Get-HostedService $service -SubscriptionId $sub `

    -Certificate $cert | Get-Deployment Production).DeploymentId

 

$counter = '\Processor\(_Total)\% Processor Time'

$rate = [TimeSpan]::FromSeconds(5)

 

Get-DiagnosticAwareRoles -StorageAccountName $storage -StorageAccountKey $key `

-DeploymentId $deployId |

foreach {

    $role = $_

    Get-DiagnosticAwareRoleInstances $role -DeploymentId $deployId `

    -StorageAccountName $storage -StorageAccountKey $key |

    foreach {

        $instance = $_

        $config = Get-DiagnosticConfiguration -RoleName $role -InstanceId $_ `

            -StorageAccountName $storage -StorageAccountKey $key `

            -BufferName PerformanceCounters -DeploymentId $deployId

        $perf = New-Object Microsoft.WindowsAzure.Diagnostics.PerformanceCounterConfiguration `

            -Property @{CounterSpecifier=$counter; SampleRate=$rate}

        $config.DataSources.Add($perf)

        $config.DataSources |

         foreach {

             Set-PerformanceCounter -PerformanceCounters $_ -RoleName $role `

             -InstanceId $instance -DeploymentId $deployId -StorageAccountName $storage `

             -StorageAccountKey $key

         }

    }   

}

More Examples

You can find more examples and documentation on these cmdlets by typing 'Get-Help <cmdlet> -full' from the PowerShell cmd prompt.

If you have any questions for feedback, please send it directly to me through the blog (look at right hand navigation pane for Contact Ryan link).

The Collectible Edition of Our Book

Occasionally, I will check online to see the reviews for our book.  It is now almost 4 years old and a bit outdated with respect to the changes that came with .NET 3.5.  The website and forums however has been trucking along (thanks Joe!) these years.  We never sold a ton of books about this particular niche topic, but for the audience size, it wasn't too shabby.  Joe and I are not about to retire on our royalties, however.

I was a bit surprised to see this online however at Amazon:

image

Now, it is a bit silly for two reasons, a.) our book as a collectible, really?  Who would actually collect it?  and b.) It says it was signed by both authors.  Now, there is a slight chance it is authentic as I think Joe and I signed maybe 2 books together ever.  However, the odds of it being authentic are exceedingly slim.  Who knows. it's funny regardless.

ADAM on Windows 7

One of my most popular posts to this day is the hack to install ADAM (now called AD LDS) on Vista.  It is the source of numerous emails as well.  So today, I am happy to say that AD LDS (aka ADAM) is available for Windows 7 officially - no hacks needed.

Download it here

Now, I fully realize this doesn't help those that are using Vista today, but there are quite a few folks that are using Windows 7 or upgrading from Vista or XP to 7.  LDAP directories are fabulous tools and AD LDS is a great one.  Enjoy.