Completing Oauth without the use of threading - c#

I am not exactly sure how to explain this so I'll give it my best shot.
Basically I have an application that connects to DropBox. One of the situations I have run into is with the registering process. At the moment during the registration process it connects to DropBox using the default browser, which it then requires the user to login and click allow app to use the service. In return you get a token which the app can use to connect to the service with. The problem I am having is getting the application to wait until the above process is completed. The only way I have figured out to get it to wait is to use system.threading(int). however if the person takes longer then the timeout then it fails to register properly.
I am hoping someone may be able to point me in the right direction and get it to wait without the threading function. I was hoping I could use a if loop or something but i have no idea how to do that properly.
here is the actual Oauth code:
private static OAuthToken GetAccessToken()
{
string consumerKey = "*****";
string consumerSecret = "****";
var oauth = new OAuth();
var requestToken = oauth.GetRequestToken(new Uri(DropboxRestApi.BaseUri), consumerKey, consumerSecret);
var authorizeUri = oauth.GetAuthorizeUri(new Uri(DropboxRestApi.AuthorizeBaseUri), requestToken);
Process.Start(authorizeUri.AbsoluteUri);
return oauth.GetAccessToken(new Uri(DropboxRestApi.BaseUri), consumerKey, consumerSecret, requestToken);
}
and here is the complete oauth function that is called when the registration button is clicked:
var accesstoken = GetAccessToken();

You need to make the Async (asynchronous) version of their GetAccessToken call. One that will call some function of yours when it is complete.
You could also loop until the information is ready, e.g.
while (dataIsNotReady()) {
Thread.Sleep(1000); // sleep for a bit. this is bad, locks up entire thread maybe even application while it sleeps. Make it shorter for less impact.
// TODO add a "timeout", i.e. only try this for X amount of time before breaking out
}
// Now we data is ready let's go
Update:
Perhaps you are better off using a library that can do it async for you e.g. this Dropbox C# library: https://github.com/dkarzon/DropNet

Related

How to leave a voicemail using Twilio AMD?

Given client code that makes an outgoing call like this:
var accountSid = configuration["accountSid"];
var authToken = configuration["authToken"];
TwilioClient.Init(accountSid, authToken);
var call = CallResource.Create(
machineDetection: "DetectMessageEnd",
asyncAmd: "true",
asyncAmdStatusCallback: new Uri("[URL]/callback/index"),
asyncAmdStatusCallbackMethod: HttpMethod.Post,
twiml: new Twilio.Types.Twiml("<Response><Say>Ahoy there!</Say></Response>"),
from: new Twilio.Types.PhoneNumber(configuration["fromPhoneNumber"]),
to: new Twilio.Types.PhoneNumber(configuration["toPhoneNumber"])
);
aka, asyncAmd is enabled and callback URL is specified, with my webhook controller action that looks like this:
[ApiController]
[Route("callback")]
public class CallbackController : TwilioController
{
[HttpPost]
[Route("index")]
public IActionResult Index()
{
var response = new VoiceResponse();
if (Request.Form.TryGetValue("AnsweredBy", out var answeredBy))
{
if (answeredBy != "human")
{
response.Say("this is the voice message");
}
}
return Content(response.ToString(), "text/xml");
}
}
why is it there is no voicemail being left?
Note: I am including the Twiml I want to say in CallResource.Create b/c I don't want a callback to get the message contents in case of a human answering.
I only need the callback performed for the results of AMD detection, and then to leave a voice message.
Do I do that with response.Say?
Thanks!
Twilio developer evangelist here.
Twilio answering machine detection can happen in synchronous or asynchronous mode. From this blog post:
With Async AMD on Twilio, AMD is done asynchronously (hence the name). When the call is answered, a call url is executed immediately, so if a person answers the call rather than voicemail, they can begin interacting with your application without any silence. Then “asynchronously”, or “in parallel”, AMD processes the call audio and determines what answered the call. When AMD processing is complete, the result (the AnsweredBy parameter) is sent to a second URL, the asyncAmdStatusCallback.
One key difference between standard AMD and async AMD is how you modify the call once receiving the AMD result. With standard AMD, you have one URL and the result is sent to this URL just like any other outbound-api call. When your URL receives the result, you can check the AnsweredBy parameter and update the call accordingly with TwiML. With Async AMD, your call is already executing TwiML and you instead need to update the call via API.
In your case you are using async AMD, but you are not updating the call via the API.
You have two options. You can choose to use synchronous AMD and you can then respond to the result using TwiML like you are doing so far.
Alternatively, you can continue to use async AMD, but instead of responding to the webhook with TwiML, use the REST API to update the call with the new TwiML or with a new webhook URL.
One thing I would look out for too. Your initial TwiML is very short, your example code shows that it sends <Response><Say>Ahoy there!</Say></Response>. It is entirely possible that this TwiML will be completed before an answering machine is detected and since it is the only TwiML for the call, the call would then hang up. You may want to consider using a longer message or pausing so that you can get the result of the AMD.
Figured I'd follow up here. Thanks #philnash for the help. You were indeed right
I was returning Twiml from the asyncAMD webhook instead of updating the call.
my very short Twiml in the initiating call was not long enough
I got through the first part and things were still failing even with Twiml that was longer:
<Response><Say>Hello there. This is a longer message that will be about as long as the real message asking you to confirm or cancel your appointment. Hopefully it's long enough!</Say></Response>
BUT, that still was not long enough! By the time the asyncAMD callback was invoked, and I tried to use CallResource.Update, the call was already ended.
I ended up dumping about 2,000 characters of lorem ipsum into the outgoing call Twiml and the asyncAMD callback using CallResource.Update worked perfectly.

