0

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?

Brett JB
  • 687
  • 7
  • 24

2 Answers2

3

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.

Victor Hurdugaci
  • 28,177
  • 5
  • 87
  • 103
  • Brilliant and thank you!.. I would ask however.. how did you find this out.. I am trying to find some decent examples and documentation .. thanks again. – Brett JB Jul 17 '14 at 12:30
  • I work on the WebJobs SDK - that's how I found out :) Did you see the examples here: http://aspnet.codeplex.com/SourceControl/latest#Samples/AzureWebJobs/ReadMe.txt ? – Victor Hurdugaci Jul 17 '14 at 17:06
  • Ah.. that explains it. Yes I have seen the examples on Codeplex and that is how I got as far as I did. I don't think there is/was an example that covered what I wanted to achieve and I had tried something similar to that but it barfed with my attempt .. As I said, I realise this is early days but a few simple examples that show getting to the storage objects wouldn't go amiss.(short of full documentation :). Thanks again though and its looking like a great solution so far. – Brett JB Jul 18 '14 at 09:15
0

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();
umino
  • 36
  • 5