Nick Sologoub
Nick Sologoub

Reputation: 734

Setting Azure Function Service Bus Topic and Subscription Output Binding via C#

I have a simple HTTP trigger Azure Function with multiple Service Bus output bindings. All the bindings are pointing to the same Topic, but they have different Subscriptions. If I was to set this function app through function.json it is pretty straightforward:

{
  "bindings": [
    {
      "authLevel": "function",
      "name": "req",
      "type": "httpTrigger",
      "direction": "in",
      "methods": [
        "get",
        "post"
      ]
    },
    {
      "name": "$return",
      "type": "http",
      "direction": "out"
    },
    {
      "type": "serviceBus",
      "connection": "SERVICEBUS",
      "name": "output",
      "topicName": "outtopic",
      "subscriptionName": "sub",
      "direction": "out"
    },
    {
      "type": "serviceBus",
      "connection": "SERVICEBUS",
      "name": "output",
      "topicName": "outtopic",
      "subscriptionName": "sub2",
      "direction": "out"
    }
  ],
  "disabled": false
}

But I publish my functions via Visual Studio and therefore my Azure Functions are read only in the portal and function.json is automatically generated by VS upon publishing. The problem is that I cannot figure out how do I setup multiple output bindings pointing to different subscriptions. Currently I have something like this:

[FunctionName("Function2")]
public static async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
    [ServiceBus("outtopic", entityType:EntityType.Topic)] IAsyncCollector<string> output,
    [ServiceBus("outtopic", entityType: EntityType.Topic)] IAsyncCollector<string> output2,
    ILogger log)
{
    log.LogInformation("C# HTTP trigger function processed a request.");

    string requestBody = await new StreamReader(req.Body).ReadToEndAsync();

    await output.AddAsync(requestBody);

    return new OkObjectResult("OK");
}

As you can see output and output2 are pointing to the same Topic, but there is no option to specify Subscription. At this point I am pretty confident that this has not been implemented yet. But I hope there is a workaround maybe?

Upvotes: 0

Views: 2845

Answers (2)

Nadeem Duke
Nadeem Duke

Reputation: 171

It is not possible to directly put messages into a Topic Subscription, rather every message has to come through a Topic.

To make sure only a particular subscription receives a message, you need to configure the Topic Subscription rule. You can read more about rules in the blog post here.

Upvotes: 1

kgalic
kgalic

Reputation: 2654

Try this, add Connection property in the definition, per this example - if by subscription you mean on the azure subscription:

public static void Run([BlobTrigger("inputvideo/{customername}/{date}/{filename}", Connection = "AzureWebJobsStorage")]Stream myBlob, 
                                string customername, 
                                string date, 
                                string filename,
                                [ServiceBus("detectobjectsqueue",EntityType.Queue, Connection="ServiceBusConnectionString")] IAsyncCollector<string> output,
                                ILogger log)

Update Per your comment, I understood that by subscription you mean on topic subscription. In that case, the idea of topic is that all subscriptions receive the message. So you have one publisher, and whoever subscribes to the topic it will receive the message. If you would like to make sure that a specific subscriber receives the message, either implement message filtering(per type for example) on the receiving endpoint or use dedicated queue per subscriber.

Also, conceptually, the publisher should not know who are the subscribers, and the subscriber should not know who is the publisher. If you know who is the subscriber, why not use the REST call for example to the receiving endpoint?

Upvotes: 1

Related Questions