Azure Tables: Create/Delete example
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>"; } }