Bot Framework возвращается - при отправке этого сообщения вашему боту произошла ошибка: код состояния HTTP 401: не авторизован - PullRequest
0 голосов
/ 24 сентября 2018

Я развернул чат-бот на оконном сервере, но через несколько дней я получаю следующую ошибку в боте «Произошла ошибка при отправке этого сообщения вашему боту: код состояния HTTP InternalServerError», и в приложении отображается следующее сообщение «Операция вернула недопустимыйкод состояния «Несанкционированный», и это происходило 8 раз за последние 4 дня.

Что это значит:

1) Сообщения не могут получить доступ к серверу окон.

2) Сообщения доходят до сервера, и чат-бот испытывает некоторые проблемы.

3) Это проблема в конце Microsoft

Я использую версию 3.15.3 (Bot.builder).

Кто-нибудь сталкивался с такой же проблемой?

1 Ответ

0 голосов
/ 24 сентября 2018

К сожалению, похоже, что это проблема в самой Bot Framework , в настоящее время для решения этой проблемы необходимо зарегистрировать DocumentDbBotDataStore вместо TableBotDataStore, в вас Global.asax.cs_ApplicationStart поместите эти:

var uri = new Uri(ConfigurationManager.AppSettings["DocumentDBUri"]);
var key = ConfigurationManager.AppSettings["DocumentDBKey"];

var store = new DocumentDbBotDataStore(uri, key);

Conversation.UpdateContainer(
    builder =>
    {
        builder.Register(c => store)
            .Keyed<IBotDataStore<BotData>>(AzureModule.Key_DataStore)
            .AsSelf()
            .SingleInstance();
    });

Редактировать:

Есть исправление огромный клейкой ленты, я не хотел публиковать, что я реализовал некоторое время назад иудалось заставить его работать.Идея состоит в том, чтобы найти сервис устранения неполадок и взломать структуру бота, переопределив его и заставив повторить попытку.В какой-то момент менеджер кэша токенов в фреймворке становится неисправным, и токен доступа не обновляется вовремя, прежде чем сделать запрос, мы вызываем Unauthorized Error, поэтому мы также взламываем его и заставляем обновить токен.

Вот как:

Мы перезаписываем IBotToUser декоратор платформы ботов, который создает HttpRequest, который вызывает ошибку:

public class RetryHandlerDecorator : IBotToUser
{
    private readonly IMessageActivity _toBot;
    private readonly IConnectorClient _client;

    public RetryHandlerDecorator(IMessageActivity toBot, IConnectorClient client)
    {
        SetField.NotNull(out _toBot, nameof(toBot), toBot);
        SetField.NotNull(out _client, nameof(client), client);
    }

    IMessageActivity IBotToUser.MakeMessage()
    {
        var toBotActivity = (Activity)_toBot;
        return toBotActivity.CreateReply();
    }

    async Task IBotToUser.PostAsync(IMessageActivity message, CancellationToken cancellationToken)
    {
        try
        {
            await _client.Conversations.ReplyToActivityAsync((Activity)message, cancellationToken);
        }
        catch (Exception e)
        {
            if (IsTransientError(e))
            {
                await HandleRetry(message, cancellationToken);
            }
            else
            {
                throw;
            }
        }
    }

    private async Task HandleRetry(IMessageActivity activity, CancellationToken token)
    {
        await ForceRefreshTokenAsync();

        await _client.Conversations.ReplyToActivityAsync((Activity)activity, token);
    }

    private async Task ForceRefreshTokenAsync()
    {
        var credentialsManager = new MicrosoftAppCredentials(
            ConfigurationManager.AppSettings[MicrosoftAppCredentials.MicrosoftAppIdKey],
            ConfigurationManager.AppSettings[MicrosoftAppCredentials.MicrosoftAppPasswordKey]);

        // force the generation of a new token
        // this will store the token in a static cache list, so no harm in creating a new instance of MicrosoftAppCredentials
        await credentialsManager.GetTokenAsync(true);
    }

    private static bool IsTransientError(Exception e)
    {
        switch (e)
        {
            case ErrorResponseException ex:
                return ex.Response.StatusCode == HttpStatusCode.Unauthorized;
            default:
                return false;
        }
    }
}

Мы переопределяем модуль каркаса бота, который регистрирует IBotToUser service:

public class BotToUserModuleOverride : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterType<RetryHandlerDecorator>().Keyed<IBotToUser>(typeof(RetryHandlerDecorator))
            .InstancePerLifetimeScope();

        RegisterAdapterChain<IBotToUser>(builder,
                typeof(RetryHandlerDecorator), // this was previously AlwaysSendDirect_BotToUser 
                typeof(AutoInputHint_BotToUser),
                typeof(MapToChannelData_BotToUser),
                typeof(LogBotToUser)
            )
            .InstancePerLifetimeScope();
    }

    public static IRegistrationBuilder<TLimit, SimpleActivatorData, SingleRegistrationStyle> RegisterAdapterChain<TLimit>(ContainerBuilder builder, params Type[] types)
    {
        return
            builder
                .Register(c =>
                {
                    var service = default(TLimit);

                    return types.Aggregate(service,
                        (current, t) => c.ResolveKeyed<TLimit>(t, TypedParameter.From(current)));
                })
                .As<TLimit>();
    }
}

И, наконец, мы взломаем контейнер IoC фреймворка ботов, зарегистрировав наш модуль, который переопределяет сервис, это нужно сделать в Global.asax.cs ApplicationStart:

Conversation.UpdateContainer(
    builder =>
    {
        builder.RegisterModule(new BotToUserModuleOverride());
    });

Так что случится так, что всякий раз, когда UnauthorizedError поднимается методом ReplyToActivityAsync, будет процесс, заставляющий обновить токен доступа и повторить попытку.

...