无法发布活动。取消授权。 Bot仿真器错误

时间:2019-04-12 07:26:43

标签: c# azure botframework

我已将以下代码行添加到我的机器人的Startup.cs中,以便它可以在Azure的WebChat中工作:

var appid = Configuration.GetSection("microsoftappid").Value;
var apppassword = Configuration.GetSection("microsoftapppassword").Value;
options.CredentialProvider = new SimpleCredentialProvider(appid, apppassword);

但是,当我有这些行时,我的机器人就无法在Bot模拟器中运行。如何将其与我的机器人集成在一起,以便在模拟器中发布和打开我的机器人时无需注释/取消注释代码行。我在阅读代码方面还不太好,很抱歉提出这个要求。谢谢!

public class Startup
{
    private ILoggerFactory _loggerFactory;
    private bool _isProduction = false;

    public Startup(IHostingEnvironment env)
    {
        _isProduction = env.IsProduction();

        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            .AddEnvironmentVariables();

        Configuration = builder.Build();
    }

    public IConfiguration Configuration { get; }


    public void ConfigureServices(IServiceCollection services)
    {
        var secretKey = Configuration.GetSection("botFileSecret")?.Value;
        var botFilePath = Configuration.GetSection("botFilePath")?.Value;
        if (!File.Exists(botFilePath))
        {
            throw new FileNotFoundException($"The .bot configuration file was not found. botFilePath: {botFilePath}");
        }

        BotConfiguration botConfig = null;
        try
        {
            botConfig = BotConfiguration.Load(botFilePath, secretKey);
        }
        catch
        {
            var msg = @"Error reading bot file. Please ensure you have valid botFilePath and botFileSecret set for your environment.
            - You can find the botFilePath and botFileSecret in the Azure App Service application settings.
            - If you are running this bot locally, consider adding a appsettings.json file with botFilePath and botFileSecret.
            - See https://aka.ms/about-bot-file to learn more about .bot file its use and bot configuration.
            ";
            throw new InvalidOperationException(msg);
        }

        services.AddSingleton(sp => botConfig ?? throw new InvalidOperationException($"The .bot configuration file could not be loaded. botFilePath: {botFilePath}"));

        var connectedServices = InitBotServices(botConfig);
        services.AddSingleton(sp => connectedServices);

        var environment = _isProduction ? "production" : "development";
        var service = botConfig.Services.FirstOrDefault(s => s.Type == "endpoint" && s.Name == environment);
        if (service == null && _isProduction)
        {

            service = botConfig.Services.Where(s => s.Type == "endpoint" && s.Name == "development").FirstOrDefault();
        }

        if (!(service is EndpointService endpointService))
        {
            throw new InvalidOperationException($"The .bot file does not contain an endpoint with name '{environment}'.");
        }

        services.AddBot<CoreBot>(options =>
        {
            options.CredentialProvider = new SimpleCredentialProvider(endpointService.AppId, endpointService.AppPassword);
            options.ChannelProvider = new ConfigurationChannelProvider(Configuration);

            var appid = Configuration.GetSection("microsoftappid").Value;
            var apppassword = Configuration.GetSection("microsoftapppassword").Value;
            options.CredentialProvider = new SimpleCredentialProvider(appid, apppassword);

            ILogger logger = _loggerFactory.CreateLogger<CoreBot>();
            options.OnTurnError = async (context, exception) =>
            {
                logger.LogError($"Exception caught : {exception}");
                await context.SendActivityAsync($"Oops Sorry, it looks like something went wrong.");
            };

            IStorage dataStore = new MemoryStorage();

            var conversationState = new ConversationState(dataStore);
            options.State.Add(conversationState);

            var userState = new UserState(dataStore);
            options.State.Add(userState);

        });

        services.AddSingleton<BasicAccessors>(sp =>
        {
            var options = sp.GetRequiredService<IOptions<BotFrameworkOptions>>().Value;
            if (options == null)
            {
                throw new InvalidOperationException("BotFrameworkOptions must be configured prior to setting up the state accessors");
            }

            var conversationState = options.State.OfType<ConversationState>().FirstOrDefault();
            if (conversationState == null)
            {
                throw new InvalidOperationException(
                    "ConversationState must be defined and added before adding conversation-scoped state accessors.");
            }

            var userState = options.State.OfType<UserState>().FirstOrDefault();
            if (userState == null)
            {
                throw new InvalidOperationException(
                    "UserState must be defined and added before adding user-scoped state accessors.");
            }

            var accessors = new BasicAccessors(conversationState, userState)
            {
                DialogStateAccessor = conversationState.CreateProperty<DialogState>(BasicAccessors.DialogStateAccessorName),
                UserStateAccessor = userState.CreateProperty<UserProfile>(BasicAccessors.UserStateAccessorName),
                ComplaintTicketAccessor = conversationState.CreateProperty<ComplaintTicket>(BasicAccessors.ComplaintTicketName),
            };

            return accessors;
        });
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        _loggerFactory = loggerFactory;

        app.UseDefaultFiles()
            .UseStaticFiles()
            .UseBotFramework();
    }

