C# 客户端和服务器位于同一web应用程序中的Azure Bot项目
我已经使用BotFrameworkV4创建了一个Azure机器人应用程序,并使用作为接口。我注意到bot服务器的dotnetcore应用程序有一个wwwroot文件夹,其中有一个占位符HTML页面,因此我认为在那里托管webchat客户端可能比较方便。但现在,我的webchat客户端使用DirectLine将活动发送回为其提供服务的同一后端,这似乎与直觉背道而驰 我选择webchat客户端是因为我需要定制客户端的外观。我还需要为bot客户端提供服务的MVC应用程序包含azureactivedirectoryb2c身份验证(确实如此)。用户应该在身份验证之前和之后看到webchat客户端,但是bot后端(处理活动)需要知道用户是否登录并相应地修改其行为(我正在使用DirectLine努力实现这一点) 因此,我的第一个问题(关于StackOverflow)是:由于Bot后端和webchat客户端前端托管在同一个单一的Azure web应用程序中,是否有必要使用DirectLine,还是有更简单的方法 my Startup.cs中的相关代码:C# 客户端和服务器位于同一web应用程序中的Azure Bot项目,c#,asp.net-mvc,.net-core,azure-active-directory,botframework,C#,Asp.net Mvc,.net Core,Azure Active Directory,Botframework,我已经使用BotFrameworkV4创建了一个Azure机器人应用程序,并使用作为接口。我注意到bot服务器的dotnetcore应用程序有一个wwwroot文件夹,其中有一个占位符HTML页面,因此我认为在那里托管webchat客户端可能比较方便。但现在,我的webchat客户端使用DirectLine将活动发送回为其提供服务的同一后端,这似乎与直觉背道而驰 我选择webchat客户端是因为我需要定制客户端的外观。我还需要为bot客户端提供服务的MVC应用程序包含azureactivedir
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
_loggerFactory = loggerFactory;
app.UseStaticFiles(); // to allow serving up the JS, CSS, etc., files.
app.UseBotFramework(); // to add middleware to route webchat activity to the bot back-end code
app.UseSession(); // to enable session state
app.UseAuthentication(); // to enable authentication (in this case AAD B2C)
app.UseMvcWithDefaultRoute(); // to add MVC middleware with default route
}
public void ConfigureServices(IServiceCollection services)
{
同样在Startup.cs中:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
_loggerFactory = loggerFactory;
app.UseStaticFiles(); // to allow serving up the JS, CSS, etc., files.
app.UseBotFramework(); // to add middleware to route webchat activity to the bot back-end code
app.UseSession(); // to enable session state
app.UseAuthentication(); // to enable authentication (in this case AAD B2C)
app.UseMvcWithDefaultRoute(); // to add MVC middleware with default route
}
public void ConfigureServices(IServiceCollection services)
{
//添加HttpContextAssessor、BotServices、BotConfigs和内存存储单例的标准代码为简洁起见
services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddAzureAdB2C(options => Configuration.Bind("Authentication:AzureAdB2C", options))
.AddCookie();
services.AddMvc();
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromHours(1);
options.CookieHttpOnly = true;
});
// Create and add conversation state.
var conversationState = new ConversationState(dataStore);
services.AddSingleton(conversationState);
var userState = new UserState(dataStore);
services.AddSingleton(userState);
services.AddBot<MyBot>(options =>
{
options.CredentialProvider = new SimpleCredentialProvider(endpointService.AppId, endpointService.AppPassword);
options.ChannelProvider = new ConfigurationChannelProvider(Configuration);
// Catches any errors that occur during a conversation turn and logs them to currently
// configured ILogger.
ILogger logger = _loggerFactory.CreateLogger<RucheBot>();
options.OnTurnError = async (context, exception) =>
{
logger.LogError($"Exception caught : {exception}");
await context.SendActivityAsync("Sorry, it looks like something went wrong.");
};
});
}
services.AddAuthentication(sharedOptions=>
{
sharedOptions.DefaultScheme=CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme=OpenIdConnectDefaults.AuthenticationScheme;
})
.AddAzureAdB2C(选项=>Configuration.Bind(“身份验证:AzureAdB2C”,选项))
.AddCookie();
services.AddMvc();
services.AddSession(选项=>
{
options.IdleTimeout=TimeSpan.FromHours(1);
options.CookieHttpOnly=true;
});
//创建并添加会话状态。
var conversationState=新的conversationState(数据存储);
服务。AddSingleton(会话状态);
var userState=新的userState(数据存储);
services.AddSingleton(userState);
services.AddBot(选项=>
{
options.CredentialProvider=新的SimpleCredentialProvider(endpointService.AppId,endpointService.AppPassword);
options.ChannelProvider=新配置ChannelProvider(配置);
//捕获会话回合期间发生的任何错误,并将其记录到当前会话
//配置ILogger。
ILogger logger=_loggerFactory.CreateLogger();
options.OnTurnError=异步(上下文,异常)=>
{
logger.LogError($“捕获异常:{Exception}”);
wait context.SendActivityAsync(“抱歉,看起来好像出了问题。”);
};
});
}
我的控制器的索引方法:
public async Task<ActionResult> Index()
{
string userId;
if (User.Identity.IsAuthenticated)
{
string aadb2cUserId = User.FindFirst("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier").Value;
Users.EnsureAccountExists(aadb2cUserId); // ensure account with given AAD identifier is know locally (by creating it if not)
userId = $"ia_{aadb2cUserId}";
}
else
{
userId = $"na_{Guid.NewGuid()}";
}
HttpClient client = new HttpClient();
string directLineUrl = $"https://directline.botframework.com/v3/directline/tokens/generate";
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, directLineUrl);
// TODO: put this in the config somewhere
var secret = "<the secret code from my bot's DirectLine channel config in the Azure portal>";
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", secret);
string jsonUser = JsonConvert.SerializeObject(new { User = new { Id = userId } });
request.Content = new StringContent(jsonUser, Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);
string token = string.Empty;
if (response.IsSuccessStatusCode)
{
var body = await response.Content.ReadAsStringAsync();
token = JsonConvert.DeserializeObject<DirectLineToken>(body).token;
}
var config = new ChatConfig()
{
Token = token,
UserId = userId,
};
return View(config);
}
公共异步任务索引()
{
字符串用户标识;
if(User.Identity.IsAuthenticated)
{
字符串aadb2cUserId=User.FindFirst(“http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier1.价值;
Users.EnsureAccountExists(aadb2cUserId);//确保在本地知道具有给定AAD标识符的帐户(如果不知道,则创建该帐户)
userId=$“ia_{aadb2cUserId}”;
}
其他的
{
userId=$“na_{Guid.NewGuid()}”;
}
HttpClient=新的HttpClient();
字符串directLineUrl=$”https://directline.botframework.com/v3/directline/tokens/generate";
HttpRequestMessage请求=新的HttpRequestMessage(HttpMethod.Post,directLineUrl);
//TODO:把它放在配置文件的某个地方
var secret=“*”).focus();
}
问题很长,但答案会短得多
所以我的第一个问题(关于StackOverflow)是:使用Bot后端
webchat客户端前端托管在同一个
Azure web app,是否需要使用DirectLine,或者是否存在
这样做更简单吗
是的,这是必要的。事实上,所有频道类型都使用Bot连接器与后端(您的Bot代码)通信,无法直接访问。原因有很多,其中一个是账单!我有点不同意Nicolas R的观点。当涉及到直接访问您的机器人时,您可能想看看以下内容:
还有一个选项,我认为这可能有助于您寻求的那种直接沟通。好的方面。但第一个是非官方的软件包,我不确定这是微软会鼓励的方向(但由于您是微软的支持团队成员,您必须了解更多这方面的信息)。我确实和你一样犹豫不决,我只是在与上级讨论后才发布了这个答案,以确保它没有问题。脱机directline软件包也是由一名Microsoft员工开发的。Kyle和Nicolas感谢您提供的信息性答案:-)我认为脱机directline选项允许与托管bot,同时通过标准通道(DL、Skype等)保持开放通信?浏览器托管选项是否也排除了bot框架,因此不允许通过其他通道(托管它的浏览器除外)与bot通信?@JohnChurch-我没有尝试脱机directline,所以我需要仔细研究一下才能回答您的问题。我想您将无法通过另一个通道连接到浏览器托管的机器人,尽管我也没有尝试过。@JohnChurch-我在本地机器上做了一些测试,下面是我的发现。这两个都是ese选项可能仍然可以公开标准通道可以访问的端点,但在身份验证方面,您可能会错过,而且听起来您希望您的bot是secur