How to initiate an outgoing call with message? - c#

I'm trying to notify the caller with an automated message. Here is my code below.
string
string AccountSid = "***************";
string AuthToken = "**************";
var doc = new XDocument();
var call = new XElement("call");
call.Add(new XElement("Say", Message));
doc.Add(call);
var twilio = new TwilioRestClient(AccountSid, AuthToken);
var options = new CallOptions();
options.Url = doc.ToString(); //Don't have URL need to add XML doc instead
options.To = Phone;
options.From = "********";
var callnow = twilio.InitiateOutboundCall(options);

Twilio Developer Evangelist here.
You cannot add the XML into the CallOptions as shown in the code above. You do need to find a way to place your TwiML into an XML document on a URI accessible by Twilio.
If the message is not dynamic to the call, you could host a static XML file containing TwiML on a service such as Amazon's S3. I have occasionally used Dropbox Public URLs, but only for testing at low volume. But there are lots of options available, including the TwiMLBin service. But if your message is dynamic in any way, you are going to need an application that can respond to HTTP requests.
Is there some particular constraint you have, maybe I can suggest a work around?
Hope this helps!

Related

InvalidSignatureException with AWS Kinesis Video Stream C#

I am attempting to execute my own HTTP signed request since there is no SDK in C# for the PutMedia API for the AWS Kinesis Video Stream, but I am getting the following error message:
StatusCode: 403, ReasonPhrase: 'Forbidden'
x-amzn-ErrorType: InvalidSignatureException:http://internal.amazon.com/coral/com.amazon.coral.service/
Here is a gist of what my code looks like:
var streamName = "audio-stream-test";
var service = "kinesisvideo";
var endpoint = GetPutMediaEndpoint(streamName);
var host = GetHostFromEndpoint(endpoint);
var region = GetRegionFromEndpoint(endpoint);
var t = DateTime.UtcNow;
var canonical_uri = $"{endpoint}/putMedia";
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, new Uri(canonical_uri));
httpRequestMessage.Headers.Add("connection", "keep-alive");
httpRequestMessage.Headers.Add("host", host);
httpRequestMessage.Headers.Add("Transfer-Encoding", "chunked");
httpRequestMessage.Headers.Add("user-agent", "AWS-SDK-KVS/2.0.2");
httpRequestMessage.Headers.Add("x-amzn-fragment-acknowledgment-required", "1");
httpRequestMessage.Headers.Add("x-amzn-fragment-timecode-type", "ABSOLUTE");
httpRequestMessage.Headers.Add("x-amzn-producer-start-timestamp", (t - DateTime.MinValue).TotalMilliseconds.ToString());
httpRequestMessage.Headers.Add("x-amzn-stream-name", streamName);
httpRequestMessage.Headers.Add("x-amz-security-token", sessionToken);
var byteArray = File.ReadAllBytes(filePath);
var content = new ByteArrayContent(byteArray);
httpRequestMessage.Content = content;
var httpClient = new HttpClient();
var aws4RequestSigner = new AWS4RequestSigner(accessKey, secretAccessKey);
var signedHttpRequestMessage = aws4RequestSigner.Sign(httpRequestMessage, service, region).Result;
var httpResponseMessage = httpClient.SendAsync(signedHttpRequestMessage);
Screenshot of Error
I am using the Aws4RequestSigner NuGet package to sign the request. Any ideas what I am doing wrong here? Has anyone tried to use the AWS Kinesis Video Stream with C#/.NET successfully?
Two potential issues with the pseudo-code.
If using session token then the request signing should include the session token as well not only access key/secret access key combination.
The body of the PutMedia is "endless" as it streams out as a realtime stream. As such, the data shouldn't be included in the signature calculation.
This is answer to your question "the actual "content" is not being added to the stream. I see the Put Connection from KVS but no data added".
After you get 200 by setting http headers properly for the signing with below code, you need to have your content set in signedHttpRequestMessage.
var httpResponseMessage = httpClient.SendAsync(signedHttpRequestMessage);

Send file attachment to Facebook messenger API in C#

