tech spartans
tech spartans

Reputation: 370

Accessing azure tables entities

Hi all i want to access azure tables entities from windows phone either using rest API or using Odata. I have written a code but that this giving me NULL response. Every time i want to access a table entity i call GetEntity function. Below is the code that i am using. Please if anybody know what wrong in this code or any help reply asap.

//////////// GetEntity Function.//////////

     private void GetEntity(String tableName, String partitionKey, String rowKey)
    {
        String requestMethod = "GET";

        String urlPath = String.Format("{0}(PartitionKey='{1}',RowKey='{2}')", tableName,   partitionKey, rowKey);


        String dateInRfc1123Format = DateTime.Now.ToString("R", System.Globalization.CultureInfo.InvariantCulture);

        String canonicalizedResource = String.Format("/{0}/{1}", AzureStorageConstants.Account, urlPath);
        String stringToSign = String.Format(
              "{0}\n\n\n{1}\n{2}",
              requestMethod,
              dateInRfc1123Format,
              canonicalizedResource);
        String authorizationHeader = CreateAuthorizationHeader(stringToSign);
        HttpWebResponse response;
        Uri uri = new Uri(AzureStorageConstants.TableEndPoint + urlPath);


        HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri);
        request = (HttpWebRequest)WebRequest.Create(uri);
        request.Method = requestMethod;
        request.Headers[HttpRequestHeader.ProxyAuthorization] = null;
        request.Headers["Address"] = uri.ToString();
        request.Headers["Method"] = requestMethod;
        request.Headers["x-ms-date"]= DateTime.Now.ToString("R", System.Globalization.CultureInfo.InvariantCulture);
        request.Headers["x-ms-version"]= "2011-08-18";            
        request.Headers["Authorization"] = authorizationHeader;
        request.Headers["Accept-Charset"] = "UTF-8";
        request.Headers["ContentType"] = "application/atom+xml,application/xml";
        request.ContentType = "application/atom+xml,application/xml";
        request.Headers["DataServiceVersion"] = "1.0;NetFx";
        request.Headers["MaxDataServiceVersion"] = "1.0;NetFx";

       using (response = GetResponse(request))
        {
            Stream dataStream = response.GetResponseStream();
            using (StreamReader reader = new StreamReader(dataStream))
            {
                String responseFromServer = reader.ReadToEnd();
            }
        }
    }

// GetResponse Function.

       public HttpWebResponse GetResponse(HttpWebRequest request)
       {
        var dataReady = new AutoResetEvent(false);
        HttpWebResponse response = null;
        var callback = new AsyncCallback(delegate(IAsyncResult asynchronousResult)
        {
            response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
            dataReady.Set();
        });

        request.BeginGetResponse(callback, request);
            return response;
    }

////// CreateAuthorization Function.///

      private String CreateAuthorizationHeader(String canonicalizedString)
    {
   String signature = string.Empty;
 using (HMACSHA256 hmacSha256 = new HMACSHA256(Convert.FromBase64String(AzureStorageConstants.Key))) 

 {
     Byte[] dataToHmac = System.Text.Encoding.UTF8.GetBytes(canonicalizedString);
     signature = Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac));
 }

String authorizationHeader = String.Format(
       CultureInfo.InvariantCulture,
       "{0} {1}:{2}",
       AzureStorageConstants.SharedKeyAuthorizationScheme,
       AzureStorageConstants.Account,
       signature);

return authorizationHeader;

}

////////AzureStorageConstants.

      public static class AzureStorageConstants
    {


     private static String TableAccount = "datablobs";
     private static String cloudEndPointFormat = "http://" + TableAccount + ".table.core.windows.net/";


    private static String cloudKey = "Primary Access Key";// Here actual key is written.
    private static string AzureStorage_SharedKeyAuthorizationScheme = "SharedKey";


        public static String Account
        {
            get { return TableAccount; }
        }

        public static string SharedKeyAuthorizationScheme
        {
            get { return AzureStorage_SharedKeyAuthorizationScheme; }
        }

        public static string Key
        {
            get { return  cloudKey; }
        }

        public static String TableEndPoint
        {
            get { return cloudEndPointFormat; }
        }
    }

Upvotes: 3

Views: 1733

Answers (2)

tech spartans
tech spartans

Reputation: 370

