Twilio enhanced answering machine detection c# - c#

How exactly do I use the enhanced AMD through Twilio? I understand that it can only be done through the REST API (no TwiML) but I'm having a hard time seeing the connection between a standard call and the answering machine detection.
I've read through this page a few times, but I still don't understand. So here is the standard c# code for placing a call through the REST API:
TwilioClient.Init(AccountSid, AuthToken);
var to = new PhoneNumber("+14155551212");
var from = new PhoneNumber("+15017250604");
var call = CallResource.Create(to, from, url: new Uri("http://demo.twilio.com/docs/voice.xml"));
And here is my c# translated code from the aforementioned link:
using (var client = new HttpClient())
{
var byteArray = Encoding.ASCII.GetBytes($#"{AccountSid}:{AuthToken}");
var header = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
client.DefaultRequestHeaders.Authorization = header;
var requestContent = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("To", "+15017250604"),
new KeyValuePair<string, string>("From", "+15017250604"),
new KeyValuePair<string, string>("MachineDetection", "DetectMessageEnd"),
new KeyValuePair<string, string>("Url", Url.Action("PostTransfer"))
});
var response = client.PostAsync(_amdRequest, requestContent);
var responseContent = response.Result.Content;
}
So what am I missing? I'm sure it's something simple, but I'm not seeing how the enhanced AMD knows what call to listen to, and what the order of events here should be. And finally, how am I supposed to see the results?
EDIT:
So to be crystal clear, here is my code as it currently sits:
TwilioClient.Init(AccountSid, AuthToken);
var toPhone = new PhoneNumber(to);
var fromPhone = new PhoneNumber(from);
var call = CallResource.Create(toPhone, fromPhone, url: new Uri("http://demo.twilio.com/docs/voice.xml"));
using (var client = new HttpClient())
{
var byteArray = Encoding.ASCII.GetBytes($#"{AccountSid}:{AuthToken}");
var header = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
client.DefaultRequestHeaders.Authorization = header;
var requestContent = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("To", to),
new KeyValuePair<string, string>("From", from),
new KeyValuePair<string, string>("MachineDetection", "DetectMessageEnd"),
new KeyValuePair<string, string>("Url", Url.Action("PostTransfer"))
});
var response = client.PostAsync(_amdRequest, requestContent);
var responseContent = response.Result.Content;
}
And elsewhere in my code is a function called "PostTransfer" that gets the "AnsweredBy" parameter and does some stuff after the call is placed. Should this be working? Because it isn't. The call goes through and I can hear Twilio's example file play, but it never gets to the "PostTransfer" function.

Twilio developer evangelist here.
You look like you're making a call with detection successfully. You're making a call from your Twilio number to a users number.
You see the results of the answering machine detection when Twilio has decided on whether it is a machine or a human, at which point it makes a webhook request to your URL that you send as part of making the call.
When Twilio makes the webhook, it will include an extra parameter: AnsweredBy. When you set MachineDetection to DetectMessageEnd the values of AnsweredBy can be: machine_end_beep, machine_end_silence, machine_end_other, human, fax, and unknown. You can then read this value and decide what to do with the call at this point.
Does that help at all?

Can you try HttpWebRequest instead? here is an example how to do it,
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri);
request.Method = "POST";
request.Headers.Add("Authorization", string.Format("Bearer {0}",AccessToken));
request.ContentType = "application/json;charset=utf-8";
request.ContentLength = body.Length;
request.Accept = "application/json"
if (!string.IsNullOrWhiteSpace(body))
{
System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
byte[] bytes = encoding.GetBytes(body);
request.ContentLength = bytes.Length;
using (Stream requestStream = request.GetRequestStream())
{
// Send the data.
requestStream.Write(bytes, 0, bytes.Length);
}
}
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
if (callback != null)
{
var reader = new StreamReader(response.GetResponseStream());
callback(reader.ReadToEnd());
}
}

Related

How to replace obsolete WebClient POST+ZIP with HttpClient in .NET 6

Since WebClient is deprecated in .NET 6, what is the best solution to convert the following code using WebClient with an equivalent code using HttpClient?
byte[] data = Converter(...); // object to zipped json string
var client = new WebClient();
client.Headers.Add("Accept", "application/json");
client.Headers.Add("Content-Type", "application/json; charset=utf-8");
client.Headers.Add("Content-Encoding", "gzip");
client.Encoding = Encoding.UTF8;
byte[] response = webClient.UploadData("...url...", "POST", data);
string body = Encoding.UTF8.GetString(response);
This code works but only accepts simple json strings as input:
var request = new HttpRequestMessage()
{
RequestUri = new Uri("...url..."),
Version = HttpVersion.Version20,
Method = HttpMethod.Post,
Content = new StringContent("...json string...", Encoding.UTF8, "application/json");
};
var client = new HttpClient();
var response = client.SendAsync(request).Result;
I need a solution to post a zipped json string.
Thank you!
No surprise you managed to only send simple strings, because you used StringContent, which is meant for (drum roll!) string content.
So, what to do if you want to send binary data in form of a byte array? Well, the answer is simple: Don't use StringContent. Instead, use (drum roll intensifies) ByteArrayContent.
In order to add content type you could do this:
var content = new StringContent(payload, Encoding.UTF8);
content.Headers.ContentType = new MediaTypeWithQualityHeaderValue("application/json");
If you want to add headers like you did with webclient:
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
//OR
var header = new KeyValuePair<string, string>(key: "Accept", value: "application/json");
client.DefaultRequestHeaders.Add(header.Key, header.Value));

Bitstamp API POST request with parameters

