3
votes

I'm trying to create an Azure Function that triggers on an AZ ServiceBus Queue message. The message contains a GUID string, matching the name of a BLOB on AZ storage. I'd like to have that BLOB available through an input binding but I'm not sure how...

I tried :

public static async Task Run(
   [ServiceBusTrigger("outgoing-mail", Connection = "QueueConnString")] string inputMessage,
   [Blob("email-messages/{inputMessage}", FileAccess.Read)] Stream mailBlob,
   [SendGrid(ApiKey = "%SendgridApiKey%")] IAsyncCollector<SendGridMessage> messageCollector,
   ILogger log)

I also tried {serviceBusTrigger} on the blob path by-the-way but either way, I get the following exception :

Microsoft.Azure.WebJobs.Host: Error indexing method 'SendMailQueueWorker'. Microsoft.Azure.WebJobs.Host: Unable to resolve binding parameter 'inputMessage'. Binding expressions must map to either a value provided by the trigger or property of the value the trigger is bound to or must be a system binding expression (e.g. sys.randguid, sys.utcnow, etc.).

I'm sure the input message of the queue is a string, how can I use this message content in the input binding of the BLOB?

[edit]
I added the feature request to UserVoice, so if you're running into this issue as well, please vote! https://feedback.azure.com/forums/355860-azure-functions/suggestions/37528912-combine-servicebus-queue-message-with-storage-inpu
[/edit]

2

2 Answers

5
votes

Looks like this isn't supported for Service Bus Trigger the way it is for Queue Trigger.
You could raise a feature request on UserVoice for this.

But one thing to note is that this limitation holds only for non-JSON messages. If you send a JSON message instead, it will get parsed as documented.

Your function could be something like this

using System;
using System.IO;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;

namespace funk_csharp_queue
{
  public class QueueMsg
  {
    public string filename { get; set; }
  }
  public static class ServiceBusTrigger
  {
    [FunctionName("ServiceBusTrigger")]
    public static void Run(
      [ServiceBusTrigger("myqueue", Connection = "ServiceBusConnection")] QueueMsg myQueueItem,
      [Blob("samples-workitems/{filename}", FileAccess.Read)] String myBlob,
      ILogger log)
    {
      log.LogInformation($"C# Service Bus trigger function processed: {JsonConvert.SerializeObject(myQueueItem)}");
      log.LogInformation($"C# Blob input read: {myBlob}");
    }
  }
}

And the message you send in the Service Bus Queue / Topic would be something like this

{
  "filename": "11c8f49d-cddf-4b82-a980-e16e8a8e42f8.json"
}

Make sure you set the Content Type to application/json.

0
votes

I don't think that's directly possible as you would like to. I would just use a CloudBlobContainer input binding to work around this.

[Blob("email-messages", FileAccess.Read, Connection = "BlobConnectionString")] CloudBlobContainer blobContainer

Then use the blobContainer to read the blob in your function using the inputMessage.

CloudBlob mailBlob = blobContainer.GetBlobReference(inputMessage);