Twilio testing outbound call with ngrok - c#

I'm trying to test my outbound calling via Twilio, using my Twilio "test" credentials. It's an ASP.NET MVC 4 Web app that is hosting the endpoints for Twilio to hit. Since I'm running on localhost, they will be hit via ngrok (public endpoint that routes to your localhost).
I have configured a [toll-free] phone number in twilio where voice requests route to my ngrok url.
When I try to execute my test outbound call in my web app, I navigate to a test controller. It fires off some code that ends up executing this:
var call = _client.InitiateOutboundCall(
new CallOptions
{
From = "+1" + _fromPhone, // twilio toll-free phone number with base site/ngrok url configured, ie http://{ngrokcode}.ngrok.io
To = "+1" + phoneNumber, // phone that I want to "answer" and listen to the message
Url = url, // ngrok url that points to my localhost endpoint to play message, ie http://{ngrokcode}.ngrok.io/message/{forCustomerId}
IfMachine = "Continue"
});
In this call, the "_fromPhone" is the phone number that I have purchased/configured in twilio, the toll-free number, which is what routes to my ngrok url.
The "phoneNumber" is the phone that I want to call
The "url" is the endpoint that I want twilio to hit so it can "Say" the message to the recipient.
But, using these test credentials, the phone call never goes out. I accidentally ran this same thing, but using the production credentials, and the phone call DID go out (and started ringing on my cell phone), but when I answered, it was silent for about 15 seconds, then it finally said twilio encountered an error.
Looking at the logs for the accidental production call, it said it couldn't connect to my [ngrok] url.
So, two questions, why isn't the phone call getting executed when using my test credentials? And, if/when the phone call goes out, why isn't it executing/hitting my endpoint that contains my "Say" verbs?

