Post JSON data to Microsoft Graph API Azure Function - c#

I'm trying to use an Azure function to forward an Outlook email using its ID.
var url = "https://graph.microsoft.com/v1.0/users('<blah>')/messages/" + ID + "/forward";
var content = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json");
var response = await client.PostAsJsonAsync(url, content);
log.Info(response.Content.ReadAsStringAsync().Result);
The result I'm getting is The value of the parameter 'ToRecipients' is empty. Specify 'ToRecipients' either in the message object or in the action.
The data variable I'm passing in is {"message":{"ToRecipients":[{"emailAddress":{"address":"<blah>"}}]}}.
What am I doing wrong? How do I successfully post a data JSON object? I feel like I've tried every example I can find online and I haven't had any luck.
FYI, token has already been attached to headers, I'm just not showing that part.

You appear to be double serializing the data to be sent.
First when you manually serialize
...JsonConvert.SerializeObject(data)...
and second when you call PostAsJsonAsync
client.PostAsJsonAsync(url, content);
which would serialize the provided object to JSON before posting.
If calling PostAsJsonAsync then no need for you to create the content manually
//...
var url = "https://graph.microsoft.com/v1.0/users('<blah>')/messages/" + ID + "/forward";
var response = await client.PostAsJsonAsync(url, data);
var result = await response.Content.ReadAsStringAsync();
log.Info(result);
//...

Related

Use HttpPost to send multiple data to one URL at same time

I need to send information to an API, but due to memory limitation, I have to split this data into two parts
My question is, how to send this information separately at the same time?
Example:
I tested it this way and only postTo1 is sent
result = repository.GetAll();
result2 = repository.GetNames();
var jsonString = JsonConvert.SerializeObject(result, Formatting.None);
var jsonString2 = JsonConvert.SerializeObject(result2, Formatting.None);
var postTo1 = HttpPostAsync(Url, "[" +jsonString1 + "]");
var postTo2 = HttpPostAsync(Url, "[" +jsonString2 + "]");
static async Task<HttpResponseMessage> HttpPostAsync(string url, string data)
{
HttpContent content = new StringContent(data);
HttpResponseMessage response = await httpClient.PostAsync(url, content);
response.EnsureSuccessStatusCode();
return response;
}
It depends how you're sending it.
If you sent it via a query parameter or the route, just create an object that holds the two strings. You'll be able to get away with a single API call.
If you are already sending it via the body, you'll need to store the data in something like SQL. Return the primary key in the first API call. Then in your second call, pass the primary key in the route. You'll be able to retrieve the first record.

SendGrid - Loading Exported Contacts

I'm trying to process the resulting URLs from the marketing/contacts/exports/{id} call I used the following code however the data is dataresponse is zipped/encrypted.
SendGridClient client = new SendGridClient(AppConfig.ReadSetting("SENDGRID_API_KEY"));
SingleSendContactList allListsSingleSend = new SingleSendContactList();
var response = await client.RequestAsync(method: SendGridClient.Method.GET, urlPath: "marketing/lists?page_size=500");
allListsSingleSend = JsonConvert.DeserializeObject<SingleSendContactList>(response.Body.ReadAsStringAsync().Result);
SingleSendExportSetup SSExportSetup = new SingleSendExportSetup();
SSExportSetup.file_type = "json";
SSExportSetup.max_file_size = 5000;
// marketing/contacts/exports, POST returns JSON with id as main field
SingleSendExportID ExportContactsSingleSend = new SingleSendExportID();
response = await client.RequestAsync(method: SendGridClient.Method.POST, urlPath: "marketing/contacts/exports", requestBody: JsonConvert.SerializeObject(SSExportSetup));
ExportContactsSingleSend = JsonConvert.DeserializeObject<SingleSendExportID>(response.Body.ReadAsStringAsync().Result);
//Use this id to then call
// marketing/contacts/exports/id, GET returns JSON with urls as a property, use urls[0]
SingleSendExportURL ExportURLSingleSend = new SingleSendExportURL();
response = await client.RequestAsync(method: SendGridClient.Method.GET, urlPath: "marketing/contacts/exports/" + ExportContactsSingleSend.id);
ExportURLSingleSend = JsonConvert.DeserializeObject<SingleSendExportURL>(response.Body.ReadAsStringAsync().Result);
// Call the URL to get the returned JSON
List<SingleSendExportData> ExportDataSingleSend = new List<SingleSendExportData>();
var dataresponse = await client.RequestAsync(method: SendGridClient.Method.GET, urlPath: ExportURLSingleSend.urls[0]);
ExportDataSingleSend = JsonConvert.DeserializeObject<List<SingleSendExportData>>(dataresponse.Body.ReadAsStringAsync().Result);
I can take the URL in ExportURLSingleSend.urls[0] and drop it in a browser and it will force the download of the file and the data is fine. How do I get this data to convert to my class List<SingleSendExportData>?
I posted this question to SendGrid support and they sent me here.
Thanks.
UPDATE:
This post solved my issue:
https://weblog.west-wind.com/posts/2007/jun/29/httpwebrequest-and-gzip-http-responses
However, now I am realizing that the JSON coming from SendGrid is not properly formatted. There is no comma between rows of data.
UPDATE 2:
This post solved my handling of line delimited JSON files;
Line delimited json serializing and de-serializing
Now I am able to read these zipped JSON files without saving them and then handle the JSON format to load into my list List ExportDataSingleSend.