    private static BotServices InitBotServices(BotConfiguration config)
    {
        var qnaServices = new Dictionary<string, QnAMaker>();
        var luisServices = new Dictionary<string, LuisRecognizer>();

        foreach (var service in config.Services)
        {
            switch (service.Type)
            {
                case ServiceTypes.Luis:
                    {
                        if (!(service is LuisService luis))
                        {
                            throw new InvalidOperationException("The LUIS service is not configured correctly in your '.bot' file.");
                        }

                        var app = new LuisApplication(luis.AppId, luis.SubscriptionKey, luis.GetEndpoint());
                        var recognizer = new LuisRecognizer(app);
                        luisServices.Add(luis.Name, recognizer);
                        break;
                    }

                case ServiceTypes.Dispatch:

                    if (!(service is DispatchService dispatch))
                    {
                        throw new InvalidOperationException("The Dispatch service is not configured correctly in your '.bot' file.");
                    }        

                    var dispatchApp = new LuisApplication(dispatch.AppId, dispatch.AuthoringKey, dispatch.GetEndpoint());

                    var dispatchARecognizer = new LuisRecognizer(dispatchApp);
                    luisServices.Add(dispatch.Name, dispatchARecognizer);
                    break;

                case ServiceTypes.QnA:
                    {

                        if (!(service is QnAMakerService qna))
                        {
                            throw new InvalidOperationException("The QnA service is not configured correctly in your '.bot' file.");
                        }

                        var qnaEndpoint = new QnAMakerEndpoint()
                        {
                            KnowledgeBaseId = qna.KbId,
                            EndpointKey = qna.EndpointKey,
                            Host = qna.Hostname,
                        };

                        var qnaMaker = new QnAMaker(qnaEndpoint);
                        qnaServices.Add(qna.Name, qnaMaker);

                        break;
                    }
            }
        }

        return new BotServices(qnaServices, luisServices);
    }
}

}

2 个答案:

答案 0 :(得分:1)

使用2个.bot文件(例如dev.bot和prod.bot)

在dev.bot中,为仿真器添加端点,如下所示:

{
  "type": "endpoint",
  "name": "dev",
  "endpoint": "http://localhost:3978/api/messages",
  "appId": "",
  "appPassword": "",
  "id": "1"
},

您将在prod.bot中添加appId和appPassword以及正确的终结点(例如,托管在Azure上:***。azurewebsites.net/api/messages)。

使用appSettings.json +创建appSettings.dev.json和appSettings.prod.json。确保.dev.json设置

"botFilePath": ".\\dev.bot"

类似于appSettings.prod.json。

我发现,当ASPNETCORE_ENVIRONMENT环境变量不等于正在使用的.bot文件中的“名称”端点参数时,您会在模拟器中收到未授权的错误。因此,在模拟器上进行本地调试时,请将ASPNETCORE_ENVIRONMENT设置为(在这种情况下)等于“ dev”。

您可以通过右键单击.NET核心Web项目->属性->调试(选项卡)->环境变量进行设置。

Set env vars in .NET core web project

答案 1 :(得分:0)

您可以使用此代码来满足您的需求。如果您在本地环境中运行代码,则_isProduction的值为false。如果您在Azure中运行代码,则_isProduction的值为true。

       var appid = Configuration.GetSection("microsoftappid").Value;
       var apppassword = Configuration.GetSection("microsoftapppassword").Value;
       if (_isProduction)
       {
           options.CredentialProvider = new SimpleCredentialProvider(appid, apppassword);
       }
       else
       {
           options.CredentialProvider = new SimpleCredentialProvider(endpointService.AppId, endpointService.AppPassword);
       }

将本地漫游器appsettings.json文件中的botFileSecret和botFilePath添加到新的appsettings.json文件中。

enter image description here

现在,代码将同时在Azure和模拟器上运行。 此外,我注意到您正在使用的Memory Storage仅用于本地bot调试。重新启动漫游器后,存储在内存中的所有内容都将消失。

IStorage dataStore = new MemoryStorage();

对于生产机器人,您可以使用Azure Blob或Azure CosmosDB存储提供程序。