Twilio developer evangelist here.
Test credentials are not used to make test calls, they are used to ensure that calls to the API are working as expected and will not generate calls themselves. The docs say:
When you authenticate with your test credentials, we will not charge your account, update the state of your account, or connect to real phone numbers.
As for when you made the call with your real credentials, there's more to look into here.
15 seconds is the timeout that Twilio will wait for when trying to connect to an endpoint. This suggests to me that ngrok was working and proxying the request but that your web application was hanging or taking too long to respond.
Can you hit your ngrok endpoints from a browser (or Postman or curl)? Is your web application logging anything that might help when you do access it? Does the ngrok dashboard (available at http://127.0.0.1:4040 when ngrok is running) give you any more insight.
Let me know and I'll update my answer with more suggestions.

Related

Why cant i use serveo instead of ngrok to tunnel connection to a mvc application hosted on EC2 server for receiving SMS on Twilio

I have a simple asp.net mvc web application which listens for a message and replied back with a standard response. It uses the Twilio API and in
Here is the code:
// Code sample for ASP.NET MVC on .NET Framework 4.6.1+
// In Package Manager, run:
// Install-Package Twilio.AspNet.Mvc -DependencyVersion HighestMinor
using Twilio.AspNet.Common;
using Twilio.AspNet.Mvc;
using Twilio.TwiML;
namespace WebApplication1.Controllers
{
public class SmsController : TwilioController
{
public TwiMLResult Index(SmsRequest incomingMessage)
{
var messagingResponse = new MessagingResponse();
messagingResponse.Message("The copy cat says: " +
incomingMessage.Body);
return TwiML(messagingResponse);
}
}
}
For the code to run, Twilio suggests me "While there are a lot of ways to do this, like deploying your application to Azure or AWS, you'll probably want a less laborious way to test your Twilio like ngrok to allow Twilio to Talk to Your ASP.NET Application"
I have used ngrok, which allows me to expose my local environment to the whole public internet which can then be accessed by URL provided by ngrok,
but the free version keeps changing the subdomain whenever I restart my ec2 server (thus restarting the ngrok tunnel).
What I would like to know is I tried an alternate called serveo which allowed me to chose a subdomain for free, but the URL generated it given an error (400) when I send a message to Twilio.
Is there a way around? I m new to the world of asp.net mcv web application and Twilio and would really appreciate some guidance.
I just need this code to keep running so that it can listen for SMS and respond back.
If not, How can I deploy it on AWS? Which would provide me with an URL to feed to the Twilio's console
The reason 'serveo' isn't working is because (I believe) you are using IIS Express which doesn't allow requests with host header's other than localhost.
'ngrok' has a way around that, as does our free VS Extension called Conveyor. Conveyor at the moment has tunnelling in beta, but it is stable and subdomains are fixed. You can download it from the Extensions menu in VS or marketplace. Here's a tutorial for Twilio https://conveyor.cloud/Help/Writing_webhooks_on_localhost_with_Visual_Studio_and_IIS_Express

Paypal Payments - 500 Error

I am trying to make a automatic payment in my system, and got it to work perfectly in sandbox mode. As soon, as I switch to live mode I am receiving a 500 error. I am not sure if maybe the URL's I've copied are maybe from a legacy site or something.
Here is my params:
My post back error looks like:
{"ClassName":"PayPal.Exception.HttpException","Message":"The remote server returned an error: (500) Internal Server Error.","Data":null,"InnerException":null,"HelpURL":null,"StackTraceString":" at PayPal.HttpConnection.Execute(String payLoad, HttpWebRequest httpRequest)\r\n at PayPal.APIService.MakeRequestUsing(IAPICallPreHandler apiCallHandler)\r\n at PayPal.BasePayPalService.Call(IAPICallPreHandler apiCallHandler)\r\n at PayPal.AdaptivePayments.AdaptivePaymentsService.Pay(PayRequest payRequest, String apiUserName)\r\n at Cashbackeroo.Payment.PayPal.PayPalPaymentService.Pay(PaymentRequest paymentRequest)","RemoteStackTraceString":null,"RemoteStackIndex":0,"ExceptionMethod":"8\nExecute\nPayPalCoreSDK, Version=1.7.1.0, Culture=neutral, PublicKeyToken=5b4afc1ccaef40fb\nPayPal.HttpConnection\nSystem.String Execute(System.String, System.Net.HttpWebRequest)","HResult":-2146233088,"Source":"PayPalCoreSDK","WatsonBuckets":null}
Adaptive Accounts
The Adaptive Accounts API allows you to create and manage PayPal accounts for PayPal users. To make an API call, see Adaptive Accounts API call headers and endpoints.
Adaptive Accounts endpoints
To make Adaptive Accounts API calls. include an AppID with your API credentials.
For sandbox testing, specify an AppID of APP-80W284485P519543T.
API
Formats
Endpoints
Adaptive Accounts
SOAP with XML,
NVP, or JSON
Live
https://svcs.paypal.com/AdaptiveAccounts/
Sandbox
https://svcs.sandbox.paypal.com/AdaptiveAccounts/
Try to open the Paypal URL dirrectly in your browser. Does it returns a 500 server error or 200 ok?
Usually when the Paypal servers are down, the response is 500 server error.

Facebook Graph API Requests from .NET (C#)

I have an application that generates a web request to Facebook Graph API to get a share count from an external page. I have been using this code for over a year without issue, and suddenly, the share count is not working when the request is made from .NET. However, if I make the request from a web browser, it works just fine. My code is as follows:
string fbLink = "https://graph.facebook.com/?id=" + externalLink + "&fields=og_object%7Bengagement%7D&access_token=<token_removed>";
WebClient client = new WebClient();
string fbString = client.DownloadString(fbLink);
This code still appears to be working fine, in that the request is made, and FB responds with no errors. In fact, it responds back with correct page id, and details. However, the share count is zero.
Here is where it gets a little bit weird. On my localhost development machine, the code works fine and returns the proper share count. However, if I run the code on my actual server (an AWS EC2 instance), the share count shows zero.
If I open Chrome and run the request from the browser, the share count displays as expected.
If I open Internet Explorer 11, and run the request from the browser, the counter shows zero. HOWEVER, if I log in to Facebook from IE11, and then run the request to FB Graph API, the response shows the correct page count.
This is very confusing to me, as it appears the reason the counter has stopped working, has to do with cookies, or maybe the browser being logged into FB. This should not be the case as I am using an APP token ID, and I wouldn't expect to need to be logged into FB in order to make a request to Graph API.
Does anybody have any ideas why my request/code in .NET worked just fine for a year and a half, and just stopped working? Or why the requests work fine on my localhost and not my live server?
After spending considerable time on this issue, I have fixed the issue. There is a FB authentication cookie that was being transmitted through a web browser query. The cookie name was "XS" and the value was a long string that is used as a sessionId for my specific login. If I created this cookie in my web request in C# code, I get the proper response with correct # of shares.
WebClient client = new WebClient();
client.Headers.Add("Cookie", "xs=<removed>;");
I have no idea why I have to do this, only on my EC2 server. Nowhere in FB's documentation does it say you have to spoof a valid logged in authentication string cookie in order to obtain correct Share Count results from a request to it's Graph API, but there you have it. A workaround at least.

How to inform users that api maintenance is in progress

I am using azure app service and DB for my C# ODATA API and DB as the backend of of my phone app.
I only have one app service that hosts 10s of endpoints. There are times when I need to publish new versions and I don't want any incoming requests during that time of deployment.
I don't mind that users are not able to finish their requests during the maintenance.
Is there anything in Azure or API that can let me:
1. turn off the api/app service manually?
2. Be able to inform the user that a maintenance is in progress?
This is my trial:
the only thing I can come up with is this. While users always use the "odata" in their url requests: https://myserverl/odata/Users
which is setup in the webapi.config like this:
config.MapODataServiceRoute("odata", "odata", builder.GetEdmModel());
I put the routePrefix (2nd odata) in a web.config.
When I need to turn off access, I change my web.config (which I can access manually even after the publish of code into Azure) to be like this:
<add key="odata" value="noaccess" />
and in my webapi.config:
string odata = ConfigurationManager.AppSettings["odata"].ToString();
config.MapODataServiceRoute("odata", odata, builder.GetEdmModel());
and then save the web.config which will reset the server and all incoming requests that has "odata" will result into error. I can always set it back later.
This method will stop the users from sending requests during maintenance but will not let them know what is going on.
I figured it out.
when I call the server from my client, I verify that the response is between 200 & 299 before parsing results or any other further processing.
So now, I check also for the possible response from the server that it could be either 403 (access is denied) or 503 (server is unavailable). That's where I can add code to notify the user.
In Azure, simply stopping the app service, will generate one of those 2 error codes.
Note: You must check for both: 403 & 503.

How do people test their [RequireHttps] attribute in a Web API?

Quick version
I'm sure many people have implemented a [RequireHttps] SSL check of some description (message handler, attribute, whatever) at some point in their Web API development. How do you guys and gals test that it works correctly both in terms of success and failure?
Not so quick version
I'm developing a REST service in a OWIN self-hosted ASP.NET Web API 2. I have already successfully secured the service with SSL and have implemented a custom [RequireHttps] attribute (derived from the answers to this SO question).
In the case when the client is calling the correct URL (e.g. https://my.server.com/api/values), if I add a breakpoint in the attribute definition, the debugger correctly breaks in the code (just calls the base and all is well, as expected).
The question is: how can I exercise the failure scenario for this attribute, such that the attribute code will return an error response without interfering with other server processes?
My Web API service listens on base address https://+:9443/. I've tried removing the s such that I connect to http://my.server.com:9443/api/values, but I get an error response status 502 (connection failed) after about a minute's timeout. Fair enough I suppose, but I was actually hoping to return a response ("SSL required") from my [RequireHttps] attribute.
Then I've tried creating the following StartOptions object:
var options = new StartOptions();
options.Urls.Add("https://+:9443/"); // listen on port 9443 with SSL
options.Urls.Add("http://+:80/"); // listen to standard HTTP port 80
and passing it to the WebApp like this:
WebApp.Start<Startup>(options)
Again, this didn't work when I connected to http://my.server.com:9443/api/values, but it worked when I connected to http://my.server.com:80/api/values.
However, this is not what I want to do. My production server hosts both secure (HTTPS) and insecure (HTTP on port 80) resources so my code will intercept legitimate calls to other processes that rely on port 80 and tell them to reconnect via https, which is wrong.
Can someone please advise on what options I have? Is there even a point to have [RequireHttps] given my situation, as it never seems to do anything useful?
What you are trying to do can't be done. Basically, you're trying to do the same thing as typing
http:443//www.google.com
Notice how that doesn't work either
The problem is that you're trying to access an http protocol over an SSL protocol port, and that is what's failing. Your code for the RequireHttps doesn't even get to execute because the request can't even be processed through IIS.

Categories