for solution refer to below linked i have posted the solution there http://social.msdn.microsoft.com/Forums/en-US/windowsazureconnectivity/thread/84415c36-9475-4af0-9f52-c534f5681432

Upvotes: 2

AvkashChauhan
AvkashChauhan

Reputation: 20556

I checked you code and found the GetEntity() function does have some problem with regard to creating signature to access the Windows Azure Table Storage, so I hack together the following code which does work. You can just replace your GetEntity() and add two other function included in the code below to work signature process properly.

private string GetEntity(String tableName, String partitionKey, String rowKey)
{
    string result = "";
    String requestMethod = "GET";
    String urlPath = String.Format("{0}(PartitionKey='{1}',RowKey='{2}')",tableName, partitionKey, rowKey);
    DateTime now = DateTime.UtcNow;
    HttpWebResponse response;
    string uri = AzureStorageConstants.TableEndPoint + urlPath;
    HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri);
    request.Method = requestMethod;
    request.ContentLength = 0;
    request.Headers.Add("x-ms-date", now.ToString("R", System.Globalization.CultureInfo.InvariantCulture));
    request.Headers.Add("x-ms-version", "2009-09-19");
    request.ContentType = "application/atom+xml";
    request.Headers.Add("DataServiceVersion", "1.0;NetFx");
    request.Headers.Add("MaxDataServiceVersion", "1.0;NetFx");
    request.Headers.Add("If-Match", "*");
    request.Headers.Add("Accept-Charset", "UTF-8");
    request.Headers.Add("Authorization", AuthorizationHeader(requestMethod, now, request));
    request.Accept = "application/atom+xml";
    using (response = request.GetResponse() as HttpWebResponse)
    {
        Stream dataStream = response.GetResponseStream();
        using (StreamReader reader = new StreamReader(dataStream))
        {
            result = reader.ReadToEnd();
        }
    }
    return result;
}

public string AuthorizationHeader(string method, DateTime now, HttpWebRequest request)
{
    string MessageSignature;
    MessageSignature = String.Format("{0}\n\n{1}\n{2}\n{3}",
        method,
        "application/atom+xml",
        now.ToString("R", System.Globalization.CultureInfo.InvariantCulture),
        GetCanonicalizedResource(request.RequestUri, AzureStorageConstants.Account)
        );
    byte[] SignatureBytes = System.Text.Encoding.UTF8.GetBytes(MessageSignature);
    System.Security.Cryptography.HMACSHA256 SHA256 = new System.Security.Cryptography.HMACSHA256(Convert.FromBase64String(AzureStorageConstants.Key));
    String AuthorizationHeader = "SharedKey " + AzureStorageConstants.Account + ":" + Convert.ToBase64String(SHA256.ComputeHash(SignatureBytes));
    return AuthorizationHeader;
}

public string GetCanonicalizedResource(Uri address, string accountName)
{
    StringBuilder str = new StringBuilder();
    StringBuilder builder = new StringBuilder("/");
    builder.Append(accountName);
    builder.Append(address.AbsolutePath);
    str.Append(builder.ToString());
    NameValueCollection values2 = new NameValueCollection();
    NameValueCollection values = HttpUtility.ParseQueryString(address.Query);
    foreach (string str2 in values.Keys)
    {
        ArrayList list = new ArrayList(values.GetValues(str2));
        list.Sort();
        StringBuilder builder2 = new StringBuilder();
        foreach (object obj2 in list)
        {
            if (builder2.Length > 0)
            {
                builder2.Append(",");
            }
            builder2.Append(obj2.ToString());
        }
        values2.Add((str2 == null) ? str2 : str2.ToLowerInvariant(), builder2.ToString());
    }
    ArrayList list2 = new ArrayList(values2.AllKeys);
    list2.Sort();
    foreach (string str3 in list2)
    {
        StringBuilder builder3 = new StringBuilder(string.Empty);
        builder3.Append(str3);
        builder3.Append(":");
        builder3.Append(values2[str3]);
        str.Append("\n");
        str.Append(builder3.ToString());
    }
    return str.ToString();
}

To fix your Signature related problem, I took the code from Storage_REST_CS sample which has superb implementation of accessing Windows Azure (Blob, Table & Queue) Storage over REST interface.

Upvotes: 1

Related Questions