Transform Restsharp call to asynchronous - c#

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.

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.

API HTTP client returning data

I am working on this helper method that will call an API using the body section. I am passing in the url and data in the model. Then I SerializeObject the model, but I am not sure what to return I get the error message about the response.Content is not found.
public static async System.Threading.Tasks.Task<HttpResponse> HttpClientHandlerAsync(string url, object model)
{
var fullUrl = apiUrl + url;
var json = JsonConvert.SerializeObject(model);
var data = new StringContent(json, Encoding.UTF8, "application/json");
Client.DefaultRequestHeaders.Add("Accept", "*/*");
Client.DefaultRequestHeaders.Authorization
= new AuthenticationHeaderValue("Bearer", "token");
var response = await Client.PostAsync(fullUrl, data);
return response;
}
Add await in front of your
await Client.PostAsync(fullUrl, data);
Because you're trying to get content of Task
I am not sure what to return I get the error message about the response.Content is not found.
Set a breakpoint and hover over the response to see the status code. You could have a 500 server error, authentication error etc.
Furthermore
using (var client = new HttpClient())
Do not do this. It doesn't work the way you think it does, it will starve your connection pool and eventually throw an exception. You need to define the HttpClient somewhere and continue to reuse the same instance.
Further reading if you care https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/

C# httpclient request size/bandwidth

Basically I'm sending a http post request using HttpClient, but the total response of the kb is roughly 60kb, however I only need to read the response url to determine the outcome, is there anyway I can just read response url rather than the entire data?
Example of the code I'm currently using
string URI = "example.com";
var client = new HttpClient();
var response = await client.PostAsync(URI);
var content = await response.Content.ReadAsStringAsync();
string source = content.ToString();
return source;
What this does is return the body content of " Example.com " but I later realised I wouldn't need to read the body content for a string to determine the outcome, but just simply get the response urls.
I assume this would decrease the size of the request drastically if I'm able to receive the response url of the post request without receiving the body content or other content.
Try to use HttpCompletionOption with proper overload of SendAsync method and rewrite your code like
var request = new HttpRequestMessage(HttpMethod.Post, url);
var response = await _client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);

Post JSON data to Microsoft Graph API Azure Function

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);
//...

Get application to wait until Variables are updated

I am working with OAuth at the moment. The problem with the current code is it doesn't wait until the user allows the application on the site and gets the proper key and secret. I was using a threading type wait but, sometimes it not long enough...some users are slower then others. I have attached a snippet of my code. What I would like to know is where to insert a while statement, or should I even use that ?
public OAuthToken GetRequestToken(Uri baseUri, string consumerKey, string consumerSecret)
{
var uri = new Uri(baseUri, "oauth/request_token");
uri = SignRequest(uri, consumerKey, consumerSecret);
var request = (HttpWebRequest) WebRequest.Create(uri);
request.Method = WebRequestMethods.Http.Get;
var response = request.GetResponse();
var queryString = new StreamReader(response.GetResponseStream()).ReadToEnd();
var parts = queryString.Split('&');
var token = parts[1].Substring(parts[1].IndexOf('=') + 1);
var secret = parts[0].Substring(parts[0].IndexOf('=') + 1);
return new OAuthToken(token, secret);
}
You should switch over to the newer System.Net.Http and System.Net.Http.WebRequest libraries that come with .NET now. These all use the new async programming stuff that is available with .NET 4.5.
You can call a request (returning you a task object that you can wait on) and automatically pause the thread for the response. The UI won't respond, as normal. That is probably the easiest thing to do if you don't understand how the new async and await keywords work. For more information on them, see http://msdn.microsoft.com/en-us/library/hh191443.aspx
Here is your code doing things with the new libraries:
using System.Net.Http;
public OAuthToken GetRequestToken(Uri baseUri, string consumerKey, string consumerSecret)
{
var uri = new Uri(baseUri, "oauth/request_token");
uri = SignRequest(uri, consumerKey, consumerSecret);
var message = new HttpRequestMessage(new HttpMethod("GET"), uri);
var handler = new WebRequestHandler();
var client = new HttpClient(handler);
// Use the http client to send the request to the server.
Task<HttpResponseMessage> responseTask = client.SendAsync(message);
// The responseTask object is like a wrapper for the other task thread.
// We can tell this task object that we want to pause our current thread
// and wait for the client.SendAsync call to finish.
responseTask.Wait();
// - Once that thread finishes, and the code continues on, we need to
// tell it to read out the response data from the backing objects.
// - The responseTask.Result property represents the object the async task
// was wrapping, we want to pull it out, then use it and get the content
// (body of the response) back.
// - Getting the response actually creates another async task (the
// .ReadAsStringAsync() call) but by accessing the .Result
// property, it is as if we called .ReadAsStringAsync().Wait(); Except that
// by using Result directly, we not only call Wait() but we get the resulting,
// wrapped object back. Hope that didn't confuse you much :)
var queryString = responseTask.Result.Content.ReadAsStringAsync().Result;
// And all your other normal code continues.
var parts = queryString.Split('&');
var token = parts[1].Substring(parts[1].IndexOf('=') + 1);
var secret = parts[0].Substring(parts[0].IndexOf('=') + 1);
return new OAuthToken(token, secret);
}
Why Not use a modal pop up and then call the authentication class on the submit button

Categories

Resources