Azure-functions-vs-build-sdk: Service Bus-output is not added to generated function.json

Created on 30 Aug 2017  Â·  13Comments  Â·  Source: Azure/azure-functions-vs-build-sdk

Tooling Information

  • Version: 15.0.30812.0
  • Visual Studio: 2017 Enterprise
  • NuGet: Microsoft.NET.Sdk.Functions v1.0.2

Issue Description

I want to send messages to an Azure Service Bus Queue on a scheduled basis using the new tooling so that I can run it locally.

Works with a Service Bus Trigger

When I use a Service Bus input & output everything works fine:
working-version

This is based on this function:

[ServiceBusAccount("ServiceBus.ConnectionString")]
public static class SampleFunction
{
    [FunctionName("SampleFunction")]
    public static void Run([ServiceBusTrigger("myqueue", AccessRights.Manage)] string myQueueItem, TraceWriter log, [ServiceBus("myotherqueue", AccessRights.Manage)] ICollector<string> queueMessages)
    {
        log.Info($"C# function triggered processed message: {myQueueItem}");

        queueMessages.Add($"{Guid.NewGuid().ToString().ToUpper()}-{DateTime.UtcNow}");

        log.Info($"Outputting message");
    }
}

Doesn't work without a Service Bus Trigger

However, when I use a different trigger such as a timer the function is broken:
timer-version

Error:

Run: Microsoft.Azure.WebJobs.Host: Error indexing method 'SampleFunction.Run'. Microsoft.Azure.WebJobs.Host: Cannot bind parameter 'queueMessages' to type ICollector`1. Make sure the parameter Type is supported by the binding. If you're using binding extensions (e.g. ServiceBus, Timers, etc.) make sure you've called the registration method for the extension(s) in your startup code (e.g. config.UseServiceBus(), config.UseTimers(), etc.).

This is based on this function:

[ServiceBusAccount("ServiceBus.ConnectionString")]
public static class SampleFunction
{
    [FunctionName("SampleFunction")]
    public static void Run([TimerTrigger("0 0 * * * *")] TimerInfo myTimer, TraceWriter log, [ServiceBus("myotherqueue", AccessRights.Manage)] ICollector<string> queueMessages)
    {
        log.Info($"C# function triggered processed message: {myTimer}");

        queueMessages.Add($"{Guid.NewGuid().ToString().ToUpper()}-{DateTime.UtcNow}");

        log.Info($"Outputting message");
    }
}

It turns out that the tooling is not generating the correct function.json output:

{
  "generatedBy": "Microsoft.NET.Sdk.Functions-1.0.0.0",
  "configurationSource": "attributes",
  "bindings": [
    {
      "type": "timerTrigger",
      "schedule": "0 0 * * * *",
      "useMonitor": true,
      "runOnStartup": false,
      "name": "myTimer"
    }
  ],
  "disabled": false,
  "scriptFile": "..\\bin\\Sample.Functions.dll",
  "entryPoint": "Sample.Functions.SampleFunction.Run"
}

Expected output

{
  "scriptFile": "..\\bin\\Sample.Functions.dll",
  "entryPoint": "Sample.Functions.SampleFunction.Run",
  "bindings": [
    {
      "name": "timer",
      "type": "timerTrigger",
      "direction": "in",
      "schedule": "0 0 * * * *",
      "name": "myTimer"
    },
    {
      "type": "serviceBus",
      "name": "brokeredMessages",
      "queueName": "myotherqueue",
      "connection": "ServiceBus.ConnectionString",
      "accessRights_": "Manage",
      "direction": "out"
    }
  ],
  "disabled": false
}

Repro

[ServiceBusAccount("ServiceBus.ConnectionString")]
public static class SampleFunction
{
    [FunctionName("SampleFunction")]
    public static void Run([TimerTrigger("0 0 * * * *")] TimerInfo myTimer, TraceWriter log, [ServiceBus("myotherqueue", AccessRights.Manage)] ICollector<string> queueMessages)
    {
        log.Info($"C# function triggered processed message: {myTimer}");

        queueMessages.Add($"{Guid.NewGuid().ToString().ToUpper()}-{DateTime.UtcNow}");

        log.Info($"Outputting message");
    }
}
bug

All 13 comments

What's the status here?

I've had the exact same issue in one of the projects I worked on.
It seems that if you add a single function that uses the "ServiceBusTrigger" Attribute to a project, then the output binding for the servicebus seems to work for all functions in that same project. Even if you are only using TimerBindings along with ServiceBus outputs.

However it is quite annoying having to create a dummy function only to enable a specific part of the library. Some sort of configuration for this would be greatly appreciated.

Maybe @lindydonna can help us here or add the relevant people?

@tomkerkhove @Dickow Sorry for the late reply. With the new version of the VS 2017 tooling, only triggers are generated in function.json. Input and output bindings will be read directly from the attributes in the assembly.

@ahmelsayed Could you try to repro the sample above? If it repros, it's likely a script host bug.

@lindydonna Thanks for circling back on this! However, the binding is not the only issue.

When I ran the function locally it wasn't working as well, as you can see here:

Any updates on this? /cc @jeffhollan

@tomkerkhove

Could you try this?

[ServiceBusAccount("ServiceBus.ConnectionString")]
public static class SampleFunction
{
    [FunctionName("SampleFunction")]
        [return: ServiceBus("myotherqueue", Connection = "ServiceBus.ConnectionString")]
    public static ICollector<string> Run([TimerTrigger("0 0 * * * *")] TimerInfo myTimer, TraceWriter log)
    {
        log.Info($"C# function triggered processed message: {myTimer}");
                ICollector<string> queueMessages = new ICollector<string>();
        queueMessages.Add($"{Guid.NewGuid().ToString().ToUpper()}-{DateTime.UtcNow}");
                return queueMessages;
        log.Info($"Outputting message");
    }
}

I didn't test exactly this code, but this approach works for me.
HTH

@pacodelacruz The question is, how do you get it working with the collector. You cannot simply create an instance on that and in the signature it says that the type is not supported.

The documentation on this has improved but not ideal yet.
https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-service-bus#output

Sorry mate, I should've tested it myself first.
This should work:

        [FunctionName("MultipleOutputs")]
        public static void Run([TimerTrigger("0 0 * * * * *")]TimerInfo myTimer, [ServiceBus("myotherqueue", Connection = "ServiceBusConnection")]ICollector<string> queueMessages, TraceWriter log)
        {
            log.Info($"C# function triggered processed message: {myTimer}");
            queueMessages.Add($"{Guid.NewGuid().ToString().ToUpper()}-{DateTime.UtcNow}");
            queueMessages.Add($"{Guid.NewGuid().ToString().ToUpper()}-{DateTime.UtcNow}");
            log.Info($"Outputting message");
        }

Sorry if this is not the right place to ask this :)

We are building our customized Microsoft.Azure.ServiceBus.Message object and when we try to add that message to outputCollector, which we are defining it as ICollector type, we get the following exception (any idea?):

Newtonsoft.Json.JsonSerializationException
HResult=0x80131500
Message=Error getting value from 'ExpiresAtUtc' on 'Microsoft.Azure.ServiceBus.Message'.
Source=Newtonsoft.Json
StackTrace:
at Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue(Object target)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CalculatePropertyValues(JsonWriter writer, Object value, JsonContainerContract contract, JsonProperty member, JsonProperty property, JsonContract& memberContract, Object& memberValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)
at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)
at Newtonsoft.Json.JsonConvert.SerializeObjectInternal(Object value, Type type, JsonSerializer jsonSerializer)
at Microsoft.Azure.WebJobs.ServiceBus.Bindings.UserTypeToBrokeredMessageConverter1.Convert(TInput input) at Microsoft.Azure.WebJobs.ServiceBus.Bindings.MessageSenderCollector1.Add(T item)
at McioDoveAndDoleE2eValidator.DoveE2eValidator.Run(String omnibusMessage, ICollector1 outputTopic, IDoveValidationEngineReportingDbContextFactory dbFactory, ISettings settings, ExecutionContext executionContext, TraceWriter log) in D:\dove\src\McioDoveAndDoleE2eValidator\DoveE2eValidator.cs:line 97 at Microsoft.Azure.WebJobs.Host.Executors.VoidMethodInvoker2.InvokeAsync(TReflected instance, Object[] arguments)
at Microsoft.Azure.WebJobs.Host.Executors.FunctionInvoker`2.d__9.MoveNext()

