Я разрабатываю чат-бота с использованием MS bot Framework v4 SDK в C#.
Я выбрал Отправка образца бота в качестве своей базы, так как я использую QnA Создатель и Луис. Теперь я хочу добавить аутентификацию для доступа к моему боту. В соответствии с примером Authentication Bot Я добавил все зависимости, включая пакеты nuget, методы и классы, в код моего проекта бота, но все равно аутентификация у меня не работает, он выдает ошибку исключения и дает извините что-то пошло не так ошибка. Может быть некоторая проблема со способом интеграции и вызовом правильных методов.
, если у кого-либо есть решение или образец бота с аутентификацией и с использованием QnA Maker, пожалуйста, поделитесь со мной.
Мой код: Dispatchbot.cs
namespace Microsoft.BotBuilderSamples
{
public class DispatchBot<T> : ActivityHandler where T : Dialog
{
private ILogger _logger;
private IBotServices _botServices;
private BotState _conversationState;
private BotState _userState;
protected readonly Dialog Dialog;
public DispatchBot(ConversationState conversationState, UserState userState, T dialog, ILogger<DispatchBot<T>> logger, IBotServices botServices)
{
_conversationState = conversationState;
_userState = userState;
Dialog = dialog;
_logger = logger;
_botServices = botServices;
}
[HttpGet]
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
await Dialog.RunAsync(turnContext, _conversationState.CreateProperty<DialogState>(nameof(DialogState)), cancellationToken);
/*....my custom logic..........*/
}
//added for authentication
protected override async Task OnTokenResponseEventAsync(ITurnContext<IEventActivity> turnContext, CancellationToken cancellationToken)
{
_logger.LogInformation("Running dialog with Token Response Event Activity.");
// Run the Dialog with the new Token Response Event Activity.
await Dialog.RunAsync(turnContext, _conversationState.CreateProperty<DialogState>(nameof(DialogState)), cancellationToken);
}
//added code for welcome message on page load
protected override async Task OnEventActivityAsync(ITurnContext<IEventActivity> turnContext, CancellationToken cancellationToken)
{
var oneventconversationStateAccessors = _conversationState.CreateProperty<oneventvalues>(nameof(oneventvalues));
var onevntconversationData = await oneventconversationStateAccessors.GetAsync(turnContext, () => new oneventvalues());
var objectdata = JsonConvert.DeserializeObject<dynamic>(turnContext.Activity.Value.ToString());
data _data = new data();
_data.prodselected = objectdata["Product"];
_data.relselected = objectdata["Release"];
_data.hour = objectdata["Hour"];
/*....my custom logic..........*/
}
public class data
{
public string prodselected { get; set; }
public string relselected { get; set; }
public int hour { get; set; }
}
protected override async Task OnMembersAddedAsync(IList<ChannelAccount> membersAdded, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
{
var userStateAccessors = _userState.CreateProperty<UserProfile>(nameof(UserProfile));
var userProfile = await userStateAccessors.GetAsync(turnContext, () => new UserProfile());
foreach (var member in membersAdded)
{
if (member.Id != turnContext.Activity.Recipient.Id)
{
userProfile.Name = member.Name.Replace('.', ' ');
await turnContext.SendActivityAsync(MessageFactory.Text($"Hi **{member.Name.Replace('.',' ')}**. I'm your Assistant."), cancellationToken);
User = member.Name;
}
}
}
//added from statemanagement
public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
{
if (turnContext?.Activity?.Type == ActivityTypes.Invoke && turnContext.Activity.ChannelId == "msteams")
await Dialog.Run(turnContext, _conversationState.CreateProperty<DialogState>(nameof(DialogState)), cancellationToken);
else
await base.OnTurnAsync(turnContext, cancellationToken);
// Save any state changes that might have occured during the turn.
await _conversationState.SaveChangesAsync(turnContext, false, cancellationToken);
await _userState.SaveChangesAsync(turnContext, false, cancellationToken);
}
private async Task DispatchToTopIntentAsync(ITurnContext<IMessageActivity> turnContext, string intent, RecognizerResult recognizerResult, CancellationToken cancellationToken, ConversationData conversationData)
{
switch (intent)
{
case "q-qna-1":
await Process1(turnContext, cancellationToken,conversationData);
break;
case "q-qna-2":
await Process2(turnContext, cancellationToken, conversationData);
break;
default:
_logger.LogInformation($"Dispatch unrecognized intent: {intent}.");
}
}
/*....my custom logic methods.........*/
}
Authbot.cs
namespace Microsoft.BotBuilderSamples
{
public class AuthBot<T> : DispatchBot<T> where T : Dialog
{
public AuthBot(ConversationState conversationState, UserState userState, ILogger<DispatchBot<T>> logger, T dialog, IBotServices botServices )
: base(conversationState, userState, dialog, logger, botServices)
{
}
protected override async Task OnMembersAddedAsync(IList<ChannelAccount> membersAdded, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
{
foreach (var member in turnContext.Activity.MembersAdded)
{
if (member.Id != turnContext.Activity.Recipient.Id)
{
await turnContext.SendActivityAsync(MessageFactory.Text("Welcome to AuthenticationBot ."), cancellationToken);
}
}
}
}
}
MainDialog :
namespace Microsoft.BotBuilderSamples
{
public class MainDialog : LogoutDialog
{
protected readonly ILogger Logger;
public MainDialog(IConfiguration configuration, ILogger<MainDialog> logger)
: base(nameof(MainDialog), configuration["ConnectionName"])
{
Logger = logger;
AddDialog(new OAuthPrompt(
nameof(OAuthPrompt),
new OAuthPromptSettings
{
ConnectionName = ConnectionName,
Text = "Please Sign In",
Title = "Sign In",
Timeout = 300000, // User has 5 minutes to login (1000 * 60 * 5)
}));
AddDialog(new ConfirmPrompt(nameof(ConfirmPrompt)));
AddDialog(new WaterfallDialog(nameof(WaterfallDialog), new WaterfallStep[]
{
PromptStepAsync,
LoginStepAsync,
DisplayTokenPhase1Async,
DisplayTokenPhase2Async,
}));
// The initial child Dialog to run.
InitialDialogId = nameof(WaterfallDialog);
}
private async Task<DialogTurnResult> PromptStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
return await stepContext.BeginDialogAsync(nameof(OAuthPrompt), null, cancellationToken);
}
private async Task<DialogTurnResult> LoginStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
// Get the token from the previous step. Note that we could also have gotten the
// token directly from the prompt itself. There is an example of this in the next method.
var tokenResponse = (TokenResponse)stepContext.Result;
if (tokenResponse != null)
{
await stepContext.Context.SendActivityAsync(MessageFactory.Text("You are now logged in."), cancellationToken);
return await stepContext.PromptAsync(nameof(ConfirmPrompt), new PromptOptions { Prompt = MessageFactory.Text("Would you like to view your token?") }, cancellationToken);
}
await stepContext.Context.SendActivityAsync(MessageFactory.Text("Login was not successful please try again."), cancellationToken);
return await stepContext.EndDialogAsync(cancellationToken: cancellationToken);
}
private async Task<DialogTurnResult> DisplayTokenPhase1Async(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
await stepContext.Context.SendActivityAsync(MessageFactory.Text("Thank you."), cancellationToken);
var result = (bool)stepContext.Result;
if (result)
{
// Call the prompt again because we need the token. The reasons for this are:
// 1. If the user is already logged in we do not need to store the token locally in the bot and worry
// about refreshing it. We can always just call the prompt again to get the token.
// 2. We never know how long it will take a user to respond. By the time the
// user responds the token may have expired. The user would then be prompted to login again.
//
// There is no reason to store the token locally in the bot because we can always just call
// the OAuth prompt to get the token or get a new token if needed.
return await stepContext.BeginDialogAsync(nameof(OAuthPrompt), cancellationToken: cancellationToken);
}
return await stepContext.EndDialogAsync(cancellationToken: cancellationToken);
}
private async Task<DialogTurnResult> DisplayTokenPhase2Async(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
var tokenResponse = (TokenResponse)stepContext.Result;
if (tokenResponse != null)
{
await stepContext.Context.SendActivityAsync(MessageFactory.Text($"Here is your token {tokenResponse.Token}"), cancellationToken);
}
return await stepContext.EndDialogAsync(cancellationToken: cancellationToken);
}
}
}
Окончательное сообщение об ошибке в исключении:
невозможно получить идентификатор приложения бота из заявки на аудиторию.