Friday, July 16, 2010
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
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
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
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
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 | Upload / configure / control / upgrade / swap / remove Windows Azure application deployments
|
| 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 | Upload / manage certificates for Windows Azure applications |
| Storage Services | Configure Storage Services for Windows Azure applications |
| BLOBs and Containers | Add / Upload / Download / Remove BLOBs and Containers and connect to multiple storage accounts
|
| Queues | Add / Purge / Delete Windows Azure Queues |
| Tables | Query and delete Windows Azure Tables |
| 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-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
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.
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
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
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.

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).
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:
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.
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.