Inner Exception 1:
InvalidOperationException: Operation is not valid due to the current state of the object.

@aeghbal1 created an issue to help track your bug in the right spot 😊here

  • swapnil
    Swapnil, if this is not an issue anymore please close our AAD more details.

Thanks
Sent from my Windows 10 phone


From: Jeff Hollan notifications@github.com
Sent: Wednesday, June 13, 2018 2:45:42 AM
To: Azure/azure-functions-vs-build-sdk
Cc: Arash Eghbal; Mention
Subject: Re: [Azure/azure-functions-vs-build-sdk] Service Bus-output is not added to generated function.json (#104)

@aeghbal1https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Faeghbal1&data=02%7C01%7Caeghbal%40microsoft.com%7C066410e89217484ded2b08d5d1126deb%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636644799454946683&sdata=d32550B0yMTrUKTeRJKAC7QnXWw5O2UVZHu9mQV7WPs%3D&reserved=0 created an issue to help track your bug in the right spot 😊herehttps://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2FAzure%2Fazure-webjobs-sdk%2Fissues%2F1751&data=02%7C01%7Caeghbal%40microsoft.com%7C066410e89217484ded2b08d5d1126deb%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636644799454946683&sdata=Ten%2Byeu4M%2BmViERHFV4HgoaA35rXHQm2tQhRbwOSM4s%3D&reserved=0

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHubhttps://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2FAzure%2Fazure-functions-vs-build-sdk%2Fissues%2F104%23issuecomment-396879666&data=02%7C01%7Caeghbal%40microsoft.com%7C066410e89217484ded2b08d5d1126deb%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636644799454956688&sdata=P1Lcv8as84A5c%2FRUiEVZmihP6wgF%2Ftqlg%2BSJjunxKBI%3D&reserved=0, or mute the threadhttps://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FAaGuPlnEtX_2Sp48bHoL7PZNBi_9UB_yks5t8N9GgaJpZM4PHXhG&data=02%7C01%7Caeghbal%40microsoft.com%7C066410e89217484ded2b08d5d1126deb%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636644799454956688&sdata=VAQPeORAEvhwx8finzca12rDuCzVcNVcq1nQXGvQwnM%3D&reserved=0.

Closing this as resolved.

Was this page helpful?
0 / 5 - 0 ratings