I am needing some help. I am new at developing in Azure's Bot Framework, creating my first chatbot some weeks ago using a QnA KB. In any case, I managed to create the bot in Azure's portal and it is working perfectly. But I need to do some alterations and tests in Bot Framework Emulator (using V4) and, to do so, download and run locally my bot.
I made the download of my bot's .zip file following Azure's instructions and initialized it using Visual Studio 2017 as my IDE. When I hit the button "debug", though, the program tries to connect to localhost:3984.
using Autofac;
using System.Web.Http;
using System.Configuration;
using System.Reflection;
using Microsoft.Bot.Builder.Azure;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.Dialogs.Internals;
using Microsoft.Bot.Connector;
namespace SimpleEchoBot
{
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
// Bot Storage: This is a great spot to register the private state storage for your bot.
// We provide adapters for Azure Table, CosmosDb, SQL Azure, or you can implement your own!
// For samples and documentation, see: https://github.com/Microsoft/BotBuilder-Azure
Conversation.UpdateContainer(
builder =>
{
builder.RegisterModule(new AzureModule(Assembly.GetExecutingAssembly()));
// Using Azure Table Storage
var store = new TableBotDataStore(ConfigurationManager.AppSettings["AzureWebJobsStorage"]); // requires Microsoft.BotBuilder.Azure Nuget package
// To use CosmosDb or InMemory storage instead of the default table storage, uncomment the corresponding line below
// var store = new DocumentDbBotDataStore("cosmos db uri", "cosmos db key"); // requires Microsoft.BotBuilder.Azure Nuget package
// var store = new InMemoryDataStore(); // volatile in-memory store
builder.Register(c => store)
.Keyed<IBotDataStore<BotData>>(AzureModule.Key_DataStore)
.AsSelf()
.SingleInstance();
});
GlobalConfiguration.Configure(WebApiConfig.Register);
}
}
}
In matter of seconds, though, the following line of code returns the error System.ArgumentNullException: 'Value cannot be null. Arg_ParamName_Name':
var store = new TableBotDataStore(ConfigurationManager.AppSettings["AzureWebJobsStorage"]); // requires Microsoft.BotBuilder.Azure Nuget package
As a consequence, I am unable to test my bot in the Bot Framework Emulator. Since I am really new with C#, could anyone give me a hand at solving this?
EDIT: Here is my web.config part of the code, just removing sensitive data:
<?xml version="1.0" encoding="utf-8"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=301879
-->
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<appSettings>
<!-- update these with your Microsoft App Id and your Microsoft App Password-->
<!--<add key="BotId" value="" />-->
<add key="MicrosoftAppId" value="" />
<add key="MicrosoftAppPassword" value="" />
<add key="QnaSubscriptionKey" value="" />
<add key="QnaKnowledgebaseId" value="" />
<add key="AzureWebJobsStorage" value="" />
</appSettings>
<!--
For a description of web.config changes see http://go.microsoft.com/fwlink/?LinkId=235367.
The following attributes can be set on the <httpRuntime> tag.
<system.Web>
<httpRuntime targetFramework="4.6" />
</system.Web>
-->
<system.web>
<customErrors mode="Off" />
<compilation debug="true" targetFramework="4.6" />
<httpRuntime targetFramework="4.6" />
</system.web>
<system.webServer>
<defaultDocument>
<files>
<clear />
<add value="default.htm" />
</files>
</defaultDocument>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.29.0" newVersion="4.2.29.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IdentityModel.Tokens.Jwt" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.1.4.0" newVersion="5.1.4.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.Protocol.Extensions" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.0.40306.1554" newVersion="1.0.40306.1554" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Bot.Connector" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.15.2.2" newVersion="3.15.2.2" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Bot.Builder" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.15.2.2" newVersion="3.15.2.2" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Azure.Documents.Client" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.11.0.0" newVersion="1.11.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Bot.Builder.History" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.12.2.4" newVersion="3.12.2.4" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Bot.Builder.Autofac" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.15.2.2" newVersion="3.15.2.2" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Data.Services.Client" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.7.0.0" newVersion="5.7.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Data.OData" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.7.0.0" newVersion="5.7.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Data.Edm" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.7.0.0" newVersion="5.7.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<system.codedom>
<compilers>
<compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:6 /nowarn:1659;1699;1701" />
<compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:14 /nowarn:41008 /define:_MYTYPE=\"Web\" /optionInfer+" />
</compilers>
</system.codedom>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
</configuration>
EDIT 2: Some screenshots of the issue so far:
EDIT 3: Trying to solve "Please set QnAKnowledgebaseId, QnAAuthKey and QnAEndpointHostName (if applicable) in App Settings. Learn how to get them at https://aka.ms/qnaabssetup.". Basic QnAMakerDialog.cs so far (the first instances of qnaAuthKey, qnaKBId and endpointHostName had values attributed to them, but I erased them at here for safety):
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Azure;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.CognitiveServices.QnAMaker;
using Microsoft.Bot.Connector;
using System.Configuration;
namespace Microsoft.Bot.Sample.QnABot
{
[Serializable]
public class RootDialog : IDialog<object>
{
public async Task StartAsync(IDialogContext context)
{
/* Wait until the first message is received from the conversation and call MessageReceviedAsync
* to process that message. */
context.Wait(this.MessageReceivedAsync);
}
private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
{
/* When MessageReceivedAsync is called, it's passed an IAwaitable<IMessageActivity>. To get the message,
* await the result. */
var message = await result;
var qnaAuthKey = GetSetting("");
var qnaKBId = ConfigurationManager.AppSettings[""];
var endpointHostName = ConfigurationManager.AppSettings[""];
// QnA Subscription Key and KnowledgeBase Id null verification
if (!string.IsNullOrEmpty(qnaAuthKey) && !string.IsNullOrEmpty(qnaKBId))
{
// Forward to the appropriate Dialog based on whether the endpoint hostname is present
if (string.IsNullOrEmpty(endpointHostName))
await context.Forward(new BasicQnAMakerPreviewDialog(), AfterAnswerAsync, message, CancellationToken.None);
else
await context.Forward(new BasicQnAMakerDialog(), AfterAnswerAsync, message, CancellationToken.None);
}
else
{
await context.PostAsync("Please set QnAKnowledgebaseId, QnAAuthKey and QnAEndpointHostName (if applicable) in App Settings. Learn how to get them at https://aka.ms/qnaabssetup.");
}
}
private async Task AfterAnswerAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
{
// wait for the next user message
context.Wait(MessageReceivedAsync);
}
public static string GetSetting(string key)
{
var value = ConfigurationManager.AppSettings[key];
if (String.IsNullOrEmpty(value) && key == "QnAAuthKey")
{
value = ConfigurationManager.AppSettings["QnASubscriptionKey"]; // QnASubscriptionKey for backward compatibility with QnAMaker (Preview)
}
return value;
}
}
// Dialog for QnAMaker Preview service
[Serializable]
public class BasicQnAMakerPreviewDialog : QnAMakerDialog
{
// Go to https://qnamaker.ai and feed data, train & publish your QnA Knowledgebase.
// Parameters to QnAMakerService are:
// Required: subscriptionKey, knowledgebaseId,
// Optional: defaultMessage, scoreThreshold[Range 0.0 – 1.0]
public BasicQnAMakerPreviewDialog() : base(new QnAMakerService(new QnAMakerAttribute(RootDialog.GetSetting("QnAAuthKey"), ConfigurationManager.AppSettings["QnAKnowledgebaseId"], "No good match in FAQ.", 0.5)))
{ }
}
// Dialog for QnAMaker GA service
[Serializable]
public class BasicQnAMakerDialog : QnAMakerDialog
{
// Go to https://qnamaker.ai and feed data, train & publish your QnA Knowledgebase.
// Parameters to QnAMakerService are:
// Required: qnaAuthKey, knowledgebaseId, endpointHostName
// Optional: defaultMessage, scoreThreshold[Range 0.0 – 1.0]
public BasicQnAMakerDialog() : base(new QnAMakerService(new QnAMakerAttribute(RootDialog.GetSetting("QnAAuthKey"), ConfigurationManager.AppSettings["QnAKnowledgebaseId"], "Desculpe, não entendi muito bem sua pergunta... Poderia refazê-la de forma diferente? Caso já tenha tentado, talvez eu ainda não saiba como responder sua dúvida.", 0.3, 1, ConfigurationManager.AppSettings["QnAEndpointHostName"])))
{ }
}
}
答案 0 :(得分:4)
正如错误提到的那样,问题是AzureWebJobsStorage
文件中找不到web.config
。要解决您的问题,请在azure门户中导航到您的bot,然后单击左侧刀片上的应用程序设置。在那里,您会找到一个带有密钥AzureWebJobsStorage
的设置。
复制设置的值并将其粘贴到web.config
文件中:
<configuration>
<appSettings>
<!-- update these with your BotId, Microsoft App Id and your Microsoft App Password-->
<add key="BotId" value="YourBotId" />
<add key="MicrosoftAppId" value="" />
<add key="MicrosoftAppPassword" value="" />
<add key="QnaSubscriptionKey" value="" />
<add key="QnaKnowledgebaseId" value="" />
<add key="AzureWebJobsStorage" value="copied value from azure portal" />
</appSettings>
<强>更新强>
要回答评论中发布的进一步问题,
我被重定向到浏览器中的空白页面,地址为localhost:3984,文本中可以读取QnABot模板,然后是一些链接
表示僵尸程序现在运行正常,实际上是预期的行为。 要在本地测试机器人,您需要使用Bot Emulator。按照链接中提到的步骤测试机器人。您还可以浏览bot framework链接,因为这样可以让您更清楚地了解Microsoft Bot Framework。
更新2:
根据您发布的截图,我认为您已更改了Global.asax
文件。
注册TableBotDataStore
的代码应该是
var store = new TableBotDataStore(ConfigurationManager.AppSettings["AzureWebJobsStorage"]);
根本没有变化。
其次如费韩所说:
Utils.GetAppSetting(string key)
方法适用于在Azure上运行的漫游器,如果您想在本地访问bot应用程序并从web.config文件访问设置,则可以使用ConfigurationManager.AppSettings[“your_key”]
替换{ {1}}在QnAMakerDialog中。
第二个屏幕截图显示您的代码中仍有Utils.GetAppSetting(“your_key”)
。将其替换为:
Utils.GetAppSetting(“your_key”)
以及其他地方等等。
答案 1 :(得分:1)
错误System.ArgumentNullException:'值不能为空。
正如Ashwin Kumar所提到的,您应该在web.config文件中为您的机器人应用程序包含"AzureWebJobsStorage"
的名称/值对。
System.FormatException:'设置必须是“name = value”形式。
请检查您是否获得值ConfigurationManager.AppSettings["AzureWebJobsStorage"]
并传递有效的连接字符串以启动TableBotDataStore,而不仅仅是传递密钥"AzureWebJobsStorage"
。
我需要在Bot Framework Emulator中进行一些更改和测试(使用V4),然后在本地下载并运行我的机器人
Utils.GetAppSetting(string key) method适用于在Azure上运行的漫游器,如果您想在本地访问bot应用程序并从web.config文件访问设置,则可以使用 ConfigurationManager.AppSettings [“your_key”] 在QnAMakerDialog中替换 Utils.GetAppSetting(“your_key”) ,如下所示:
//var qnaKBId = Utils.GetAppSetting("QnAKnowledgebaseId");
var qnaKBId = ConfigurationManager.AppSettings["QnAKnowledgebaseId"];