0

I would like to see if/how it would be possible to plug into the deserialization process for a parameter that's decorated with the ServiceBusTrigger?

Say I have a function that looks like:

public static void HandleMessage([ServiceBusTrigger("myqueue")] MyCustomType myCustomType) { }

How would I go about taking over the deserialization? I know that there is a notion of an IArgumentBindingProvider and IArgumentBinding but it does not look like ServiceBusTrigger supports these concepts.

I know I can use GetBody<Stream>() and deserialize that way but I'd like to know if I can plug into the ServiceBusTrigger's pipeline. By the looks at the SDK, the ServiceBusTrigger has a hard coded list of IQueueArgumentBindingProviders and so I can't add my own.

Thomas
  • 24,234
  • 6
  • 81
  • 125
Carlos
  • 223
  • 1
  • 2
  • 5

1 Answers1

0

If you have a look at the Azure WebJobs SDK Extensions, there is an overview on how to create your own bindings :

Otherwise the ServiceBusConfiguration exposes a MessagingProvider property that allows you to intercept the ServiceBusTrigger pipeline:

private static void Main()
{
    var sbConfig = new ServiceBusConfiguration()
    {
        MessagingProvider = // you implemetation of the MessagingProvider class goes here !!!
    };
    var config = new JobHostConfiguration();
    config.UseServiceBus(sbConfig);
    new JobHost(config).RunAndBlock();
}

Here is a simple skeleton of a MessagingProvider implementation:

public sealed class MyMessagingProvider : MessagingProvider
{
    private readonly ServiceBusConfiguration _config;

    public MyMessagingProvider(ServiceBusConfiguration config)
        : base(config)
    {
        _config = config;
    }

    public override MessageProcessor CreateMessageProcessor(string entityPath)
    {
        return new MyMessageProcessor(_config.MessageOptions);
    }

    private class MyMessageProcessor : MessageProcessor
    {
        public MyMessageProcessor(OnMessageOptions messageOptions)
            : base(messageOptions)
        {
        }


        public override Task<bool> BeginProcessingMessageAsync(BrokeredMessage message, CancellationToken cancellationToken)
        {
            // Intercept the message before the execution of the triggerred function
            return base.BeginProcessingMessageAsync(message, cancellationToken);
        }

        public override Task CompleteProcessingMessageAsync(BrokeredMessage message, FunctionResult result, CancellationToken cancellationToken)
        {
            // Intercept the message after the execution of the triggerred function and before being completed
            return base.CompleteProcessingMessageAsync(message, result, cancellationToken);
        }
    }
}

So you're main function now looks like that:

private static void Main()
{
    var sbConfig = new ServiceBusConfiguration();
    sbConfig.MessagingProvider = new MyMessagingProvider(sbConfig);
    var config = new JobHostConfiguration();
    config.UseServiceBus(sbConfig);
    new JobHost(config).RunAndBlock();
}
Thomas
  • 24,234
  • 6
  • 81
  • 125
  • Thanks for the reply however, message processors let you do processing before and after a message is processed. What I'm trying to do is plug into the value binding process. For example, I want to extend the deserialization of the BrokeredMessage to my custom type so that I can have a web job function that looks like: – Carlos Sep 02 '16 at 02:18
  • @Carlos, sorry cant see how your function should look like – Thomas Sep 02 '16 at 02:23
  • Thanks for the reply however, message processors let you do processing before and after a message is processed. What I'm trying to do is plug into the value binding process. For example, I want to extend the deserialization of the BrokeredMessage to my custom type so that I can have a web job function that like: public void JobFunction([ServiceBusTrigger(...)] MyType myType) And instead of the vanilla deserialization that happens (which for custom types, the properties dictionary isn't mapped), plug into so that I can copy values from the BrokeredMessage.Properties dictionary to MyType. – Carlos Sep 02 '16 at 02:24
  • Its just a nice to have since it'd avoid having all web job functions from calling some translator. – Carlos Sep 02 '16 at 02:25
  • Have you consider using BrokeredMessage binding rather than a POCO ? This way you have access to all the properties of the message but you need to manually deserialize the message – Thomas Sep 02 '16 at 02:50
  • Yes, but using brokered message means using strings to access the dictionary whose properties are untyped. Or the first line in each web job's function would be to call a translator to go from BrokeredMessage to a custom type. It'd just be nice if I could do this behind the scenes before the web job is called, so that the web job's signature is pretty clean. – Carlos Sep 02 '16 at 03:09
  • I don't think so, you should open an issue on the github webjob sdk project. – Thomas Sep 02 '16 at 03:42