please, help me with POST api request in C#.I dont know how to correctly send parameters „key“, „signature“ and „nonce“ in POST request. It constantly tells me "Missing key, signature and nonce parameters“.
HttpWebRequest webRequest =(HttpWebRequest)System.Net.WebRequest.Create("https://www.bitstamp.net/api/balance/");
if (webRequest != null)
{
webRequest.Method = HttpMethod.Post;
webRequest.ContentType = "application/json";
webRequest.UserAgent = "BitstampBot";
byte[] data = Convert.FromBase64String(apisecret);
string nonce = GetNonce().ToString();
var prehash = nonce + custID + apikey;
string signature = HashString(prehash, data);
body = Serialize(new
{
key=apikey,
signature=signature,
nonce=nonce
});
if (!string.IsNullOrEmpty(body))
{
var data1 = Encoding.UTF8.GetBytes(body);
webRequest.ContentLength = data1.Length;
using (var stream = webRequest.GetRequestStream()) stream.Write(data1, 0, data1.Length);
}
using (Stream s = webRequest.GetResponse().GetResponseStream())
{
using (StreamReader sr = new System.IO.StreamReader(s))
{
contentBody = await sr.ReadToEndAsync();
return contentBody;
}
}
}
The "Request parameters" as Bitstamp specifies in the docs is actually supposed to be sent with content type "application/x-www-form-urlencoded" instead of "application/json".
I would also use HttpClient to perform the post as that has a much more simple setup to perform Http requests
using (var client = new HttpClient())
{
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("key", apikey),
new KeyValuePair<string, string>("signature", signature),
new KeyValuePair<string, string>("nonce", nonce)
});
var result = await client.PostAsync("https://www.bitstamp.net/api/balance/", content);
string resultContent = await result.Content.ReadAsStringAsync();
}

Posting unicode data using HttpClient

I am trying to post some unicode data using Http request message. Somehow content encoding is causing some issue. I am not setting any encoding explicitly in my code.
For example, I am trying to send 'รัค' & on client side it is being received as 'รัà¸'.
Sample code
var cookieContainer = new CookieContainer();
using (var handler = new HttpClientHandler() { CookieContainer = cookieContainer, })
using(var httpClient = new HttpClient(handler)){
//set all cookies
foreach (var obj in configurationData["request_cookies"])
{
var cookie = ((JProperty)(obj));
cookieContainer.Add(new Uri(configurationData["request_cookie_base_url"].ToString()),
new Cookie(cookie.Name, HttpUtility.UrlEncode(cookie.Value.ToString())));
}
var request = new HttpRequestMessage();
request.Method = HttpMethod.Post;
request.RequestUri = new Uri(configurationData["form_url"].ToString());
//set all request headers
foreach (var obj in configurationData["request_headers"])
{
var cookie = ((JProperty) (obj));
request.Headers.Add(cookie.Name, cookie.Value.ToString());
}
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
//get request content data from configurationData as keyvalue pair
var contentValue = parsedCrmConfigurationData["form_data_template"]
.ToObject<Dictionary<string, string>>();
request.Content = new FormUrlEncodedContent(contentValue);
var response = httpClient.SendAsync(request).Result;
response.EnsureSuccessStatusCode();
}
Do I need to pass encoding specifically? if yes then how?
Please help me understand the issue.
you can use below code to encode your content
private static HttpContent getencodedContent(string jsonString)
{
var cont = new StringContent(jsonString, Encoding.UTF8, "application/json");
return cont;
}

Consuming compressed JSON using HttpClient and Jil

I'm a little confused about how to properly deserialize gziped Json payload from a HttpClient instance.
So far I'm doing the following, but it seems wrong. At least too complicated. Can't I feed a stream to Jil? Can't the HttpClient unzip the stream?
var client = new HttpClient();
var userEndPoint = new Uri(baseUri, "api/login");
var request = new HttpRequestMessage();
request.RequestUri = userEndPoint;
request.Method = HttpMethod.Get;
var response = _client.SendAsync(request).Result;
var userGzipByteArray = response.Content.ReadAsByteArrayAsync().Result;
var outStream = new MemoryStream();
using (var gzStream = new GZipStream(userGzipByteArray , CompressionMode.Decompress))
{
gzStream.CopyTo(outStream);
}
var userByteArray = outStream.ToArray();
var userJson = userByteArray .ConvertToString();
var user = JSON.Deserialize<User>(userJson , Jil.Options.ISO8601PrettyPrintIncludeInherited);
You can use the AutomaticDecompression flag for this. See Does .NET's HttpWebResponse uncompress automatically GZiped and Deflated responses?

HttpWebRequest works but HttpClient doesn't?

I'm trying to connect to a 3rd party WebApi and have created several unit tests to determine the functionality of said WebApi. My initial test used System.Net and did something like the following ...
var request = (HttpWebRequest)WebRequest.Create(commonUrl +
"api/controller/action?value=" + value);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = 0;
request.Method = "POST";
var response = (HttpWebResponse)request.GetResponse();
This returns an expected response and everything is ok, however I was later asked to use System.Net.Http instead so attempting to something like the following ...
HttpClient client = new HttpClient() { BaseAddress = new Uri(commonUrl) };
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue(
"application/x-www-form-urlencoded"));
var postData = new List<KeyValuePair<string, string>>()
{
new KeyValuePair<string, string>("value", value)
};
var response = client.PostAsync("api/controller/action",
new FormUrlEncodedContent(postData)).Result;
Unfortunately though, the response StatusCode comes back with System.Net.HttpStatusCode.NotFound Any idea why this is happening?
Thanks in advance

Categories