I'm working with RestSharp.NetCore package and have a need to call the ExecuteAsyncPost method. I'm struggling with the understanding the callback parameter.
var client = new RestClient("url");
request.AddParameter("application/json", "{myobject}", ParameterType.RequestBody);
client.ExecuteAsyncPost(request,**callback**, "POST");
The callback is of type Action<IRestResponse,RestRequestAsyncHandler>
Would someone please post a small code example showing how to use the callback parameter with an explanation.
Thanks
-C
This worked for me using ExecuteAsync for a Get call. It should hopefully point you in the right direction. Note that the code and credit goes to https://www.learnhowtoprogram.com/net/apis-67c53b46-d070-4d2a-a264-cf23ee1d76d0/apis-with-mvc
public void ApiTest()
{
var client = new RestClient("url");
var request = new RestRequest(Method.GET);
var response = new RestResponse();
Task.Run(async () =>
{
response = await GetResponseContentAsync(client, request) as RestResponse;
}).Wait();
var jsonResponse = JsonConvert.DeserializeObject<JObject>(response.Content);
}
public static Task<IRestResponse> GetResponseContentAsync(RestClient theClient, RestRequest theRequest)
{
var tcs = new TaskCompletionSource<IRestResponse>();
theClient.ExecuteAsync(theRequest, response => {
tcs.SetResult(response);
});
return tcs.Task;
}
RestSharp v106 support .NET Standard 2.0 so if your code worked with RestSharp 105 under .NET Framework - it will also work with .NET Core 2.
RestSharp.NetCore package is not from RestSharp team and is not supported by us. It is also not being updated and the owner does not respond on messages, neither the source code of the package is published.
Related
My API is calling REST API using RestSharp and Code looks like this
var runRequest = { Contains my JSON}
var client = new RestClient(".....");
var request = new RestRequest("....", Method.Post);
string AuthHeader = "...";
request.AddParameter("application/json", runRequest, ParameterType.RequestBody);
request.AddParameter("Authorization", "Bearer " + AuthHeader, ParameterType.HttpHeader);
var response = client.Execute(request); <---- {Red line showing under client}
return Ok(response);
Error
Because of that red line, I am not able to run my program. Can somebody please tell what the issue can be ?
Thank you
You are using the latest RestSharp version. All the sync methods were deprecated as RestSharp uses HttpClient under the hood, and HttpClient doesn't have any sync overloads, everything is async.
You can find a list of changed or deprecated members of RestClient in the documentation.
I am using Xamarin.Forms and I am using HttpClient GetAsync and PostAsync to make calls to an api, my problem is the client is complaining that the application is too slow when it makes an api call. Is there anyways I can speed up this process or is there another faster way to call an api? Here is an example method:
public async Task<List<SubCatClass>> GetSubCategories(int category)
{
var client = new HttpClient();
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("category", category.ToString())
});
var response = await client.PostAsync(string.Format("https://exmample.com/api/index.php?action=getSubCategories"), content);
var responseString = await response.Content.ReadAsStringAsync();
List<SubCatClass> items = JsonConvert.DeserializeObject<List<SubCatClass>>(responseString);
return items;
}
And here is how I am calling it.
await webService.GetSubCategories(item.categoryid);
The api I have full control over the code (PHP) and the server.
Any help would be much appreciated.
Thanks in advance.
UPDATE
I called the api in postman and here was the results
You can try using ModernHttpClient, it will increase your speed than using default by Xamarin
I have an IO bound method that hangs for a split second while fetching data. I've attempted to convert the method to an async method but am having issues with this.
I've included below the non-async version of the code, and my attempt at making it async.
//non async method
public double GetBaseline()
{
var Client = new RestClient();
IRestResponse response;
Client.BaseUrl = new Uri("https://apiv2.bitcoinaverage.com/indices/global/ticker/short?crypto=BTC&fiat=USD");
CryptoAverage BTCAvg;
var request = new RestRequest();
response = Client.Execute(request);
BTCAvg = JsonConvert.DeserializeObject<CryptoAverage>(response.Content);
return Math.Round(BTCAvg.BTCUSD.Last, 2);
}
//async method
public async double GetBaselineAsync()
{
var Client = new RestClient();
IRestResponse response;
Client.BaseUrl = new Uri("https://apiv2.bitcoinaverage.com/indices/global/ticker/short?crypto=BTC&fiat=USD");
CryptoAverage BTCAvg;
var request = new RestRequest();
response = await Client.ExecuteAsync(request);
BTCAvg = JsonConvert.DeserializeObject<CryptoAverage>(response.Content);
return Math.Round(BTCAvg.BTCUSD.Last, 2);
}
There are two issues that I know of with the above code. The first line requires some some of Task keyword but I'm unsure how to code it. I've tried a number of things here without success.
Secondly, ExecuteAsync takes a 2nd argument but I'm unsure what. I've seen some examples of this, but they seem overly complicated for what I'm trying to do?
Appreciate any help you guys can offer!
If you want to use the Async Await pattern, you need to declare the method appropriately
public async Task<double> GetBaselineAsync()
{
var Client = new RestClient();
IRestResponse response;
Client.BaseUrl = new Uri("https://apiv2.bitcoinaverage.com/indices/global/ticker/short?crypto=BTC&fiat=USD");
CryptoAverage BTCAvg;
var request = new RestRequest();
response = await Client.ExecuteAsync(request);
BTCAvg = JsonConvert.DeserializeObject<CryptoAverage>(response.Content);
return Math.Round(BTCAvg.BTCUSD.Last, 2);
}
Usage
await GetBaselineAsync();
Yes.. You will have to let your async propagate through your code like a virus, or not use it at all.
Secondly, if ExecuteAsync is taking 2 seconds, its not because of .Net, there is not reason why the compiler would make your code pause for 2 seconds because of an await (even if you aren't using it correctly) Its the the call to the internet
If the library you use supports both sync and async methods(last usually with Async suffix) you should always use async ones. Async will create separate threads in your code in order to have better performance. And it will run concurrently when it needs. Async methods should almost in every case return Task or generic Task<>. If you want to call an asynchronous method in the synchronous method (in case of method signature doesn't allow you to use await keyword) you need to use .GetAwaiter().GetResult() upon a method which returns Task(in this case it will block the thread and won't run concurrently). Google around it worse it to spend time on it. Async await pattern was a huge step up of C# as language
EDIT: The solution was to change the declaration to;
public async Task<double> GetBaselineAsync()
And change ExecuteAsync to ExecuteTaskAsync. Full code;
public async Task<double> GetBaselineAsync()
{
var Client = new RestClient();
IRestResponse response;
Client.BaseUrl = new Uri("https://apiv2.bitcoinaverage.com/indices/global/ticker/short?crypto=BTC&fiat=USD");
CryptoAverage BTCAvg;
var request = new RestRequest();
response = await Client.ExecuteTaskAsync(request);
BTCAvg = JsonConvert.DeserializeObject<CryptoAverage>(response.Content);
return Math.Round(BTCAvg.BTCUSD.Last, 2);
}
This should be pretty straightforward, but I can't get it to work. I'm using these instructions. I've tried using the Nuget package in my PCL targeting 259 as as well as in another PCL targeting 7. Both PCLs never return after these lines. I've tried both.
//text = await client.RecognizeTextAsync(imageURL);
text = await client.RecognizeTextAsync(imageURL, languageCode: "en", detectOrientation: true);
Here is the REST code I've also tried. This works with my HTTP Helper.
public static async Task<OcrResults> PostReceiptAsync(string imageURL)
{
try
{
var apiKey = "KEY 1";
var content = await HttpHelper.Request(null, String.Format("https://eastus2.api.cognitive.microsoft.com/vision/v1.0?language=en&detectOrientation=true&subscription-key={0}&url={1}", apiKey, imageURL), null, HttpRequestType.POST);
return Mapper<OcrResults>.MapFromJson(await content.ReadAsStringAsync());
}
catch (Exception e)
{
throw;
}
}
In both methods, I'm trying to use a Blob image URL. Here is my calling method.
takePhoto.Clicked += async (sender, args) =>
{
}
It's almost seems like a deadlock issue.
Any help is much appreciated. Thanks!
UPDATE: I finally got the REST method to work with Android and UWP using this bit of code, but it fails in my iOS app. The main problem I had is that the URL that you copy out of Azure does not include the ocr? parameter. The Json Mapper is something that my SDK uses. OcrResults comes from the Project Oxford Nuget package.
public static async Task<OcrResults> ProcessReceiptAsync(string imageUrl)
{
// Instantiate a HTTP Client
var client = new HttpClient();
var apiKey = "KEY 1";
// Request parameters and URI
string requestParameters = "language=en&detectOrientation =true";
string uri = "https://eastus2.api.cognitive.microsoft.com/vision/v1.0/ocr?" + requestParameters;
// Pass subscription key thru the HTTP Request Header
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", apiKey);
// Format Request body
byte[] byteData = Encoding.UTF8.GetBytes($"{{\"url\": \"{imageUrl}\"}}");
using (var content = new ByteArrayContent(byteData))
{
// Specify Request body Content-Type
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
// Send Post Request
HttpResponseMessage response = await client.PostAsync(uri, content);
// Read Response body into the model
//return await response.Content.ReadAsStringAsync(OcrResults);
var result = Mapper<OcrResults>.MapFromJson(await response.Content.ReadAsStringAsync());
return result;
}
}
UPDATE 2: This method also works on Android and UWP, but fails with a BadRequest in my iOS app. I wanted to change up how the image URL gets encoded.
public static async Task<OcrResults> ProcessReceiptAsync2(string imageUrl)
{
// Instantiate a HTTP Client
var client = new HttpClient();
var apiKey = "KEY 1";
// Request parameters and URI
string requestParameters = "language=en&detectOrientation =true";
string uri = "https://eastus2.api.cognitive.microsoft.com/vision/v1.0/ocr?" + requestParameters;
// Pass subscription key thru the HTTP Request Header
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", apiKey);
// Format Request body
var dict = new Dictionary<string, string>();
dict.Add("url", imageUrl);
//var param = JsonConvert.SerializeObject($"{{\"url\": \"{imageUrl}\"}}");
var param = JsonConvert.SerializeObject(dict);
HttpContent contentPost = new StringContent(param, Encoding.UTF8, "application/json");
// Specify Request body Content-Type
//contentPost.Headers.ContentType = new MediaTypeHeaderValue("application/json");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// Send Post Request
HttpResponseMessage response = await client.PostAsync(uri, contentPost);
// Read Response body into the model
//return await response.Content.ReadAsStringAsync(OcrResults);
var result = Mapper<OcrResults>.MapFromJson(await response.Content.ReadAsStringAsync());
return result;
}
UPDATE 3: I tried this code, but it failed with a Bad Request on iOS. I'm using the ExtractTextFromImageUrlAsync. I did get a "file too large" error using the ExtractTextFromImageStreamAsync, so that method appears to have worked.
https://github.com/HoussemDellai/Microsoft-Cognitive-Services-API/blob/master/ComputerVisionApplication/ComputerVisionApplication/Services/ComputerVisionService.cs
UPDATE 4: I removed Microsoft.Net.Http 2.9 from all the Projects and commented out System.Net.Http from all the app.config files. Both methods now work in the Android and UWP app. I still can't get the iOS app to work. The Project Oxford Nuget fails at this line requestObject.url = imageUrl; (see GitHub). The Rest method fails with a Bad Request, but I managed to catch a "InvalidImageUrl" message, so something is happening when the imageUrl is encoded. At this stage, I believe this is a Xamarin issue that's specific to iOS 10.4.0.
Could someone please help me modify the code below:
client.ExecuteAsync(request, response => {
Console.WriteLine(response.Content);
});
Basically I want to use ExecuteAsync method above but don't want to print but return response.Content to the caller.
Is there any easy way to achieve this?
I tried this but doesnt' work:
public T Execute<T>(RestRequest request) where T : new()
{
var client = new RestClient();
client.BaseUrl = BaseUrl;
client.Authenticator = new HttpBasicAuthenticator(_accountSid, _secretKey);
request.AddParameter("AccountSid", _accountSid, ParameterType.UrlSegment); // used on every request
var response = client.ExecuteAsync(request, response => {
return response.data);
});
}
The above code is from
https://github.com/restsharp/RestSharp
There's the thing... you can't return an asynchronously delivered value, because your calling method will already have returned. Blocking the caller until you have a result defeats the point of using ExecuteAsync. In this case, I'd return a Task<string> (assuming response.Content is a string):
Task<string> GetResponseContentAsync(...)
{
var tcs=new TaskCompletionSource<string>();
client.ExecuteAsync(request, response => {
tcs.SetResult(response.Content);
});
return tcs.Task;
}
Now, when the task completes, you have a value. As we move to c#5 async/await, you should get used to stating asynchrony in terms of Task<T> as it's pretty core.
http://msdn.microsoft.com/en-us/library/dd537609.aspx
http://msdn.microsoft.com/en-us/library/hh191443.aspx
With the help of #spender, this is what i got:
You can add new file in RestSharp project, and add this code:
public partial class RestClient
{
public Task<IRestResponse<T>> ExecuteAsync<T>(IRestRequest request)
{
var tcs=new TaskCompletionSource<IRestResponse<T>>();
this.ExecuteAsync(request, response =>
{
tcs.SetResult(
Deserialize<T>(request, response)
);
});
return tcs.Task;
}
}
This will practically return the full response, with status code and everything, so you can check if the status of the response is OK before getting the content, and you can get the content with:
response.Content
From reading the code it looks like you want to use ExecuteAsGet or ExecuteAsPost instead of the async implementation.
Or maybe just Execute- not sure exactly what type Client is.
At some point, there was a bunch of overloads introduced that support System.Threading.Tasks.Task and had the word "Task" in them. They can be awaited (like HttpClient's methods).
For instance:
ExecuteTaskAsync(request) (returns Task<IRestResponse>)
ExecuteGetTaskAsync(request) (returns Task<IRestResponse>)
ExecuteGetTaskAsync<T>(request) (returns Task<IRestResponse<T>>)
Those then became deprecated in later v106 versions in favour of Task-support being the default I believe, e.g. the first one became client.ExecuteAsync(request).
So these days you can just do:
var response = await client.ExecuteAsync(request);
return response.Content;