C# 无法将参数传递给ContinueConversationAsync方法内的BotCallback

C# 无法将参数传递给ContinueConversationAsync方法内的BotCallback,c#,asp.net-core,botframework,C#,Asp.net Core,Botframework,我正在尝试在bot framework v4上实现主动消息,它可以工作,但仅使用BotCallback函数上的字符串,我需要传递自定义文本,但ContinueConversationAsync似乎不允许这样做 public async Task<bool> SendProactiveMessage(MensajeExterno mensajeExterno) { var referenciaDeConversacion = Obten

我正在尝试在bot framework v4上实现主动消息,它可以工作,但仅使用BotCallback函数上的字符串,我需要传递自定义文本,但ContinueConversationAsync似乎不允许这样做

        public async Task<bool> SendProactiveMessage(MensajeExterno mensajeExterno)
    {

            var referenciaDeConversacion = ObtenerReferenciaConversacion(mensajeExterno.ConversationId);
            var continuationActivity = referenciaDeConversacion.GetContinuationActivity();
            if (referenciaDeConversacion == null) return false;


            await ((BotAdapter)_adapter).ContinueConversationAsync(_appId, referenciaDeConversacion, BotCallback, default(CancellationToken));

            return true;

    }

    private ConversationReference ObtenerReferenciaConversacion(string conversationId)
    {
        return new ConversationReferenceModulo().ObtenerConversationReference(conversationId);
    }

    public MensajeroDefaultModulo(IBotFrameworkHttpAdapter adapter, IConfiguration configuration)
    {
        _adapter = adapter;
        _appId = configuration["MicrosoftAppId"];

        if (string.IsNullOrEmpty(_appId))
        {
            _appId = Guid.NewGuid().ToString(); //if no AppId, use a random Guid
        }
    }

    private async Task BotCallback(ITurnContext turnContext, CancellationToken cancellationToken)
    {
        var activity = turnContext.Activity;
        await turnContext.SendActivityAsync("proactive hello", cancellationToken: cancellationToken);
    }

我知道您想要做的是向BotCallback传递一个值,该值可以通过SendActivityAsync方法发送回来

为此,可以使用lambda表达式而不是调用BotCallback

public async Task<bool> SendProactiveMessage(MensajeExterno mensajeExterno)
{
        var yourVariable = "blah";

        var referenciaDeConversacion = ObtenerReferenciaConversacion(mensajeExterno.ConversationId);
        var continuationActivity = referenciaDeConversacion.GetContinuationActivity();
        if (referenciaDeConversacion == null) return false;


        await ((BotAdapter)_adapter).ContinueConversationAsync(_appId, referenciaDeConversacion, async (context, token) => { 
await turnContext.SendActivityAsync("proactive hello " + yourVariable, cancellationToken: cancellationToken); 
}, default(CancellationToken));
        return true;
}
这源于此处对主动消息传递示例的引用:

有关Lambda表达式,请参见

lambda表达式是一个匿名函数,可以包含 表达式和语句,并可用于创建委托或 表达式树类型

所有lambda表达式都使用lambda运算符=>,该运算符被读取为 去。lambda运算符的左侧指定输入 参数(如果有),右侧包含表达式或 语句块。lambda表达式x=>x*x读取x到x 时报x

更新了API控制器示例

SendProactiveMessage需要位于Bot项目的控制器中,例如:

using System;
using System.Collections.Concurrent;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Integration.AspNet.Core;
using Microsoft.Bot.Schema;
using Microsoft.Extensions.Configuration;

namespace ProactiveBot.Controllers
{
    [Route("api/notify")]
    [ApiController]
    public class NotifyController : ControllerBase
    {
        private readonly IBotFrameworkHttpAdapter _adapter;
        private readonly string _appId;
        private readonly ConcurrentDictionary<string, ConversationReference> _conversationReferences;
    public NotifyController(IBotFrameworkHttpAdapter adapter, IConfiguration configuration, ConcurrentDictionary<string, ConversationReference> conversationReferences)
    {
        _adapter = adapter;
        _conversationReferences = conversationReferences;
        _appId = configuration["MicrosoftAppId"];

        // If the channel is the Emulator, and authentication is not in use,
        // the AppId will be null.  We generate a random AppId for this case only.
        // This is not required for production, since the AppId will have a value.
        if (string.IsNullOrEmpty(_appId))
        {
            _appId = Guid.NewGuid().ToString(); //if no AppId, use a random Guid
        }
    }

    public async Task<IActionResult> Get([FromQuery(Name = "taskID")] int taskID)
    {            

        foreach (var conversationReference in _conversationReferences.Values)
        {                

            await ((BotAdapter)_adapter).ContinueConversationAsync(_appId, conversationReference, async (context, token) => {
                await context.SendActivityAsync("proactive task notification for TaskID: " + taskID.ToString());
            }, default(CancellationToken));
        }


        // Let the caller know proactive messages have been sent
        return new ContentResult()
        {
            Content = "<html><body><h1>Proactive messages have been sent.</h1><p>" + taskID.ToString() + "</p></body></html>",
            ContentType = "text/html",
            StatusCode = (int)HttpStatusCode.OK,
        };
    }

}
}

然后,您可以通过注入的适配器访问上下文和令牌。以上代码主要来自当前版本


因此,我可以调用这个API,例如在我的例子中传入taskID参数,然后通过ContinueConversationAsync发送给用户。

您可以使用LINQ方法对BotCallback进行包装。但就我个人而言,我不理解这些代表没有任何事件的想法

    [HttpPost]
    public async Task<IActionResult> Post([FromBody] string messageText)
    {
        foreach (var conversationReference in _conversationReferences.Values)
        {
            await ((BotAdapter)_adapter).ContinueConversationAsync(_appId, conversationReference, async (context, token) => await BotCallback(messageText, context, token), default(CancellationToken));
        }

        return new ContentResult()
        {
            Content = "<html><body><h1>Proactive messages have been sent.</h1></body></html>",
            ContentType = "text/html",
            StatusCode = (int)HttpStatusCode.OK,
        };
    }

    private async Task BotCallback(string message, ITurnContext turnContext, CancellationToken cancellationToken)
    {
        await turnContext.SendActivityAsync(message, cancellationToken: cancellationToken);
    }

你所说的自定义文本是什么意思?谢谢Christopher,这里的问题是我既没有turnContext也没有cancellationToken。API调用SendProactiveMessage方法,如何解决这个问题?我尝试了依赖注入,但没有成功it@TheMemebot您的SendProactiveMessage方法是否不在您的Bot项目的控制器中?我将尝试您的更新解决方案,并将返回给您,让您知道该方法是否有效。是的,我的方法在我的机器人内project@TheMemebot运气好吗?