botframework-sdk: [.Net SDK, Azure Function] MissingMethodException thrown when accessing Microsoft.Bot.Builder.Dialogs.Conversation.Container

Bot Info

  • SDK Platform: .NET
  • SDK Version: 3.15 (happens on 3.12.2.4 too)
  • Active Channels: bot emulator, WebChat, Direct Line
  • Deployment Environment: local development with Emulator

Issue Description

My bot is based on Azure Functions. I need to access state data from a Function which is triggered by a queue, in order to push a pro-active message to the user. So I implemented code from https://stackoverflow.com/questions/46085614/, but when I tried to access the implementing method, I received a System.MissingMethodException: Method not found: 'Autofac.IContainer Microsoft.Bot.Builder.Dialogs.Conversation.get_Container()'. exception.

Code Example

(again, this is an Azure Function)

        [FunctionName("PasswordResponseFunction")]
        public static async Task Run([ServiceBusTrigger("password-response", AccessRights.Listen, Connection = "ServiceBusReceivePasswordResponseConnection")]BrokeredMessage message, TraceWriter log)
        {
            try
            {
                Stream body = message.GetBody<Stream>();
                BinaryFormatter formatter = new BinaryFormatter();
                String password = formatter.Deserialize(body) as String;
                log.Info($"C# ServiceBus queue trigger function processed message: { password }");
                IMessageActivity messageActivity = Activity.CreateMessageActivity();
               // Set some messageActivity properties here
                await SetPrivateConversationDataAsync(messageActivity, "password", password); // <-Exception thrown at this point

                ConnectorClient client = new ConnectorClient(new Uri(ActivityDataEntity.ServiceUrl));
                Activity activity = (Activity)messageActivity;
                await client.Conversations.SendToConversationAsync(activity);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message, ex);
            }
        }

        private static async Task SetPrivateConversationDataAsync<T>(IMessageActivity messageActivity, String key, T value)
        {
            using (ILifetimeScope scope = DialogModule.BeginLifetimeScope(Conversation.Container, messageActivity)) //System.MissingMethodException
            {
                IBotDataStore<BotData> botDataStore = scope.Resolve<IBotDataStore<BotData>>();
                Address address = Address.FromActivity(messageActivity);
                BotData privateConversationData = await botDataStore.LoadAsync(address, BotStoreType.BotPrivateConversationData, CancellationToken.None);

                privateConversationData.SetProperty(key, value);
                await botDataStore.SaveAsync(address, BotStoreType.BotPrivateConversationData, privateConversationData,
                    CancellationToken.None);

                await botDataStore.FlushAsync(address, CancellationToken.None);
            }
        }

Reproduction Steps

  1. Create a Class Library C# Function Bot
    1. Create a C# Function Bot
    2. Create an Azure Function with HTTP Trigger project in Visual Studio 2017
    3. Copy the code from the generated Function Bot to your Function
    4. Delete the C# Script bot from the Azure Portal
    5. Deploy the function you created
  2. Add a call to Conversation.Container, such as IContainer c = Conversation.Container; to the function
  3. make a call to the bot from Bot Emulator

Expected Behavior

Get an IContainer

Actual Results

Exception as described.

Stack Trace:

Varonis.Bot.Application.PasswordResponseFunction.<SetPrivateConversationDataAsync>d__1`1.MoveNext() System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start(TStateMachine& stateMachine) Varonis.Bot.Application.PasswordResponseFunction.SetPrivateConversationDataAsync(IMessageActivity messageActivity, String key, T value) Varonis.Bot.Application.PasswordResponseFunction.<Run>d__0.MoveNext() in PasswordResponseFunction.cs: line: 48

Additional Info

I Actually opened the Microsoft.Bot.Builder.dll with a decompiler (JetBrains dotPeek), and couldn’t find the Conversation class there. But when I pressed F12 on the property in the code, the VS decompiler did take me to the property.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 19 (7 by maintainers)

Most upvoted comments

I found a workaround for this. This bug is a manifestation of a bug in the function host, which is tied to Autofac 4.2.1. see Azure/azure-functions-host#2979 and Azure/azure-functions-host#1665. So to work around, I downgraded Autofac in my function to 4.2.1, and the problem disappeared.

How is this closed? was a fix checked in?

I was not using AzureFunctions.Autofac, but repro’d the exact same issue. Pretty weird. Played with versions of the Nuget packages and all.

I’m just gonna roll back some changes, and switch over to the Web App version. I was actually working on transitioning a pre-prod bot over to Functions, for the scalability. But this’ll have to do for our purposes. Considering there’s an Azure template for building a Function-based bot, you’d like to think it…worked. But so it goes.

Glad I found this thread, though! I’ve been banging my head for an hour.

Our considerations for choosing a functions bot were a) hopefully it will cost less, since (in Consumption plan) you only pay for actual CPU time. This is an internal organization bot, with a few dozens requests per day. And b) it’s a chance to learn new technology, which is always fun 😃