2

I have a Azure Function like that

[FunctionName("Function1")]
public static void Run([ServiceBusTrigger("myqueue", AccessRights.Manage,      Connection = "AzureWebJobsServiceBus")]string myQueueItem, TraceWriter log)
    {
        log.Info($"C# ServiceBus queue trigger function processed message: {myQueueItem}");
    }

I want to dynamic bind myqueue and AzureWebJobServiceBus connection string in a startup or OnInit of app without as method's parameter above. I mean, I want to a method run first of all like Program.cs in WebJob to binding or start up global variables. Can I do that in Azure Function and how to do it? Many thanks

Janusz Nowak
  • 2,595
  • 1
  • 17
  • 36
user974335
  • 21
  • 1
  • 2

2 Answers2

1

The attributes here are compiled into a function.jsonfile before deployment that has the info on what the binding talks to. Often things like the connection string reference app settings. Neither of these can be modified within the code itself (so a Program.cs couldn’t modify the function.json binding).

Can you share any more on your scenario? If you have multiple queues you want to listen to could you deploy a function per queue? Given the serverless nature of Functions there isn’t a downside to having extra functions deployed. Let me know - happy to see if we can help with what you need.

jeffhollan
  • 3,139
  • 15
  • 18
1

Edit

The suggestion below doesn't work for a Trigger, only for a Binding. We have to wait for the team to support Key Vault endpoints in Azure Functions, see this GitHub issue.


I think what you are looking for is something called Imperative Bindings.

I've discovered them myself just yesterday and had a question about them also. With these type of bindings you can just dynamically set up the bindings you want, so you can retrieve data from somewhere else (like a global variable, or some initialization code) and use it in the binding.

The thing I have used it for is retrieving some values from Azure Key Vault, but you can also retrieve data from somewhere else of course. Some sample code.

// Retrieving the secret from Azure Key Vault via a helper class
var connectionString = await secret.Get("CosmosConnectionStringSecret");
// Setting the AppSetting run-time with the secret value, because the Binder needs it
ConfigurationManager.AppSettings["CosmosConnectionString"] = connectionString;

// Creating an output binding
var output = await binder.BindAsync<IAsyncCollector<MinifiedUrl>>(new DocumentDBAttribute("TablesDB", "minified-urls")
{
    CreateIfNotExists = true,
    // Specify the AppSetting key which contains the actual connection string information
    ConnectionStringSetting = "CosmosConnectionString",
});

// Create the MinifiedUrl object
var create = new CreateUrlHandler();
var minifiedUrl = create.Execute(data);

// Adding the newly created object to Cosmos DB
await output.AddAsync(minifiedUrl);

There are also some other attributes you can use with imperative binding, I'm sure you'll see this in the docs (first link).

Instead of using Imperative Bindings, you can also use your application settings.

As a best practice, secrets and connection strings should be managed using app settings, rather than configuration files. This limits access to these secrets and makes it safe to store function.json in a public source control repository. App settings are also useful whenever you want to change configuration based on the environment. For example, in a test environment, you may want to monitor a different queue or blob storage container. App settings are resolved whenever a value is enclosed in percent signs, such as %MyAppSetting%. Note that the connection property of triggers and bindings is a special case and automatically resolves values as app settings. The following example is an Azure Queue Storage trigger that uses an app setting %input-queue-name% to define the queue to trigger on.

{
  "bindings": [
    {
      "name": "order",
      "type": "queueTrigger",
      "direction": "in",
      "queueName": "%input-queue-name%",
      "connection": "MY_STORAGE_ACCT_APP_SETTING"
    }
  ]
}
Jan_V
  • 4,244
  • 1
  • 40
  • 64
  • Hi Jan_v, Many thanks for your response. It's really my expected code. I tried to do it but still didn't work for me. – user974335 Oct 24 '17 at 16:41
  • Hi @Jan_V, Many thanks for your response. It's really my expected code. I want to load queue name and service bus connection string from Key Vault at initialize, pass them to function **Function1** and launch function to it trigger Service Bus Queue. I tried to do it but still didn't work for me. Can you explain more detail about where to implement your code. I wrote them in run.csx file but it didn't work. I also wrote them inside an Azure Function, and the same result (Not work). This's my code [link](https://www.dropbox.com/s/h4q6rb4fdks0889/AZureFunction2.rar?dl=0) – user974335 Oct 24 '17 at 18:28
  • I've implemented the Cosmos DB binding in my own project, you can find the implementation details over here: https://github.com/Jandev/minifier/commit/adab6afd30cc19057798a82f920b631b4d73415e#diff-943276c8eae34bc452c8cc610d4e5502 I can't open Dropbox files at work, but I'll check yours when I'm back home. – Jan_V Oct 25 '17 at 07:19
  • Thanks Jan, hope see your comment soon, I saw your project. – user974335 Oct 27 '17 at 05:46
  • I've just now reviewed your code and came to the conclusion Imperative Bindings won't help you. I missed the point you wanted to use Triggers, instead of Bindings, which makes sense as the Service Bus doesn't has an Input Binding. You can use bindings for output binding, but not to trigger (which makes sense in a way). Sorry to get your hopes up. There are some issues on GitHub (https://github.com/Azure/azure-webjobs-sdk/issues/746) concerning this. Guess we'll have to wait to get Trigger support. – Jan_V Oct 27 '17 at 08:53
  • Ohm, This's a bad news. Anyway, many thank for your supporting me. – user974335 Oct 27 '17 at 16:50