I am unable to add dynamic binding of any members of Service Bus BrokeredMessage using the Azure WebJobs SDK.
NOT working
// using properties on BrokeredMessage object
public static void ProcessDup([ServiceBusTrigger("dup")] **BrokeredMessage** q, [Blob("dup/{Label}")] string json, TextWriter log)
{
log.WriteLine($"Content(Id) {q.Label}\r\nBlob {json}");
Console.WriteLine($"Content(Id) {q.Label}\r\nBlob {json}");
}
// using properties inside of the BrokeredMessage.Properties
public static void ProcessDup([ServiceBusTrigger("dup")] **BrokeredMessage** q, [Blob("dup/{JsonFilename}")] string json, TextWriter log)
{
log.WriteLine($"Content(Id) {q.JsonFilename}\r\nBlob {json}");
Console.WriteLine($"Content(Id) {q.JsonFilename}\r\nBlob {json}");
}
It gives me the following messages when it processes messages from the service bus
Function had errors. See Azure WebJobs SDK dashboard for details. Instance ID
is '0a957645-f042-4dca-a38f-643229fbbc21'
Microsoft.Azure.WebJobs.Host.FunctionInvocationException: Exception while execut
ing function: Functions.ProcessDup ---> System.InvalidOperationException: Except
ion binding parameter 'json' ---> System.ArgumentNullException: Value cannot be
null.
Parameter name: bindingData
at Microsoft.Azure.WebJobs.Host.Bindings.BindingDataPathHelper.ConvertParamet
ers(IReadOnlyDictionary`2 bindingData)
at Microsoft.Azure.WebJobs.Host.Blobs.ParameterizedBlobPath.Bind(IReadOnlyDic
tionary`2 bindingData)
at Microsoft.Azure.WebJobs.Host.Blobs.Bindings.BlobBinding.<BindAsync>d__0.Mo
veNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNot
ification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
at Microsoft.Azure.WebJobs.Host.Triggers.TriggeredFunctionBinding`1.<BindCore
Async>d__7.MoveNext()
--- End of inner exception stack trace ---
at Microsoft.Azure.WebJobs.Host.Executors.DelayedException.Throw()
at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.<ExecuteWithWatche
rsAsync>d__31.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNot
ification(Task task)
at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.<ExecuteWithLoggin
gAsync>d__2c.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNot
ification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.<ExecuteWithLoggin
gAsync>d__13.MoveNext()
--- End of inner exception stack trace ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.<ExecuteWithLoggin
gAsync>d__13.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNot
ification(Task task)
at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.<TryExecuteAsync>d
__1.MoveNext()
DOES work
public static void ProcessDup([ServiceBusTrigger("dup")] **TheDup** q, [Blob("dup/{JsonFilename}")] string json, TextWriter log)
{
log.WriteLine($"Content(Id) {q.JsonFilename}\r\nBlob {json}");
Console.WriteLine($"Content(Id) {q.JsonFilename}\r\nBlob {json}");
}
The service bus message is based on this class
[DataContract(Name = "TheDup", Namespace = "")]
public class TheDup
{
[DataMember]
public Guid Id { get; set; }
public string JsonFilename => $"{Id}.json";
[DataMember]
public string Json { get; set; }
}
The service bus message is added with
var client = QueueClient.CreateFromConnectionString(_queueConnectionString, _queueName);
var message = new BrokeredMessage(new TheDup() {Id = id, Json = sSourceData?.Length > 128 ? string.Empty : sSourceData})
{
SessionId = sessionid == null ? id.ToString() : sessionid.ToString(),
Label = $"{id}.json"
};
message.Properties.Add(new KeyValuePair<string, object>("JsonFilename", $"{id}.json"));
client.Send(message);
client.Close();
As you've discovered, you can only include binding parameters like
dup/{JsonFileName}
when binding to a POCO that defines those members. This is by design.If this doesn't work for you and you truly need to do dynamic imperative binding, you can use
IBinder
to perform the blob binding in your code rather than in the parameter binding. Here's a simple example: