Monday, February 20, 2012

Fixing Default Date issues in Azure Table Storage

In newer versions of Azure, the minimum acceptable date in Table Storage is far further in the future than the minimum date in .NET. This means that if you have a DateTime property and you don't explicitly initialize it you will get a "One of the request inputs is out of range" error. Personally, I'd rather not have to explicitly initialize every value. I liked in previous versions of Azure, when it would just default to the DateTime.MinDate and everything was fine.

An easy way to manage this is to reset the default date for any DateTime properties before writing to Azure Table Storage. The way I chose to do this was to add a function to the WritingEntity event in the table context. See the code below:


public class SafeDateContext : TableServiceContext
{
private static MinAzureUtcDate = new DateTime(1601, 1, 1, 0, 0, 0, DateTimeKind.Utc);

public SafeDateContext(CloudStorageAccount account)
: base(account.TableEndpoint.ToString(), account.Credentials)
{
WritingEntity += new EventHandler(FixDates);
}

private void FixDates(ReadingWritingEntityEventArgs e)
{
// The XML of the properties already being sent to Azure
XElement properties = e.Data.Descendants(Meta + "properties").First();

foreach (var p in properties.Elements())
{
string type = p.Attribute(Meta + "type") == null ? null : p.Attribute(Meta + "type").Value;
bool isNull = string.Equals("true", p.Attribute(Meta + "null") == null ? null : p.Attribute(Meta + "null").Value, StringComparison.OrdinalIgnoreCase);
if (!isNull && type == "Edm.DateTime")
{
string value = p.Value;
DateTime dateValue = (DateTime)ConvertType(type, value, isNull);
if (dateValue < MinAzureUtcDate)
{
p.SetValue(MinAzureUtcDate);
}
}
}
}

Wednesday, February 1, 2012

Azure Plugin Modules

UPDATE: A response from Microsoft was received at my post on the MSDN forums. Essentially the answer was: You shouldn't do this. I leave this here for you to review at your own risk. I submitted a feature request, but I'm not holding my breath.

I've been working with Azure for over a year now, and I've always had the question: How can I create my own modules along the lines of the Diagnostics or RemoteAccess modules. There is one major reason I want this. I have created 3 Azure services, with a total of 7 roles. Many of these roles have things in common. All of them use a setting called ConnectionString. Many of them have other connection strings in common if they are using a particular library that I created myself. What I would like to be able to do is import the connection strings for a library as simply as possible whenever I am using that library.

This is where the "Import" node in the ServiceDefinition.csdef file SHOULD come in handy. For example, if you add the Diagnostics module in ServiceDefinition.csdef it automatically pulls the necessary configuration settings into ServiceConfiguration.csdef. I would like similar functionality to create my own modules. Periodic Google searches over the past year have come up empty every time. Today I tried to do a bit more of a direct search and made some discoveries.

Azure Role Modules are defined in the Windows Azure SDK folder under the bin/plugins directory. There is a folder for each plugin, and inside each is an XML file with the extension .csplugin. For example, here is the XML for the Diagnostics.csplugin file:


<?xml version="1.0" ?>
<RoleModule
xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition"
namespace="Microsoft.WindowsAzure.Plugins.Diagnostics">
<Startup priority="-2">
<Task commandLine="DiagnosticsAgent.exe" executionContext="limited" taskType="background" />
<Task commandLine="DiagnosticsAgent.exe /blockStartup" executionContext="limited" taskType="simple" />
</Startup>
<ConfigurationSettings>
<Setting name="ConnectionString" />
</ConfigurationSettings>
</RoleModule>

It turns out you use this format to create your own plugins. For example, I created a plugin that looked like the following:


<?xml version="1.0" ?>
<RoleModule
xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition"
namespace="MyLib.Azure.Plugins.MyModule">
<ConfigurationSettings>
<Setting name="ConnectionString" />
<Setting name="OtherSetting" />
</ConfigurationSettings>
</RoleModule>


To do this:
  1. Create a new folder in the Windows Azure SDK folder under bin/plugins called PluginName
  2. Create a new file called PluginName.csplugin
  3. Paste in the XML above.
  4. Rename the namespace to whatever you would like it to be.
  5. Set the ConfigurationSettings section to what you would like it to be.
Now, when you import PluginName in your ServiceDefinition.csdef file, it will automatically pull up the configuration settings you added into the ServiceConfiguration.cscfg file.

Here are some problems I can foresee with this:
  1. It is likely not supported by Microsoft, since I could not find documentation on it anywhere.
  2. When you update Azure, it will likely overwrite or delete the plugins directory and you will lose this.
I'm not sure whether I'm going to put this into practice at work or not, but I thought I'd post it in any case so that if anyone else searches for an answer to this they'll get more results than I did.