Azure Tables: Create/Delete example

2008-12-08 @ 15:52#

ok, after some on-and-off poking around w/ Azure Storage, i finally got to the point where i can create and delete tables! along the way, i uncovered a minor bug (an omission, really) in the MSDN documentation for Create Table. turns out the <updated /> element cannot be null (as indicated on the docs). of course, i compounded my problem by first using the *wrong* string format for the date-time. but once i got a hint from the forum-meisters, i was all set.

the full story is in this thread on the MSDN Azure forums.

below is a complete stand-alone console app that handles creating a table in your Azure Storage space. you'll need to supply your project name, sharedkey, and the new table name for this to work.

using System; 
using System.Text; 
using System.Web; 
using System.Net; 
using System.IO; 
using System.Security.Cryptography; 
 
namespace CreateTable 
{ 
  class Program 
  { 
    static void Main(string[] args) 
    { 
      // supply for your account 
      string account = "*** yourProjectName"; 
      string sharedKey = "*** yourSharedKey"; 
      string tableName = "*** yourNewTableName";
      // supply for your account 
 
      string endPoint = string.Format("http://{0}.table.core.windows.net", account); 
      string contentType = "application/atom+xml"; 
      string keyType = "SharedKey"; 
      string contentMD5 = string.Empty; 
      string fmtHeader = "{0} {1}:{2}"; 
      string fmtStringToSign = "{0}\n{1}\n{2}\n{3:R}\n{4}"; 
 
      string authValue = string.Empty; 
      string sigValue = string.Empty; 
      string authHeader = string.Empty; 
      string method = string.Empty; 
      string rtnBody = string.Empty; 
      string reqBody = string.Empty; 
 
      string canonicalResource = string.Format("/{0}/{1}", account, "Tables"); 
      string requestUrl = string.Format("{0}/{1}", endPoint, "Tables"); 
      DateTime requestDate = DateTime.UtcNow; 
 
      method = "POST"; 
      reqBody = string.Format(createTableXml, requestDate, tableName); 
      contentMD5 = MD5(reqBody);
       
      authValue = string.Format(fmtStringToSign, method, contentMD5, contentType, requestDate, canonicalResource); 
      sigValue = MacSha(authValue, Convert.FromBase64String(sharedKey)); 
      authHeader = string.Format(fmtHeader, keyType, account, sigValue); 
 
      try 
      { 
        WebRequest req = WebRequest.Create(requestUrl); 
        req.Headers.Add("content-md5", contentMD5); 
        req.Headers.Add("x-ms-date", string.Format("{0:R}", requestDate)); 
        req.Headers.Add("authorization", authHeader); 
        req.ContentType = contentType; 
        req.ContentLength = reqBody.Length; 
        req.Method = method; 
 
        using (StreamWriter sw = new StreamWriter(req.GetRequestStream())) 
        { 
          sw.Write(reqBody); 
          sw.Close(); 
        } 
 
        WebResponse resp = req.GetResponse(); 
        using (StreamReader sr = new StreamReader(resp.GetResponseStream(), true)) 
        { 
          rtnBody = sr.ReadToEnd(); 
          sr.Close(); 
        } 
        Console.WriteLine(rtnBody); 
      } 
      catch (WebException wex) 
      { 
        if (wex.Status == WebExceptionStatus.ProtocolError) 
        { 
          HttpWebResponse wrsp = (HttpWebResponse)wex.Response; 
          Console.WriteLine(string.Format("ERROR: {0} : {1}",wrsp.StatusCode,wrsp.StatusDescription)); 
        } 
        else 
        { 
          Console.WriteLine(string.Format("ERROR: {0}",wex.Message)); 
        } 
      } 
    } 
 
    // hashing helper 
    static string MacSha(string canonicalizedString, byte[] key) 
    { 
      byte[] dataToMAC = System.Text.Encoding.UTF8.GetBytes(canonicalizedString); 
 
      using (HMACSHA256 hmacsha1 = new HMACSHA256(key)) 
      { 
        return System.Convert.ToBase64String(hmacsha1.ComputeHash(dataToMAC)); 
      } 
    } 
 
    static string MD5(string data) 
    { 
      return MD5(data, false); 
    } 
    static string MD5(string data, bool removeTail) 
    { 
      string rtn = Convert.ToBase64String(new System.Security.Cryptography.MD5CryptoServiceProvider().ComputeHash(System.Text.Encoding.Default.GetBytes(data))); 
      if (removeTail) 
        return rtn.Replace("=", ""); 
      else 
        return rtn; 
    } 
 
    static string createTableXml = @"<?xml version=""1.0"" encoding=""utf-8""?>
<entry 
  xmlns:d=""http://schemas.microsoft.com/ado/2007/08/dataservices""  
  xmlns:m=""http://schemas.microsoft.com/ado/2007/08/dataservices/metadata""  
  xmlns=""http://www.w3.org/2005/Atom""> 
  <title /> 
  <updated>{0:yyyy-MM-ddTHH:mm:ss.fffffffZ}</updated> 
  <author> 
    <name /> 
  </author> 
  <id /> 
  <content type=""application/xml""> 
    <m:properties> 
      <d:TableName>{1}</d:TableName> 
    </m:properties> 
  </content> 
</entry>"; 
 
  } 
} 

Azure