ASP.NET Web API对接Bot Framework:serviceUrl配置与响应回传问题
问题:ASP.NET Web API对接Bot Builder的请求响应流程问题
我已基于ASP.NET C#搭建Bot Builder及配套Web API,相关代码如下:
一、现有代码实现
1. BotController代码
// This ASP Controller is created to handle a request. Dependency Injection will provide the Adapter and IBot // implementation at runtime. Multiple different IBot implementations running at different endpoints can be // achieved by specifying a more specific type for the bot constructor argument. [ApiController] public class BotController : ControllerBase { private readonly IBotFrameworkHttpAdapter _adapter; private readonly IBot _bot; public BotController(IBotFrameworkHttpAdapter adapter, IBot bot) { _adapter = adapter; _bot = bot; } [HttpPost, HttpGet] [Route("api/messages")] public async Task PostAsync() { await _adapter.ProcessAsync(Request, Response, _bot); } // Health check endpoint [HttpGet] [Route("health")] public IActionResult HealthCheck() { // Implement your availability check logic here bool isApiAvailable = CheckAPIAvailability(); if (isApiAvailable) { return Ok("API is available"); } else { return StatusCode(503, "API is unavailable"); } } private bool CheckAPIAvailability() { // Implement your logic to check API availability here // This could involve checking database connections, external dependencies, etc. // For simplicity, let's return true if the API is running return true; } }
2. 向/api/messages发送conversationUpdate请求的代码
var payload = new { type = "conversationUpdate", membersAdded = new[] { new { id = "bot1", name = "Bot 1" }, new { id = "user1", name = "User 1" }, }, membersRemoved = new object[0], channelId = "test", conversation = new { id = "conversation1" }, recipient = new { id = "bot1", name = "Bot 1" , role="bot"}, from = new { id = "user1", name = "User 1", role="user" }, locale = "en-US", id = "conversation1", //serviceUrl= }; string jsonPayload = JsonConvert.SerializeObject(payload, Formatting.Indented); HttpContent content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); var httpClient = new HttpClient(); var response = await httpClient.PostAsync($"http://localhost:5000/api/messages", content);
二、serviceUrl配置引发的报错
尝试将serviceUrl设置为http://localhost:5000/api/messages时,API返回500内部服务器错误:
{StatusCode: 500, ReasonPhrase: 'Internal Server Error', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers: { Date: Mon, 13 May 2024 11:04:51 GMT Server: Kestrel Content-Length: 0 }}
控制台日志显示异常:
fail: Microsoft.AspNetCore.Server.Kestrel[13] Connection id "0HN3J7I0HVPRG", Request id "0HN3J7I0HVPRG:00000002": An unhandled exception was thrown by the application. Microsoft.Bot.Schema.ErrorResponseException: Operation returned an invalid status code 'NotFound' at Microsoft.Bot.Connector.Conversations.ReplyToActivityWithHttpMessagesAsync(String conversationId, String activityId, Activity activity, Dictionary`2 customHeaders, CancellationToken cancellationToken) at Microsoft.Bot.Connector.ConversationsExtensions.ReplyToActivityAsync(IConversations operations, String conversationId, String activityId, Activity activity, CancellationToken cancellationToken) at Microsoft.Bot.Builder.CloudAdapterBase.SendActivitiesAsync(ITurnContext turnContext, Activity[] activities, CancellationToken cancellationToken) at Microsoft.Bot.Builder.TurnContext.<>c__DisplayClass31_0.<<SendActivitiesAsync>g__SendActivitiesThroughAdapter|1>d.MoveNext() --- End of stack trace from previous location --- at Microsoft.Bot.Builder.TurnContext.SendActivityAsync(IActivity activity, CancellationToken cancellationToken) at PteroBotWebAPI.AdapterWithErrorHandler.<>c__DisplayClass0_0.<<-ctor>b__0>d.MoveNext() in D:\Projects\ProMate\Source\PetroBot\PteroBotWebAPI\AdapterWithErrorHandler.cs:line 30 --- End of stack trace from previous location --- at Microsoft.Bot.Builder.BotAdapter.RunPipelineAsync(ITurnContext turnContext, BotCallbackHandler callback, CancellationToken cancellationToken) at Microsoft.Bot.Builder.CloudAdapterBase.ProcessActivityAsync(AuthenticateRequestResult authenticateRequestResult, Activity activity, BotCallbackHandler callback, CancellationToken cancellationToken) at Microsoft.Bot.Builder.CloudAdapterBase.ProcessActivityAsync(String authHeader, Activity activity, BotCallbackHandler callback, CancellationToken cancellationToken) at Microsoft.Bot.Builder.Integration.AspNet.Core.CloudAdapter.ProcessAsync(HttpRequest httpRequest, HttpResponse httpResponse, IBot bot, CancellationToken cancellationToken) at PteroBotWebAPI.Controllers.BotController.PostAsync() in D:\Projects\ProMate\Source\PetroBot\PteroBotWebAPI\Controllers\BotController.cs:line 43 at lambda_method6(Closure , Object ) at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker) at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
三、后续尝试及核心疑问
后续将serviceUrl设置为http://localhost:5000/api/response,并新增以下路由代码:
// Endpoint to handle any routes starting with api/response [HttpPost] [Route("api/response/{*path}")] public async Task HandleBotResponseAsync() { // what should be here?! }
此时Bot已将响应发送到该端点,但不清楚如何将Bot的响应回传给发起初始请求的用户。
请问如何解决上述报错,实现通过ASP.NET Web API向Bot发送请求并获取响应的完整流程?
内容的提问来源于stack exchange,提问作者Inevitable
相关产品推荐
相关产品推荐

