Reputation: 866
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
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
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