Azure Blob Upload not working in ASP .Net Core Application

Azure Blob Upload not working in ASP .Net Core Application



I am trying to upload a file to Azure blob storage in Asp .Net Core. Everything seems to be working but no file is uploaded. Here is my code snippet:


var blobReference = GetBlobReference();
rawData.Position = 0;

// var result = blobReference.UploadFromStreamAsync(rawData);
var result = blobReference.UploadFromFileAsync("C:\users\tjaartb\Downloads\DebitOrderMandate.pdf");
result.GetAwaiter().GetResult();
var blobPath = blobReference.Uri.ToString();



The debugger steps over the result.GetAwaiter().GetResult() with no exceptions occurring. Checking the result Task variable after the GetResult() call shows that the task state is RanToCompletion and the exception property is blank. My blob container is created successfully in earlier code indicating that the connection to blob storage is successful. GetResult() finishes instantly, so it seems like nothing is happening.


result.GetAwaiter().GetResult()


result


GetResult()


RanToCompletion


GetResult()


rawData


MemoryStream


Started Thread <ThreadNumber>


blobReference.UploadFromFileAsync()


FileNotFoundException


netcoreapp2.0


netcoreapp2.1






Why don't you just await the method call? I can't tell why it is not working with an awaiter in that case but I used netcoreapp2.1 and for me it worked with awaiting the method call.

– alsami
Sep 3 '18 at 7:02







It might be an async await deadlock. Could you try changing your code to use async all the way? ASP.NET Core supports async almost everywhere. Then you code becomes await blobReference.UploadFromFileAsync("C:\users\tjaartb\Downloads\DebitOrderMandate.pdf");

– juunas
Sep 3 '18 at 7:06


await blobReference.UploadFromFileAsync("C:\users\tjaartb\Downloads\DebitOrderMandate.pdf");






The interface I am implementing in that method is part of a larger ecosystem that doesn't have async signatures. It would require a lot of effort to refactor it. But I'll give it a try and see.

– Tjaart
Sep 3 '18 at 7:07






@alsami I made the change to await the call and it made no difference.

– Tjaart
Sep 3 '18 at 7:21






@Tjaart you did it like that and nothing happend? await blobReference.UploadFromFileAsync("C:\users\tjaartb\Downloads\DebitOrderMandate.pdf"); Then it should have worked because the upload function is returning a task only. Check in azure if the file exists.

– alsami
Sep 3 '18 at 7:52


await blobReference.UploadFromFileAsync("C:\users\tjaartb\Downloads\DebitOrderMandate.pdf");




4 Answers
4



the following code with WindowsAzure.Storage - Version 9.3.1 package works on Asp Net Core 2.1.


public class AzureBlobModel

public string FileName get; set;
public long? FileSize get; set;
public Stream Stream get; set;
public string ContentType get; set;


public interface IImageStore

Task<string> SaveDocument(Stream documentStream);
Task<bool> DeleteDocument(string imageId);
Task<AzureBlobModel> DownloadDocument(string documentId, string fileName);
string UriFor(string documentId);


public class ImageStore : IImageStore

CloudBlobClient blobClient;
string baseUri = "https://xxxxx.blob.core.windows.net/";

public ImageStore()

var credentials = new StorageCredentials("xxxxx accountName xxxxx", "xxxxx keyValue xxxxx");
blobClient = new CloudBlobClient(new Uri(baseUri), credentials);


public async Task<string> SaveDocument(Stream documentStream)

var documentId = Guid.NewGuid().ToString();
var container = blobClient.GetContainerReference("xxxxx container xxxxx");
var blob = container.GetBlockBlobReference(documentId);
await blob.UploadFromStreamAsync(documentStream);
return documentId;


public async Task<bool> DeleteDocument(string documentId)

var container = blobClient.GetContainerReference("xxxxx container xxxxx");
var blob = container.GetBlockBlobReference(documentId);
bool blobExisted = await blob.DeleteIfExistsAsync();
return blobExisted;


public async Task<AzureBlobModel> DownloadDocument(string documentId, string fileName)

var container = blobClient.GetContainerReference("xxxxx container xxxxx");
var blob = container.GetBlockBlobReference(documentId);

var doc = new AzureBlobModel()

FileName = fileName,
Stream = new MemoryStream(),
;

doc.Stream = await blob.OpenReadAsync();
doc.ContentType = blob.Properties.ContentType;
doc.FileSize = blob.Properties.Length;

return doc;


public string UriFor(string documentId)

var sasPolicy = new SharedAccessBlobPolicy

Permissions = SharedAccessBlobPermissions.Read,
SharedAccessStartTime = DateTime.UtcNow.AddMinutes(-15),
SharedAccessExpiryTime = DateTime.UtcNow.AddDays(1)
;

var container = blobClient.GetContainerReference("xxxxx container xxxxx");
var blob = container.GetBlockBlobReference(documentId);
var sas = blob.GetSharedAccessSignature(sasPolicy);
return $"baseUrixxxxx container xxxxx/documentIdsas";



public class DocForCreationDto

public IFormFile File get; set;

// other properties ...


// On the controller

[HttpPost]
public async Task<IActionResult> Upload([FromForm]DocForCreationDto docForCreationDto)
!ModelState.IsValid)

return new UnprocessableEntityObjectResult(ModelState);


string documentId = string.Empty;
using (var stream = docForCreationDto.File.OpenReadStream())

documentId = await _imageStore.SaveDocument(stream);


if (documentId != string.Empty)

// upload ok ...
//some business logic here ...
return Ok();


return BadRequest("xxx error xxx");


[HttpGet("documentId", Name = "GetDocument")]
public async Task<IActionResult> GetDocument(int documentId)

var doc = await _imageStore.DownloadDocument(documentId, "output filename");

return File(doc.Stream, doc.ContentType, doc.FileName);


// On Startup - ConfigureServices

services.AddSingleton<IImageStore, ImageStore>();



The interface I am implementing in that method is part of a larger ecosystem that doesn't have async signatures. It would require a lot of effort to refactor it.



You could use Wait() to replace await to implement the async signatures.Refer to the following code:


Wait()


await


CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connection);
CloudBlobClient cloudBlobClient = storageAccount.CreateCloudBlobClient();
var cloudBlobContainer = cloudBlobClient.GetContainerReference("containername");
CloudBlockBlob blob = cloudBlobContainer.GetBlockBlobReference("DebitOrderMandate.pdf");
using (var fileStream = System.IO.File.OpenRead("C:\users\tjaartb\Downloads\DebitOrderMandate.pdf"))

blob.UploadFromStreamAsync(fileStream).Wait();



Adding a / prefix to a Blob name results in a silent failure. The file does not upload at all. removing the / prefix fixed the problem.


/


/



With .NET Core 2.1 and WindowsAzure.Storage 9.3.2 all the methods are now async. If you don't await all the async method calls you can get silent failures. The comments below the question helped me figure that out.



Thanks for contributing an answer to Stack Overflow!



But avoid



To learn more, see our tips on writing great answers.



Required, but never shown



Required, but never shown




By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)