Bot Framework: How to exit Conversation?

so right now I'm using Microsoft.Bot.Builder.Dialogs.Conversation.SendAsync and Microsoft.Bot.Builder.Dialogs.Conversation.ResumeAsync to implement a way to pause and resume conversation but it seems impossible to 'exit' or go back to the previous state. It's stuck in the conversation dialog.
Do I just implement a 'Cancel' command? If so, what data do I need to clear so that it will be back to the original state?
public static readonly IDialog<string> dialog = Chain
.PostToChain()
.Switch(
new Case<Message, IDialog<string>>((msg) =>
{
var regex = new Regex("login", RegexOptions.IgnoreCase);
return regex.IsMatch(msg.Text);
}, (ctx, msg) =>
{
return Chain.ContinueWith(new ChatDialog(msg),
async (context, res) =>
{
var token = await res;
//var valid = await Helpers.ValidateAccessToken(token);
//var name = await Helpers.GetProfileName(token);
var name = "User";
context.UserData.SetValue("name", name);
return Chain.Return($"You are logged in as: {name}");
});
})
).Unwrap().PostToUser();
so if I send a 'login' it will go and start a new ChatDialog conversation but it seems to get stuck in this state. Even if I try to send another command, it will keep asking for login. Do I implement another Case class to handle a 'Cancel' command? Or should it automatically cancel the conversation when the user sends the same 'login' command more than once? Seems kinda clunky to have to send a 'cancel' command separately.
I think you are missing the DefaultCase. Check this. It shows the implementation of the DefaultCase for the Facebook Auth Sample. BTW, in that sample they also have a Logout command.
I would consider how your users will interpret the end of the conversation, and think about those scenarios and how people end conversations.
You can add code to handle resetting or the end of a conversation based on specific keywords, and by using the GlobalMessageHandler pattern.
https://github.com/Microsoft/BotBuilder-Samples/tree/master/CSharp/core-GlobalMessageHandlers
Also, expect users to just "hang up" / close the window once they are done.
A good set of metrics can help collect information on how people are using the bot for the owners to improve it.
i.e: Did interaction X lead on to expected interaction Y, or what was the last interaction we saw for this conversation... etc.

HttpWebRequest possibly slowing website

