问题
My bot keeps failing on the following line of code with the error in Skype, WebChat, and FB chat. I've tried entering the MS App ID and password via the app settings and the web.config. This works fine in the emulator without any errors. When I ran remote debugging I found that this fails on Webchat, Skype, and FB messenger at this line of code:
await connector.Conversations.ReplyToActivityAsync(reply1);
My bot is integrated with SmartThings so the smart accessories are turning on and off as expected but the response back that should be returned in the chat seems to be failing. I've tried creating a new bot service app but it fails as well.
Update including all code:
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Http;
using Microsoft.Bot.Connector;
using System.Net.Http.Headers;
using System.Threading;
using Microsoft.IdentityModel.Protocols;
using System.Configuration;
namespace FirstBotApp
{
[BotAuthentication]
public class Switches
{
public string name { get; set; }
public string value { get; set; }
}
public class MessagesController : ApiController
{
static HttpClient client = new HttpClient();
static HttpResponseMessage responsemain = null;
static int j = 0;
static void ShowSwitches(Switches[] switches)
{
for (int i = switches.Length - 1; i >= 0; i--)
{
Console.WriteLine($"Name: {switches[i].name}\tPrice: {switches[i].value}\t");
}
return;
}
static async Task<Switches[]> GetSwitchesAsync(string path)
{
Switches[] switches = null;
responsemain = await client.GetAsync(path);
//Console.WriteLine(client.GetAsync(path));
//Console.WriteLine(response);
if (responsemain.IsSuccessStatusCode)
{
//Console.WriteLine($"Successful response: {response.StatusCode}");
var response1 = await client.GetStringAsync("");
Console.WriteLine($"{response1}");
switches = await responsemain.Content.ReadAsAsync<Switches[]>();
//JObject j = JObject.Parse(response1);
}
else Console.WriteLine($"Error in response: {responsemain.StatusCode}");
return switches;
}
static async Task<Switches> UpdateSwitchesAsync(Switches switches)
{
Console.WriteLine("Turning off the light");
HttpResponseMessage response = await client.PutAsJsonAsync($"switches/off?room=LivingRoom", switches);
response.EnsureSuccessStatusCode();
Console.WriteLine($"The response from the server was: {response.StatusCode}");
// Deserialize the updated switches from the response body.
switches = await response.Content.ReadAsAsync<Switches>();
Thread.Sleep(10000);
Console.WriteLine($"Turning on the light");
response = await client.PutAsJsonAsync($"switches/on?room=LivingRoom", switches);
Console.WriteLine($"The response from the server was: {response.StatusCode}");
Thread.Sleep(10000);
return switches;
}
static async Task<HttpStatusCode> DeleteSwitchesAsync(string id)
{
HttpResponseMessage response = await client.DeleteAsync($"api/switchess/{id}");
return response.StatusCode;
}
/// <summary>
/// POST: api/Messages
/// Receive a message from a user and reply to it
/// </summary>
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
Switches[] switches = null;
ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
//string appdId = AppSettings.Settings["MicrosoftAppId"];
//string appPassword = ConfigurationManager.AppSettings["MicrosoftAppPassword"];
if (j == 0)
{
//client.Timeout = TimeSpan.FromSeconds(4);
//Declaration of client and Switches variable
string accessToken = "xxxxx";
client.BaseAddress = new Uri("xxxxx");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
j++;
//client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue ("Authorization", "Bearer " + accessToken);
}
if (activity.Type == ActivityTypes.Message)
{
//, appdId, appPassword);
//Switches switches = new Switches;
Activity reply1;// = activity.CreateReply($"breakpoint1");
//await connector.Conversations.ReplyToActivityAsync(reply1);
switch (activity.Text.ToLower())
{
case"turn on livingroom":
try
{
Console.WriteLine("Turning on the light");
responsemain = await client.PutAsJsonAsync($"switches/on?room=LivingRoom", switches);
responsemain.EnsureSuccessStatusCode();
//Console.WriteLine($"The response from the server was: {responsemain.StatusCode}");
// Deserialize the updated product from the response body.
switches = await responsemain.Content.ReadAsAsync<Switches[]>();
reply1 = activity.CreateReply($"Successfully turned on LivingRoom Light");
await connector.Conversations.ReplyToActivityAsync(reply1);
}
catch
{
reply1 = activity.CreateReply($"Error");
await connector.Conversations.ReplyToActivityAsync(reply1);
}
break;
case "turn off livingroom":
try
{
Console.WriteLine("Turning off the light");
responsemain = await client.PutAsJsonAsync($"switches/off?room=LivingRoom", switches);
responsemain.EnsureSuccessStatusCode();
Console.WriteLine($"The response from the server was: {responsemain.StatusCode}");
// Deserialize the updated product from the response body.
switches = await responsemain.Content.ReadAsAsync<Switches[]>();
reply1 = activity.CreateReply($"Successfully turned off LivingRoom Light");
await connector.Conversations.ReplyToActivityAsync(reply1);
}
catch
{
reply1 = activity.CreateReply($"Error");
await connector.Conversations.ReplyToActivityAsync(reply1);
}
break;
default: //"What lights are on?":
try
{
switches = await GetSwitchesAsync("");
//Console.WriteLine($"About to show the product");
ShowSwitches(switches);
//await connector.Conversations.ReplyToActivityAsync(switches[].ToString);
for (int i = switches.Length - 1; i >= 0; i--)
{
reply1 = activity.CreateReply($"Room: ");//{switches[i].name}\tStatus: {switches[i].value}\t");
responsemain.EnsureSuccessStatusCode();
await connector.Conversations.ReplyToActivityAsync(reply1);
}
break;
}
catch
{
}
break;
}
// calculate something for us to return
//int length = (activity.Text ?? string.Empty).Length;
// return our reply to the user
//Activity reply = activity.CreateReply($"You sent {activity.Text} which was {length} characters");
//await connector.Conversations.ReplyToActivityAsync(reply);
}
else
{
HandleSystemMessage(activity);
}
// var response = Request.CreateResponse(HttpStatusCode.OK);
return responsemain;
}
static Activity HandleSystemMessage(Activity message)
{
if (message.Type == ActivityTypes.DeleteUserData)
{
// Implement user deletion here
// If we handle user deletion, return a real message
}
else if (message.Type == ActivityTypes.ConversationUpdate)
{
// Handle conversation state changes, like members being added and removed
// Use Activity.MembersAdded and Activity.MembersRemoved and Activity.Action for info
// Not available in all channels
}
else if (message.Type == ActivityTypes.ContactRelationUpdate)
{
// Handle add/remove from contact lists
// Activity.From + Activity.Action represent what happened
}
else if (message.Type == ActivityTypes.Typing)
{
// Handle knowing tha the user is typing
}
else if (message.Type == ActivityTypes.Ping)
{
}
return null;
}``
//client.dispose();
}
}
回答1:
I found the error after some additional troubleshooting with remote debugging. Based on @JimLewallen's response I looked closer at the "Credentials" portion of the connector object. The OAuthScope for version 3.0 of the Botframework (connector-> Credentials->OAuthScope in the locals of the remote debugger) was pointing to api.botframework.com/.default when it should have been pointing at "graph.microsoft.com/.default". When I created a new bot service application in Visual Studios using the bot template the OAuthScope showed the correct endpoint.
Incorrect Value: OAuthScope "api.botframework.com/.default"
Correct Value: Image from the Remote Debugger showing the correct OAuthScope
来源:https://stackoverflow.com/questions/42991355/authorization-for-microsoft-app-id-xxx-failed-with-status-code-forbidden-and-rea