Bot Framework Direct Line Only Works in Debugger - c#

I have a BOT that uses QnA Maker and LUIS to answer FAQ and requests and I am trying to implement a Direct Line to another BOT. Basically whenever my BOT does not know the answer it sends the user message to the other BOT to check if it knows the answer and outputs the result. The Direct Line works fine when I step through the code with Debugger (the GET request responds with the message I sent and the reply from the BOT). However, when I just run the code normally the response only contains the message I sent and not the reply from the other BOT. I'm thinking that the GET request is just ending too fast for the BOT to respond when the code is run outside the debugger and I have no idea on how to fix or extend the request. Any ideas?
Here's the relevant code:
public class EdwardComponent
{
public static async Task<string> TalkToEdward(string userInput, string conversationID, string streamURL)
{
var DirectLineURL = ConfigurationManager.AppSettings["DirectLineURL"];
var BearerToken = ConfigurationManager.AppSettings["BearerToken"];
var DirectLineURLConversationID = ConfigurationManager.AppSettings["DirectLineURLConversationID"];
DirectLineURLConversationID = DirectLineURLConversationID.Replace("abc123", conversationID);
var postclient = new RestClient(DirectLineURLConversationID);
var postrequest = new RestRequest(Method.POST);
postrequest.AddHeader("Authorization", BearerToken);
postrequest.AddHeader("Content-Type", "application/json");
postrequest.RequestFormat = DataFormat.Json;
var idv = new { id = "user1" };
postrequest.AddBody(new { type = "message", from = idv, text = userInput });
var cancellationTokenSource = new CancellationTokenSource();
var postresponse = postclient.ExecuteAsPost(postrequest, "POST");
var getrequest = new RestRequest(Method.GET);
getrequest.AddHeader("Authorization", BearerToken);
var getresponse = await postclient.ExecuteGetTaskAsync(getrequest);
string content = getresponse.Content.ToString();
return content;
}
}
}
Here is the correct serialized response from debugging:
Activity 0 is the message sent, Activity 1 is the response from BOT
Here is the response when ran outside debugger:
Only Activity 0 returned

Fixed it by using a small delay and a loop that will continue making the GET request until the Bot responds.

Related

RestSharp is throwing a bad request on a GET call, but is missing response body

I am making a GET call to an external REST API. I was putting in a parameter incorrectly and was getting an HttpRequestException. When catching the exception the only details it returns are:
Request failed with status code BadRequest
When monitoring the traffic using Fiddler I can see the server was returning a json message in the body explaining why the call failed.
Is there anyway to access this message from RestSharp?
I am using .net 6 and RestSharp version 108.0.2
you must set ThrowOnAnyError from RestClientOptions to false :
private async Task<T?> SendRequest<T>()
{
string url = "your request url";
var options = new RestClientOptions(url)
{
ThrowOnAnyError = false,
MaxTimeout = 6000
};
var client = new RestClient(options);
var request = new RestRequest().AddHeader("Content-Type", "application/json");
request.Method = Method.Post;
var response = await client.ExecuteAsync<T>(request);
return response.Data;
}

Discord bot C# coding. Too few/too many parameters

I am trying to build a discord bot that fetches IMDb info for movies and series. I have the API and everything set up.
I have managed to get a console response when I use the command !SearchMovie Harry Potter, however it gives me the 'too few parameters' argument if i do !SearchMovie Jaws, or !SearchMovie Twilight. If i remove the (string content) from public async Task SearchMovie, then i get the 'too many parameters' error.
I would also like the bot to post the response body in the discord channel, however i get the 'Message content is too long. Must be equal to or less than 2000 (parameter content)' error. Please, if anyone has any ideas on how to fix this, please help.
This is my code:
[Command("SearchMovie")]
public async Task SearchMovie(string text, string content)
{
var client = new HttpClient();
var request = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri("https://imdb8.p.rapidapi.com/auto-complete?q=%3CREQUIRED%3E"),
Headers =
{
{ "X-RapidAPI-Key", "API-KEY" },
{ "X-RapidAPI-Host", "imdb8.p.rapidapi.com" },
},
};
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
await ReplyAsync(body);
}

Send POST request from webapi c# to onesignal url

I'm very new on this and I need some help. I'm trying to send a notification from my webapi to my app. To do this a need just send a post to the url("https://onesignal.com/api/v1/notifications") with some informations (Header from authorization and content-type). But when I send the post it takes a long and and I just get The operation timeout has been reached, no message errors that could help me. I tryed the code from onesignal's documentation from asp.net solutions but isn't worked for me. Anyone can help? Or just help how can I trace the error with my requisiton? After try the code from onesignal's documentation I decided use the following code(both codes had the same behavior):
using (var client = new HttpClient())
{
var url = new Uri("https://onesignal.com/api/v1/notifications");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", "Rest ID");
var obj = new
{
app_id = "APP ID",
contents = new { en = "English Message" },
included_segments = new string[] { "All" }
};
var json = JsonConvert.SerializeObject(obj);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
}
For some reason is taking a long time to send a notification and return some response for me. So I increase the timeout to wait the response and don't get a task cancelled. Hope help someone.

Getting an "Internal Server Error" when trying to post messages in Microsoft Bot Connector by Direct Line API