Using Visual studio 2012, C#.net 4.5 , SQL Server 2008, Feefo, Nopcommerce
Hey guys I have Recently implemented a new review service into a current site we have.
When the change went live the first day all worked fine.
Since then though the sending of sales to Feefo hasnt been working, There are no logs either of anything going wrong.
In the OrderProcessingService.cs in Nop Commerce's Service, i call a HttpWebrequest when an order has been confirmed as completed. Here is the code.
var email = HttpUtility.UrlEncode(order.Customer.Email.ToString());
var name = HttpUtility.UrlEncode(order.Customer.GetFullName().ToString());
var description = HttpUtility.UrlEncode(productVariant.ProductVariant.Product.MetaDescription != null ? productVariant.ProductVariant.Product.MetaDescription.ToString() : "product");
var orderRef = HttpUtility.UrlEncode(order.Id.ToString());
var productLink = HttpUtility.UrlEncode(string.Format("myurl/p/{0}/{1}", productVariant.ProductVariant.ProductId, productVariant.ProductVariant.Name.Replace(" ", "-")));
string itemRef = "";
try
{
itemRef = HttpUtility.UrlEncode(productVariant.ProductVariant.ProductId.ToString());
}
catch
{
itemRef = "0";
}
var url = string.Format("feefo Url",
login, password,email,name,description,orderRef,productLink,itemRef);
var request = (HttpWebRequest)WebRequest.Create(url);
request.KeepAlive = false;
request.Timeout = 5000;
request.Proxy = null;
using (var response = (HttpWebResponse)request.GetResponse())
{
if (response.StatusDescription == "OK")
{
var stream = response.GetResponseStream();
if(stream != null)
{
using (var reader = new StreamReader(stream))
{
var content = reader.ReadToEnd();
}
}
}
}
So as you can see its a simple webrequest that is processed on an order, and all product variants are sent to feefo.
Now:
this hasnt been happening all week since the 15th (day of the
implementation)
the site has been grinding to a halt recently.
The stream and reader in the the var content is there for debugging.
Im wondering does the code redflag anything to you that could relate to the process of website?
Also note i have run some SQL statements to see if there is any deadlocks or large escalations, so far seems fine, Logs have also been fine just the usual logging of Bots.
Any help would be much appreciated!
EDIT: also note that this code is in a method that is called and wrapped in A try catch
UPDATE: well forget about the "not sending", thats because i was just told my code was rolled back last week
A call to another web site while processing the order can degrade performance, as you are calling to a site that you do not control. You don't know how much time it is going to take. Furthermore, the GetResponse method can throw an exception, if you don't log anything in your outer try/catch block then you won't be able to know what's happening.
The best way to perform such a task is to implement something like the "Send Emails" scheduled task, and send data when you can afford to wait for the remote service. It is easy if you try. It is more resilient and easier to maintain if you upgrade the nopCommerce code base.
This is how I do similar things:
Avoid modifying the OrderProcessingService: Create a custom service or plugin that consumes the OrderPlacedEvent or the OrderPaidEvent (just implement the IConsumer<OrderPaidEvent> or IConsumer<OrderPlacedEvent> interface).
Do not call to a third party service directly while processing the request if you don't need the response at that moment. It will only delay your process. At the service created in step 1, store data and send it to Feefo later. You can store data to database or use an static collection if you don't mind losing pending data when restarting the site (that could be ok for statistical data for instance).
Best way to implement point #2 is to add a new scheduled task implementing ITask (remember to add a record to the ScheduleTask table). Just recover the stored data do your processing.
Add some logging. It is easy, just get an ILogger instance and call Insert.
As far as I can see, you are making a blocking synchronous call to other websites, which will definitely slow down your site in between the request-response process. What Marco has suggested is valid, try to do it in an ITask. Or you can use an asynchronous web request to potentially remove the block, if you need things done immediately instead of scheduled. :)

Windows Phone 8 HttpClient Get method returns strange results

I am developing a Windows Phone 8 app that sends some data to a server which executes it and returns a result. The server can be queried at any time to GET the status of the current execution which could be initializing,running or finished. The output is available only when the execution is in the finished state. The user has the option to check the current status of the execution, by pressing an 'update' button
XAML
<Button Background="{StaticResource PhoneAccentBrush}"
Click="UpdateRunInfo" > Update info</Button>
This is the method
private async void UpdateRunInfo(object sender, RoutedEventArgs e)
{
ExecutionItem clicked = ((sender as Button).DataContext as ExecutionItem);
HttpClientHandler handler = new HttpClientHandler();
handler.Credentials = new NetworkCredential("username", "password");
HttpClient client = new HttpClient(handler);
string Url = "http://somefakeurl.com/server/run/id/status";
string _status = await client.GetStringAsync(Url);
clicked.status = _status;
}
So the problem is that this method work properly only the first time it is called. After that, GetStringAsync() returns the same results as the first call regardless of the actual status of the server.
I have tried this method in a separate Windows Phone project, the result is the same.
To be sure that the server is running correctly I tried again the same C# code this time on a desktop application and it works perfectly fine.
My theory is that because I send the same request multiple times the WP OS is caching the last result and it gives it back to me instead of actually making the GET request to the server.
Why does the HttpClient return a cached status instead of actually getting the status from the server ?
As suggested by the people commenting it was a caching problem.
The suggestion from user L.B. to set client.DefaultRequestHeaders.IfModifiedSince resolved the problem
As already commented, it's a caching problem (simply speaking: your request is cached, so you get the cached response).
Alexei's answer is probably the most used, especially using the current time as query parameter.
Note: guys, please answer, not comment, otherwise the question will remain in "unanswered" status.