Transform Restsharp call to asynchronous

I've this function :
public string GetSecurityCrumb()
{
string uri = $"{Url}/crumbIssuer/api/xml";// URL where the XML is available
var client = new RestClient(uri); // define it as the actual client
var request = new RestRequest(Method.GET);
byte[] ua = Encoding.ASCII.GetBytes(Username + ":" + ApiToken); // Encoding username and token in base 64
request.AddHeader("authorization", "Basic " + Convert.ToBase64String(ua));// adding header to get the xml
IRestResponse response = client.Execute(request);
XDocument document = XDocument.Parse(response.Content);// parsing the content of the response in a document
var crumb = document.Root.Element("crumb").Value;// retrieve the content of the crumb only
return crumb;
}
I tried a lot of things to do this aynchronous, but I just don't see how I can return string value if I change my Rest call to an aynschronous one.
Maybe somebody already got this kind of problem and could help me.
EDIT 1
I tried this :
public async Task<string> GetSecurityCrumb()
{
string uri = $"{Url}/crumbIssuer/api/xml";// URL where the XML is available
var client = new RestClient(uri); // define it as the actual client
var request = new RestRequest(Method.GET);
byte[] ua = Encoding.ASCII.GetBytes(Username + ":" + ApiToken); // Encoding username and token in base 64
request.AddHeader("authorization", "Basic " + Convert.ToBase64String(ua));// adding header to get the xml
IRestResponse response = await client.ExecuteTaskAsync(request);
XDocument document = XDocument.Parse(response.Content);// parsing the content of the response in a document
var crumb = document.Root.Element("crumb").Value;// retrieve the content of the crumb only
return crumb;
}
but it seems like I need to put await before all my calls on this method and use GetSecurityCrumb().Result to get the real content. I don't know if it's the best way because I've totally 0 error handlers at the moment. A lot of my methods depend of this one so I prefer having the best solution
it seems like I need to put await before all my calls on this method and use GetSecurityCrumb().Result to get the real content
You shouldn't call .Result - that would block on the asynchronous method, removing all the benefits of asynchronous code in the first place.
It's normal to await the task returned from GetSecurityCrumb(). And using that await means that the calling method should also be marked async and return a task. Which means that its callers should use await, so they should be made async, etc. This is all perfectly normal and is the correct way to use async/await.

How to call rest api PUT request with adding single value in header and json data in body in C#?

Rest API is written and I have a URL of one method. I just want to hit that URL and add single key value pair in header, and json data in body. This is what I have done so far:
var client = new HttpClient();
client.BaseAddress = new Uri(uri);
client.DefaultRequestHeaders.Remove("authorization");
client.DefaultRequestHeaders.Add("authorization", "Token "+base64token);
var content = new StringContent(JsonString, Encoding.UTF8,
"application/json");
HttpResponseMessage response = await client.PutAsync(queryString, content);
Here uri= My base url, base64token= authorization token, JsonString= Json data for body, queryString= path of method called.
Now, problem is that this method works for the first time correctly for user1. But does'nt works for user2. And when I call again for user1, it is still working for user1. Kindly help

Setting up a REST Client Application (Post) from a Web API

I've been having a few issues in trying to retrieve the results of a POST operation from a Web Service.
I have been using a chrome extension to test the API Services and they are working there. However I've been having problems on implementing it in code.
This is an example of usage of the chrome extension:
What I'm trying to retrieve on code, is the last part, the json array that the POST operation generates, where it says accessToken.
However, in the code that I've been using below, I've only had access to the status (200 OK) etc.
Here's a preview of the code I am using:
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(url.Text);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(header.Text));
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, url.Text);
request.Content = new StringContent(body.Text, Encoding.UTF8, header.Text);
client.SendAsync(request)
.ContinueWith(responseTask =>
{
MessageBox.Show(responseTask.Result.Content.Headers.ToString());
}
);
}
The Header.Text is exactly "application/json", the body.Text is body which has those various properties such as username and password (in string format) and url.Text contains the complete URL to call the Web service.
I'd like to know what I'm doing wrong with my code, and what can I do to obtain that json array that contains the accessToken
In your code you need to use ReadAsStringAsync method to convert your HttpContent object to string/json. For example:
client.SendAsync(request)
.ContinueWith(responseTask =>
{
var jsonString = responseTask.Result.Content.ReadAsStringAsync().Result;
MessageBox.Show(jsonString);
});
then you can convert you jsonString as you need.

Categories

Resources