Brett JB
Brett JB

Reputation: 866

webjobs using IBinder to delete a blob

Ok, I realise the webjobs sdk is still in beta but it is pretty cool. I am struggling a little with the IBinder though in terms of getting to the actual object I'm binding to. It may be obvious so please forgive me if so...

I am processing emails to send with a webjob. They get put on a queue and triggers the event. This code works.. but I can't help thinking I could access the resulting blob, to delete it if successful, or move it if not, much more easily.

Here is the code:

        public static void ProcessEmailBlob([QueueTrigger(Email.queueEmailsToSend) ] string blobname, IBinder binder)

   {

        TextReader inputfile = binder.Bind<TextReader>(new BlobAttribute(Email.blobEmailOutboxContainerAsPath+blobname));
        string input = inputfile.ReadToEnd();

        string connection = ConfigurationManager.ConnectionStrings["AzureJobsStorage"].ConnectionString;

        CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connection);

        //Get create connect to the outbox blob
        CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
        CloudBlobContainer container = blobClient.GetContainerReference(Email.blobEmailOutboxContainer);
        CloudBlockBlob emailin = container.GetBlockBlobReference(blobname);

        MailMessage smptmail = new MailMessage();
        //ought to be able to JSONise this??
        //smptmail = JsonConvert.DeserializeObject<MailMessage>(input);   
        smptmail = XmlMailMessage.MakeSMPTMessage(input);
        bool success = Email.Send(smptmail);

        if (success && emailin.Exists()) //If sending the email succeeded
        {
            emailin.Delete();
        }
        else
        {   //The email failed or the blob doesn't exist which is also odd and bad 
            if (emailin.Exists())
            {   //Then the file is ok.. store it in the Failed Email
                CloudBlobContainer failedcontainer = blobClient.GetContainerReference(Email.blobEmailFailedContainer);
                failedcontainer.CreateIfNotExists();
                CloudBlockBlob failedmailblob = failedcontainer.GetBlockBlobReference(blobname); // use the same name just a different container
                failedmailblob.StartCopyFromBlob(emailin);
            }
            else
            {
                //log something here
            }

        }

    }

As you can see, I can get the blob content with the binder.Bind piece, but then I need to do the whole connection thing to get to it to delete it.. that can't be right .. can it?

Upvotes: 0

Views: 1527

Answers (2)

umino
umino

Reputation: 36

With this answer I also succeeded. Below are supplementary explanations

In my case, I had to change BlobAttribute by using and deleting

//use block blob
//Must be "FileAccess.Read"
var fileAttr = new BlobAttribute(anyblobname, FileAccess.Read);
using(var stream = binder.Bind<Stream>(fileAttr)){
  ...
}

//delete block blob
//Must be "FileAccess.ReadWrite"
var blobAttr = new BlobAttribute(anyblobname, FileAccess.ReadWrite);
var blockBlob = binder.Bind<CloudBlockBlob>(blobAttr);
blockBlob.DeleteIfExists();

Upvotes: 0

Victor Hurdugaci
Victor Hurdugaci

Reputation: 28425

The BlobAttribute can be used on .NET SDK types too. In your case, you can bind to a CloudBlockBlob and then you don't need the connection string.

CloudBlockBlob blobReference = binder.Bind<CloudBlockBlob>(new BlobAttribute(Email.blobEmailOutboxContainerAsPath+blobname));
blobReference.DeleteIfExists();

As a sidenote, you can also bind to CloudStorageAccount. If your web jobs has a CloudStorageAccount parameter (no attribute needed), it will be magically bound.

Upvotes: 3

Related Questions