Detecting async client disconnect in ASP.NET MVC

Given an async controller:
public class MyController : AsyncController
{
[NoAsyncTimeout]
public void MyActionAsync() { ... }
public void MyActionCompleted() { ... }
}
Assume MyActionAsync kicks off a process that takes several minutes. If the user now goes to the MyAction action, the browser will wait with the connection open. If the user closes his browser, the connection is closed. Is it possible to detect when that happens on the server (preferably inside the controller)? If so, how? I've tried overriding OnException but that never fires in this scenario.
Note: I do appreciate the helpful answers below, but the key aspect of this question is that I'm using an AsyncController. This means that the HTTP requests are still open (they are long-lived like COMET or BOSH) which means it's a live socket connection. Why can't the server be notified when this live connection is terminated (i.e. "connection reset by peer", the TCP RST packet)?
I realise this question is old, but it turned up frequently in my search for the same answer.
The details below only apply to .Net 4.5
HttpContext.Response.ClientDisconnectedToken is what you want. That will give you a CancellationToken you can pass to your async/await calls.
public async Task<ActionResult> Index()
{
//The Connected Client 'manages' this token.
//HttpContext.Response.ClientDisconnectedToken.IsCancellationRequested will be set to true if the client disconnects
try
{
using (var client = new System.Net.Http.HttpClient())
{
var url = "http://google.com";
var html = await client.GetAsync(url, HttpContext.Response.ClientDisconnectedToken);
}
}
catch (TaskCanceledException e)
{
//The Client has gone
//you can handle this and the request will keep on being processed, but no one is there to see the resonse
}
return View();
}
You can test the snippet above by putting a breakpoint at the start of the function then closing your browser window.
And another snippet, not directly related to your question but useful all the same...
You can also put a hard limit on the amount of time an action can execute for by using the AsyncTimeout attribute. To use this use add an additional parameter of type CancellationToken. This token will allow ASP.Net to time-out the request if execution takes too long.
[AsyncTimeout(500)] //500ms
public async Task<ActionResult> Index(CancellationToken cancel)
{
//ASP.Net manages the cancel token.
//cancel.IsCancellationRequested will be set to true after 500ms
try
{
using (var client = new System.Net.Http.HttpClient())
{
var url = "http://google.com";
var html = await client.GetAsync(url, cancel);
}
}
catch (TaskCanceledException e)
{
//ASP.Net has killed the request
//Yellow Screen Of Death with System.TimeoutException
//the return View() below wont render
}
return View();
}
You can test this one by putting a breakpoint at the start of the function (thus making the request take more than 500ms when the breakpoint is hit) then letting it run out.
Does not Response.IsClientConnected work fairly well for this? I have just now tried out to in my case cancel large file uploads. By that I mean if a client abort their (in my case Ajax) requests I can see that in my Action. I am not saying it is 100% accurate but my small scale testing shows that the client browser aborts the request, and that the Action gets the correct response from IsClientConnected.
It's just as #Darin says. HTTP is a stateless protocol which means that there are no way (by using HTTP) to detect if the client is still there or not. HTTP 1.0 closes the socket after each request, while HTTP/1.1 can keep it open for a while (a keep alive timeout can be set as a header). That a HTTP/1.1 client closes the socket (or the server for that matter) doesn't mean that the client has gone away, just that the socket hasn't been used for a while.
There are something called COMET servers which are used to let client/server continue to "chat" over HTTP. Search for comet here at SO or on the net, there are several implementations available.
For obvious reasons the server cannot be notified that the client has closed his browser. Or that he went to the toilet :-) What you could do is have the client continuously poll the server with AJAX requests at regular interval (window.setInterval) and if the server detects that it is no longer polled it means the client is no longer there.

Categories

Resources