0
votes

I have an MVC application that allows a user to upload a resource to blob storage with a dynamically generated SAS. A user will select a file and click upload. When upload is clicked, an ajax call is sent to a controller action that will generate an SAS for the container and return a string which is the URI for the blob that is going to be uploaded with the signature appended. This works perfectly and returns the correct URI with SAS. I then have another ajax call that will PUT the data from the file to Azure Blob Storage using the URI that was returned. When this executes I get a javascript runtime error in the Jquery.min file that says "0x80070005 Access is Denied".

I wanted to make sure I had coded this correctly and that my SAS was right so I ran it through Runscope (I had the MVC controller action modify the URI to go through my Runscope account). If I copied the URI and manually set the headers that I am setting in the ajax call, it worked. And the permission settings work. With the SAS that I generated I can access the file, without it I cannot. If I let it run through my javascript file with the ajax call it failed and returned a 405 error. Here is my ajax call and then my two different requests sent with Runscope.

I used this article http://gauravmantri.com/2013/02/16/uploading-large-files-in-windows-azure-blob-storage-using-shared-access-signature-html-and-javascript/#comment-1700 as a guide for uploading the file in chunks. The following ajax call will execute for each block uploaded, but it fails on the first try.

var uri = submitUri + "&comp=block&blockid=" + blockIds[blockIds.length - 1];
var requestData = new Uint8Array(evt.target.result);
$.ajax({
    url: uri,
    type: "PUT",
    data: requestData,
    processData: false,
    beforeSend: function(xhr) {
        xhr.setRequestHeader("x-ms-blob-type", "BlockBlob");
        xhr.setRequestHeader("Content-Length", requestData.length);
    },
    success: function() {
        // successful stuff here
        uploadFileInBlocks();
    }
    error: function (xhr, desc, err) {
        // error stuff here
    }
});

And here are my Runscope results:

Successful manual request:

PUT https://<myaccount>.blob.core.windows.net/trainingcourseresources/1002/georgewashington.jpg?sr=c&sp=rw&sig=GI+HN1hTEiyTG9Kz1OIBIcArAEkeZWyxI4v7OmMuEsA=&sv=2012-02-12&se=2013-09-17T13:19:52Z

HEADERS
Accept: */*
Accept-Encoding: gzip, deflate, compress
Connection: close
Host: atlastestblob.blob.core.windows.net
User-Agent: runscope/0.1
X-Ms-Blob-Type: BlockBlob

QUERYSTRING
se: 2013-09-17T13:19:52Z
sig: GI+HN1hTEiyTG9Kz1OIBIcArAEkeZWyxI4v7OmMuEsA=
sp: rw
sr: c
sv: 2012-02-12

Response: 201 Created

Failed ajax request:

OPTIONS https://<myaccount>.blob.core.windows.net/trainingcourseresources/1002/cslewis.jpg?sp=rw&sr=c&blockid=YmxvY2stMDAwMDAw&sv=2012-02-12&sig=iIn/AL3eBBFlZdYoT717SMS9iDOY5PEKIdIufOle7NA=&comp=block&se=2013-09-17T13:40:00Z

HEADERS
Accept: */*
Accept-Encoding: gzip, deflate
Access-Control-Request-Headers: content-type, accept, x-ms-blob-type
Access-Control-Request-Method: PUT
Cache-Control: no-cache
Connection: close
Dnt: 1
Host: atlastestblob.blob.core.windows.net
Origin: https://localhost:44308
User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)

QUERYSTRING
blockid: YmxvY2stMDAwMDAw
comp: block
se: 2013-09-17T13:40:00Z
sig: iIn/AL3eBBFlZdYoT717SMS9iDOY5PEKIdIufOle7NA=
sp: rw
sr: c
sv: 2012-02-12

Response: 405 The resource doesn't support specified Http Verb
3
Azure doesn't support CORS. Your web app and blob storage must be on the same domain, as the article states. This is clearly not the case in your situation. You'll need to either ensure your app and blob store are on the same domain, or send the files from your server instead of directly from the client/browser.Ray Nicholus
I had thought MS added CORS support back in march... maybe I was mistaken.mvanella
Nope. And the lack of support for OPTIONS is further proof that this doesn't exist. The browser will send an OPTIONS request for any "non-simple" cross-origin requests. See the spec for more details on this. I just did a quick search, and CORS support is still pending: feedback.windowsazure.com/forums/217298-storage/suggestions/…Ray Nicholus

3 Answers

2
votes

As also announced at BUILD, Windows Azure Storage will have CORS support by end of 2013.

0
votes

One of the helpful MSDN Blog it might help you all.

The code which I was missing was

private static void ConfigureCors(ServiceProperties serviceProperties)
{
    serviceProperties.Cors = new CorsProperties();
    serviceProperties.Cors.CorsRules.Add(new CorsRule()
    {
        AllowedHeaders = new List<string>() { "*" },
        AllowedMethods = CorsHttpMethods.Put | CorsHttpMethods.Get | CorsHttpMethods.Head | CorsHttpMethods.Post,
        AllowedOrigins = new List<string>() { "*" },
        ExposedHeaders = new List<string>() { "*" },
        MaxAgeInSeconds = 1800 // 30 minutes
     });
}

It basically add some rules to SAS Url, and I am able to upload my files to blob.