I looked at the messenger documentation at https://developers.facebook.com/docs/messenger-platform/send-messages/#file to try and figure out how to send local attachments. However, when I try it out with a httpclient I get an error saying that the message body can not be empty must provide a valid attachment or message. Below is my code
string fileType = ImageExtensions.Contains(Path.GetExtension(url).ToUpper()) ? "image" : "file";
var multipartContent = new MultipartFormDataContent();
var content = new StringContent($"{{\"attachment\":{{\"type\":\"{fileType}\", \"payload\":{{\"is_reusable\"=true}}}}");
multipartContent.Add(new StringContent($"{{\"id\":\"{long.Parse(recipient)}\"}}"), "recipient");
multipartContent.Add(new StringContent($"{{\"attachment\":{{\"type\":\"{fileType}\", \"payload\":{{\"is_reusable\"=true}}}}"), "message");
var file1 = File.ReadAllBytes(url);
var file2 = new ByteArrayContent(file1);
file2.Headers.Add("Content-Type", GetMimeType(Path.GetExtension(url)));
multipartContent.Add(file2,"filedata", Path.GetFileName(url));
request.Content = multipartContent;
The file type is image and the mime type is image/jpeg. I know the url exists as I checked File.exists
Welcome to Stack Overflow!
From the code sample provided it's quite hard to work out what's going wrong as it's not runnable in isolation.
That said, I'd first verify that the image you're consuming by url exists in the format you expect. If you download the .jpeg from the url can you open it on your machine? Assuming it's well structured I'd then try and work out if it's the HttpClient that's malformed - or if there's something wrong with the values you're providing to the Facebook API.
You can do this by creating a simple C# Web API project that listens for a multipart upload on a specific route. See this answer for some sample code on how to do this.
Assuming that you're able to send the .jpeg in question between a local client and a local endpoint accepting a multipart/form-data header then the issue must be with how you're using the Facebook API itself.
In your sample I don't see you using the value of the content variable anywhere. Is this intentional?
If that missing variable is a red-herring then you could try running something along the lines of (making sure to swap the values out as necessary for the ones you're having problems with):
using (var httpClient = new HttpClient())
using (var formDataContent = new MultipartFormDataContent())
{
// Read the file in from a local path first to verify that the image
// exists in the format you're expecting.
var fileStream = File.OpenRead("/some/path/image.jpeg");
using (var streamContent = new StreamContent(fileStream))
{
// Don't actually call `.Result` you should await this, but for ease of
// demonstration.
var imageContent = new ByteArrayContent(streamContent.ReadAsByteArrayAsync().Result);
imageContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");
formDataContent.Add(imageContent, "image", "your-file-name-here");
formDataContent.Add(new StringContent ($"{{\"id\":\"{long.Parse("your-recipient-here")}\"}}"), "recipient");
formDataContent.Add(new StringContent($"{{\"attachment\":{{\"type\":\"{"image"}\", \"payload\":{{\"is_reusable\"=true}}}}"), "message");
// Again don't call `.Result` - await it.
var response = httpClient.PostAsync("https://some-url-here.com", formDataContent).Result;
}
}
If you run the above do you still get an empty message body error?
If you stumble upon this and you're using the FacebookClient from Nuget. This is how I finally managed to upload files to the messages api using vb.net.
Dim Client = New FacebookClient(GetPageAccessToken(PageID))
Dim TmpParams As New Dictionary(Of String, Object)
TmpParams.Add("recipient", "{""id"":""RECIPIENT_ID""}")
TmpParams.Add("message", "{""attachment"":{""type"":""image"", ""payload"":{""url"":"""", ""is_reusable"":false}}}")
TmpParams.Add("messaging_type", "RESPONSE")
Dim Med As New FacebookMediaObject()
Med.FileName = YourFile.FileName
Med.ContentType = YourFile.ContentType
Med.SetValue(YourFile.InputStream.ToBytes())
TmpParams.Add(YourFile.FileName, Med)
Client.Post("me/messages", TmpParams)
Using a Dictionary(of string,object), manually add the params for recipient,message,messaging_type and the file bytes.

Delete email using mailinator API

I am creating application to access public emails in mailinator. I can view emails but I have difficulties when I am trying to delete them.
https://mailinator.com/apidocs.jsp all examples from documentacion worked except this one.
I have code to POST Http request:
using (var client = new HttpClient())
{
var values = new Dictionary<string, string>
{
{ "msgid", id}
};
var content = new FormUrlEncodedContent(values);
var response = await client.PostAsync("https://api.mailinator.com/api/delete?", content);
var responseString = await response.Content.ReadAsStringAsync();
}
Only error it throws is (405) Method Not Allowed. or Method is not supported by this URL.
So I guess either my url that I'm sending is bad, either my code.
I need some help to figure it out.
According to the API docs you need to pass a valid token with every call. The delete API example looks like this:
curl "https://api.mailinator.com/api/delete?id=1373143878-0-test22&token=..."
The elipsis (...) there needs to be a valid token. So, add the token to your values dictionary.

How to write nested Json web services in c# for windows store app

I'm working on windows store app where i am using a web service which have parameter which are nested like this
userData, #"user_login",
email, #"email",password, #"password",
user_login key contains to key email and password with their value .I Hit the web service in the fiddler and if works i am getting the response the parameter string i used
{
"user_login":{"email" : "mmmmmmmm#fdhfgh.co","password" : "pass1234"}
}
when i am using this parameter string in my code i am getting error of status code 400 bad request due to the parameter string .
here is my code
string content = string.Empty;
System.Net.Http.HttpClient httpClient = new System.Net.Http.HttpClient();
httpClient.DefaultRequestHeaders.Date = DateTime.Now;
var httpContent = new System.Net.Http.StringContent("{'user_login':[{'email':"mmmmmmmm#fdhfgh.co",'password':'pass1234'}}]", Encoding.UTF8,"application/json");
var httpResponse = await httpClient.PostAsync(" http://localhost/appi/pupil/log_in", httpContent);
content = await httpResponse.Content.ReadAsStringAsync();
help me out with your valuable suggestions.
In your C# code, you're passing in an array (as denoted by the [ ]'s). It doesn't look like your were doing that in Fiddler. It also looks like the [ ]'s aren't formatted properly. I'd try just taking that out.
EDIT:
"{\"user_login\":{\"email\":\"mmmmmmmm#fdhfgh.com\",\"password\":\"pass1234\"}}"
If this is the correct signature, the above JSON would work.
EDIT 2:
var httpResponse = await httpClient.PostAsync(" http://localhost/appi/pupil/log_in", httpContent);
Couldn't help but notice that you had "localhost/appi" instead of "localhost/api". That could possibly be a typo? Along with that leading space.

C# authorization in HTTP request Plivo API

I am trying to use Plivo to send text messages from within my WindowsStore Application. Here is what almost works:
// These first 3 lines don't do what I want
var unamepass = AuthID + ":" + AuthToken;
var auth = new HttpCredentialsHeaderValue("Basic", unamepass);
httpClient.DefaultRequestHeaders.Authorization = auth;
string textBody = "sample message";
var plivoText = new
{
src = plivoNumber,
dst = phoneNumber,
text = textBody
};
string Serial = JsonConvert.SerializeObject(plivoText);
IHttpContent PlivoJsonContent = new HttpJsonContent(JsonValue.Parse(Serial));
HttpResponseMessage PlivoResponse =
await httpClient.PostAsync(
new Uri("https://api.plivo.com/v1/Account/<AuthID>/Message/")
, PlivoJsonContent);
Now, this code works... technically. I get a 202 response back. However, before it sends the text, a large authentication pops onto the screen.
If I enter the correct data I get a 202 and the text sends, otherwise I can't send the data. I want to know how to programmatically add this to the request, so I don't have to do it manually. I'm pretty sure it has something to do with the first 3 lines of the snippet, but the documentation I found online wasn't very helpful to me. I can't use RestSharp because it isn't supported for windows store projects, so I would prefer an HttpClient solution.
What "scheme" does Plivo use? How should I construct HttpCredentialsHeaderValue? Is the 3rd line correct?
The answer was startlingly simple. You must convert the string to base64 in order to send it to the header.
See: Convert UTF-8 to base64 string

Categories