I've set up a simple bot - registered with Bot Connector - and I'm just trying to get the basic Direct Line API connection set up. In my separate application (C#), I've succeeded at initiating a conversation by using an HttpClient and retrieving the conversationId (by deserializing the response).
However, I then attempt to post a message to the thread, and I'm getting a "Internal Server Error", error code 500. The only message attached is "An error has occurred.".
using(var client = new HttpClient())
{
client.BaseAddress = new Uri("https://directline.botframework.com/");
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Add("Authorization", $"BotConnector {token}");
client.DefaultRequestheaders.Add("Type", "Message");
var post_content = new StringContent("Adding to the convo", Encoding.UTF8, "application/json");
HttpResponseMessage response = new client.PostAsync($"api/conversations/{convo_id}/messages", post_content).Result;
log(response.ReadAsStringAsync().Result);
}
log is a simple method to output to the console, while convo_id is the conversationId taken from the initial call to the site.
The line of code:
var post_content = new StringContent("Adding to the convo", Encoding.UTF8, "application/json");
is the source of the problems.
Look at the format of the message expected:
http://docs.botframework.com/sdkreference/restapi-directline/#!/Conversations/Conversations_PostMessage
It's expecting a JSON object with a bunch of fields. I was able to repo your problem and changed the content of the message and the error goes away.
Message message = new Message(conversationId: convId, text: "Happy days");
string output = JsonConvert.SerializeObject(message);
var post_content = new StringContent(output,Encoding.UTF8,"application/json");
Using the Microsoft.Bot.Connector.DirectLine NuGet package, I'm having some success with the DirectLine API.
var uri = new Uri("https://directline.botframework.com");
DirectLineClientCredentials creds = new DirectLineClientCredentials(secret);
DirectLineClient client = new DirectLineClient(uri, creds);
Conversations convs = new Conversations(client);
string waterMark;
var conv = convs.NewConversation();
var set = convs.GetMessages(conv.ConversationId);
waterMark = set.Watermark;
Message message = new Message(conversationId: conv.ConversationId, text: "your text");
Console.WriteLine(message.Text);
convs.PostMessage(conv.ConversationId, message);
set = convs.GetMessages(conv.ConversationId, waterMark);
PrintResponse(set);
waterMark = set.Watermark;
with the PrintResponse defined as:
private static void PrintResponse(MessageSet set)
{
var q = from x in set.Messages
where x.FromProperty == "<YOUR BOTS APP ID HERE>"
select x.Text;
foreach (var str in q.ToList())
{
Console.WriteLine(">> " +str);
}
}

Get application to wait until Variables are updated

I am working with OAuth at the moment. The problem with the current code is it doesn't wait until the user allows the application on the site and gets the proper key and secret. I was using a threading type wait but, sometimes it not long enough...some users are slower then others. I have attached a snippet of my code. What I would like to know is where to insert a while statement, or should I even use that ?
public OAuthToken GetRequestToken(Uri baseUri, string consumerKey, string consumerSecret)
{
var uri = new Uri(baseUri, "oauth/request_token");
uri = SignRequest(uri, consumerKey, consumerSecret);
var request = (HttpWebRequest) WebRequest.Create(uri);
request.Method = WebRequestMethods.Http.Get;
var response = request.GetResponse();
var queryString = new StreamReader(response.GetResponseStream()).ReadToEnd();
var parts = queryString.Split('&');
var token = parts[1].Substring(parts[1].IndexOf('=') + 1);
var secret = parts[0].Substring(parts[0].IndexOf('=') + 1);
return new OAuthToken(token, secret);
}
You should switch over to the newer System.Net.Http and System.Net.Http.WebRequest libraries that come with .NET now. These all use the new async programming stuff that is available with .NET 4.5.
You can call a request (returning you a task object that you can wait on) and automatically pause the thread for the response. The UI won't respond, as normal. That is probably the easiest thing to do if you don't understand how the new async and await keywords work. For more information on them, see http://msdn.microsoft.com/en-us/library/hh191443.aspx
Here is your code doing things with the new libraries:
using System.Net.Http;
public OAuthToken GetRequestToken(Uri baseUri, string consumerKey, string consumerSecret)
{
var uri = new Uri(baseUri, "oauth/request_token");
uri = SignRequest(uri, consumerKey, consumerSecret);
var message = new HttpRequestMessage(new HttpMethod("GET"), uri);
var handler = new WebRequestHandler();
var client = new HttpClient(handler);
// Use the http client to send the request to the server.
Task<HttpResponseMessage> responseTask = client.SendAsync(message);
// The responseTask object is like a wrapper for the other task thread.
// We can tell this task object that we want to pause our current thread
// and wait for the client.SendAsync call to finish.
responseTask.Wait();
// - Once that thread finishes, and the code continues on, we need to
// tell it to read out the response data from the backing objects.
// - The responseTask.Result property represents the object the async task
// was wrapping, we want to pull it out, then use it and get the content
// (body of the response) back.
// - Getting the response actually creates another async task (the
// .ReadAsStringAsync() call) but by accessing the .Result
// property, it is as if we called .ReadAsStringAsync().Wait(); Except that
// by using Result directly, we not only call Wait() but we get the resulting,
// wrapped object back. Hope that didn't confuse you much :)
var queryString = responseTask.Result.Content.ReadAsStringAsync().Result;
// And all your other normal code continues.
var parts = queryString.Split('&');
var token = parts[1].Substring(parts[1].IndexOf('=') + 1);
var secret = parts[0].Substring(parts[0].IndexOf('=') + 1);
return new OAuthToken(token, secret);
}
Why Not use a modal pop up and then call the authentication class on the submit button

Categories

Resources