Code gets skipped after doing a HttpRequest - c#

So I'm making a POST call to my API to get multiple objects which then get added to a list and are displayed in the RecyclerView. The problem is, after getting to the var result it skips the entire remaining code in that method and executes the next method SetupRecyclerView. The catch doesn't catch any exception. What's wrong with that code?
async void GetPostList()
{
try
{
string url = "linkToMyWebService";
var uri = new Uri(url);
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = uri
};
HttpClientHandler clientHandler = new HttpClientHandler();
clientHandler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; };
HttpClient client = new HttpClient(clientHandler);
var result = await client.SendAsync(request);
var contentBody = await result.Content.ReadAsStringAsync();
List<postRetrieved> posts = JsonConvert.DeserializeObject<List<postRetrieved>>(contentBody);
foreach (var post in posts)
{
postModel newPost = new postModel();
newPost.username = post.fullName;
newPost.description = post.postTitle;
newPost.city = post.postCity;
postList.Add(newPost);
}
}
catch
{
}
}
void SetupRecyclerView()
{
postRecyclerView.SetLayoutManager(new Android.Support.V7.Widget.LinearLayoutManager(postRecyclerView.Context));
postAdapter = new PostAdapter(MainScreenPosts);
postRecyclerView.SetAdapter(postAdapter);
}

It is likely about Catch. Some error is being returned, and an empty catch causes the method to get skipped.
You can either enable "Common Language Runtime Exception" in "Exception settings" or log the error inside the catch. This will help you to get more details about what went wrong in your code.

Alright, so the problem was with the fact that GetPostList was asynchronous. While waiting for the request to get the list of objects, it started doing the method SetupRecyclerView which required those objects to function. I've put that in the Finally{} block in my trycatch and now it works fine.

Related

HttpClient and HttpclientHandler Dispose or not dispose, that is the question

I am looking to optimize my codeā€¦
I have number of API with early same structure for client and handler.
But I have some questions about disposing.
I have read the using statement automatically dispose resources (here HttpClient and HttpClientHandler).
Could I rewrite my code here:
public static async Task<IEnumerable<T>> deletePostsAsync<T>(IEnumerable<string> urls) where T : BaseReturnValues
{
var httpClientHandler = new HttpClientHandler
{
Proxy = new WebProxy(proxy, true),
UseProxy = IsProxySelected
};
using (var client = new HttpClient(httpClientHandler))
{
client.BaseAddress = new Uri(URI);
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Add(Head.key, Head.apikey);
var tasks = urls.Select(async url => await DeleteAsync<T>(client, url).ConfigureAwait(false));
var result = await Task.WhenAll(tasks).ConfigureAwait(false);
return result!;
}
async Task<U> DeleteAsync<U>(HttpClient client, string url) where U : BaseReturnValues
{
var statusCode = -1;
var json = "_";
var isSuccess = false;
try
{
using (HttpResponseMessage response = await client.DeleteAsync(url).ConfigureAwait(false))
{
statusCode = (Int32)response.StatusCode;
json = await response.Content.ReadAsStringAsync();
isSuccess = response.IsSuccessStatusCode;
}
}
catch (Exception ex)
{
//something to catch
}
:
return record;
}
}
To this piece of code without problem? Disposing resource is always done?
public static async Task<IEnumerable<T>> deletePostsAsync<T>(IEnumerable<string> urls) where T : BaseReturnValues
{
using (var client = SetClientSettings())
{
var tasks = urls.Select(async url => await DeleteAsync<T>(client, url).ConfigureAwait(false));
var result = await Task.WhenAll(tasks).ConfigureAwait(false);
return result!;
}
async Task<U> DeleteAsync<U>(HttpClient client, string url) where U : BaseReturnValues
{
:
:
return record;
}
}
public static Httpclient SetClientSettings()
{
var httpClientHandler = new HttpClientHandler
{
Proxy = new WebProxy(proxy, true),
UseProxy = IsProxySelected
};
var client = new HttpClient(httpClientHandler);
client.BaseAddress = new Uri(URI);
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Add(Head.key, Head.apikey);
return client;
}
So I have created a method SetClientSettings and this method create the client, the clienthandler, add some headers to client and return client.
so
var httpClientHandler = new HttpClientHandler
{
Proxy = new WebProxy(proxy, true),
UseProxy = IsProxySelected
};
using (var client = new HttpClient(httpClientHandler))
{
client.BaseAddress = new Uri(URI);
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Add(Head.key, Head.apikey);
var tasks = urls.Select(async url => await DeleteAsync<T>(client, url).ConfigureAwait(false));
var result = await Task.WhenAll(tasks).ConfigureAwait(false);
return result!;
}
is really equivalent to??:
using (var client = SetClientSettings())
{
var tasks = urls.Select(async url => await DeleteAsync<T>(client, url).ConfigureAwait(false));
var result = await Task.WhenAll(tasks).ConfigureAwait(false);
return result!;
}
Your two pieces of code are not equivalent. There is a small difference, that with the first snippet you will dispose the client even when the following lines (e.g. client.BaseAddress = new Uri(URI); or client.DefaultRequestHeaders.Clear();) fail. Which is better. To achieve this with SetClientSettings you would need to wrap everything into try except and .Dispose() on exception.
I have read the using statement automatically dispose resources (here HttpClient and HttpClientHandler).
The using statement turns this:
using (var instance = something)
{
// body
}
into this
var instance = something;
try
{
// body
}
finally
{
if (instance != null)
{
instance.Dispose();
}
}
That's all it does. It is a syntactic sugar.
And so in your particular case the using statement will ensure that .Dispose() is called on HttpClient, regardless of whether exception is thrown or not.
Now, do we have to dispose HttpClient? Well, they say we have to, there's no reason not to believe it. In reality the HttpClient holds sockets under the hood, which have to be closed manually when done with. And so, yes, you should always dispose HttpClient when done with.
That being said, the best thing you can do is to have a singleton HttpClient for the duration of your app, and reuse it. You can tweak it to your needs (e.g. configure it to use pooled connections) for maximal efficiency. In such scenario you don't dispose it at all.
Note: you don't have to worry about disposing HttpClientHandler. By default HttpClient will dispose it when it is disposed itself. This behaviour can be modified by using different constructor.
Yes, the code you wrote is equivalent to each other. There's an option in HttpClient contructor to not to dispose message handler - by default, it's set to true. Anyway, as already suggested, you don't have to dispose HTTP client at all. There are reasons for that.
There's alot of nice articles about best practices of using HttpClient.
Try to search for IHttpClientFactory.

How to check the rest empty response in dotnet

I am using RestSharp for API calling in dotnet core. I have one endpoint on which sometimes I am getting empty response {} and when there is data it returns me the data.
I want to add this empty {} response check so currently, I am doing so.
var request = new RestRequest($"endpoint", Method.Get);
request.AddHeader("Content-Type", "application/json");
var response = client.Execute<EmployeeDetails>(getRequest);
How to check the rest empty response in dotnet
Altough, your code snippet were incomplete to simulate your issue. However, you could check your response data collection by simply checking response.Data.Count == 0.
Here is the complete example.
Asp.net Core C# Example:
public IActionResult GetAll()
{
HttpClientHandler clientHandler = new HttpClientHandler();
clientHandler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; };
HttpClient httpClient = new HttpClient(clientHandler);
httpClient.BaseAddress = new Uri("https://localhost:44361/");
var restClient = new RestClient(httpClient);
var request = new RestRequest("UserLog/GetData", Method.Get) { RequestFormat = DataFormat.Json };
var response = restClient.Execute<List<QueryExecutionModel>>(request);
if (response.Data.Count == 0)
{
var emptyObject = new QueryExecutionModel();
return Ok(emptyObject);
}
return Ok(response.Data);
}
Note: When I am getting qualified response I am directly returning the response as Ok(response.Data). While I am getting the response model count = 0 then I am returing the empty model by new QueryExecutionModel()
Output:
Why did not use http client?
Plese Check it out!
https://www.c-sharpcorner.com/article/calling-web-api-using-httpclient/

why does this HttpClient PutAsync returns internal server error after a successful update

I have a HttpPut API method that edits an object it is passed and saves into the database successfully. This works fine, however from my MVC application, the httpClient.PutAsync which I use to call my API Put method returns internal server error, even though the API Put method does not.
I am not sure what is going wrong, the API method works fine, but somehow the MVC HttpClient still gets an internal server error.
API PUT METHOD
[HttpPut]
public IActionResult Put([FromBody] School school)
{
try
{
var schoolExists = _schoolRepository.SchoolExists(school.Id);
if (!schoolExists) return NotFound();
if (!ModelState.IsValid) return BadRequest();
var schoolData = Mapper.Map<School, Data.School>(school);
var updatedClass = _schoolRepository.UpdateSchool(schoolData);
if (!updatedClass) return Json(GetHttpResponseMessage(HttpStatusCode.InternalServerError));
var route = CreatedAtRoute("GetSchool", school);
return route;
}
catch (Exception e)
{
return LogException(e);
}
}
The method above works fine and my changes are saved into the database and CreatedAtRouteResult object is returned from the API method.
MVC HTTPCLIENT
public async Task<T> PutObject(string path, T content, string accessToken)
{
using (var httpClient = new HttpClient())
{
try
{
SetBaseUri(httpClient, accessToken);
var serialisezContent = CreateHttpContent(content);
var httpResponse = await httpClient.PutAsync(path, serialisezContent);
if (httpResponse.StatusCode == HttpStatusCode.InternalServerError) throw new Exception("Problem accessing the api");
return JsonConvert.DeserializeObject<T>(GetResult(httpResponse));
}
catch (Exception ex)
{
throw ex;
}
}
}
The method above is where is issue is, this line var httpResponse = await httpClient.PutAsync(path, serialisezContent); returns internal server error still. I have the same implementation for my POST and that works just fine.
SETBASEURI()
private void SetBaseUri(HttpClient httpClient, string accessToken)
{
httpClient.BaseAddress = new Uri(BaseUri);
httpClient.DefaultRequestHeaders.Authorization =
_authenticationHeaderValueCreator.CreateAuthenticationHeaderValue("bearer", accessToken);
}
CreateHttpContent()
public ByteArrayContent CreateHttpContent<TParam>(TParam httpObject)
{
var content = JsonConvert.SerializeObject(httpObject);
var buffer = System.Text.Encoding.UTF8.GetBytes(content);
var byteContent = new ByteArrayContent(buffer);
byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
return byteContent;
}
I bet your API Put method indeed returns HTTP 500 error with message No route matches the supplied values. You could check it in Fiddler.
And the problem is with following line:
var route = CreatedAtRoute("GetSchool", school);
CreatedAtRoute method takes a route name as first argument. I doubt that you have a route named GetSchool. It's rather an action name in the same controller. And CreatedAtRoute will not throw exception for unknown route, it will just return 500 error code.
To fix this problem, use CreatedAtAction method instead of CreatedAtRoute:
var route = CreatedAtAction("GetSchool", school);
I think the problem is that the result from the API is failing to serialize. Try to manually serialize the result yourself in a unit-test and see where it fails.

Generic async HttpClient method sometimes doesn't work?

I'm creating an application with Xamarin.Forms which consume from SOAP services using POST method; I have a bunch of services that work correctly, indeed, one of these methods is used to send information in multiple cases and my problem is related with this.
I have the following HttpClient method, but sometimes doesn't work... unfortunately I don't have access to back-end code and they are not for the labour of help me with that.
Any idea about how to improve my method or get any approach to the real error? I'm stuck here, since I send the same fields each time.
public async Task<string> InvokeAsync (string uri, string xmlSOAP) {
try {
using (var handler = new HttpClientHandler () { UseCookies = false })
using (var client = new HttpClient (new NativeMessageHandler ())) {
client.DefaultRequestHeaders.Accept.Add (new MediaTypeWithQualityHeaderValue ("application/xml"));
client.DefaultRequestHeaders.Add ("Cache-Control", "no-cache, no-store, must-revalidate");
client.DefaultRequestHeaders.Add ("Pragma", "no-cache");
client.Timeout = TimeSpan.FromSeconds (timeout);
client.DefaultRequestHeaders.CacheControl.NoCache = true;
var req = new HttpRequestMessage (HttpMethod.Post, uri)
{
Content = new StringContent (xmlSOAP, Encoding.UTF8)
};
req.Content.Headers.ContentType = MediaTypeHeaderValue.Parse ("text/xml; charset=utf-8");
if (uri.ToLowerInvariant ().Equals (jsessionUrlCheck)) {
if (jsession != null && jsession.Count > 0) {
foreach (var cookie in jsession) {
req.Headers.Add ("JSESSIONID", cookie);
}
}
jsession = null;
}
HttpResponseMessage response = await client.SendAsync (req);
string responseBodyAsText = response.IsSuccessStatusCode ? await response.Content.ReadAsStringAsync () : string.Empty;
if (!string.IsNullOrEmpty (responseBodyAsText))
{
return responseBodyAsText;
}
return null;
}
} catch (Exception e) {
Debug.WriteLine ("========= InvokeAsync Exception =========");
Debug.WriteLine ("Error: " + e.Message);
return null;
}}
Any idea about how to [...] get any approach to the real error?
It sounds like you don't really know what exactly happens when it "doesn't work". The way you approach the real error is by finding out what exactly happens in this code when it is reported not to work.
Do you have logs? Check the logs. If the exception is there, that should point you in the right direction. Exception not there? Maybe start logging the data received too. No logs? Start logging; there's no better way to handle intermittent failures that you can't reproduce on demand.

Getting "An action can only be invoked as a 'POST' request" when I am trying to call outlook restful api

Currently working with the outlook api, even tough I usually work with the outlook library acquired via Nuget; I have reached a limitation where I am not able to accept event invitations. So I proceeded in making a a restful call out to the the outlook api. However, when I am making the call I am getting the following message {"error":{"code":"InvalidMethod","message":"An action can only be invoked as a 'POST' request."}} when executing the call.
Bad Code
class Program
{
static void Main(string[] args)
{
var testAccept = ExecuteClientCall.AcceptEvent().Result;
}
public static async Task<bool> AcceptEvent()
{
AuthenticationContext authenticationContext = new AuthenticationContext(CrmPrototype.Helpers.AuthHelper.devTenant);
try
{
var token = await GetTokenHelperAsync(authenticationContext, CrmPrototype.Helpers.AuthHelper.OutlookAuthenticationEndpoint);
string requestUrl = "https://outlook.office.com/api/v2.0/Users/***#nowwhere.com/events('AAQkAGZiNDQxZTVkLWQzZjEtNDdjNy04OTc4LTM4NmNjM2JiOTRjNAAQAFpV0CnWR0FIpWFYRtszPHU=')/accept";
HttpClient hc = new HttpClient();
hc.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
var method = new HttpMethod("POST");
var request = new HttpRequestMessage(method, requestUrl)
{
Content = new StringContent("{SendResponse: true}", Encoding.UTF8, "application/json")
};
HttpResponseMessage hrm = await hc.GetAsync(requestUrl);
if (hrm.IsSuccessStatusCode)
{
string jsonresult = await hrm.Content.ReadAsStringAsync();
var stophere = 0;
}
else
{
return false;
}
return true;
}
catch (Exception ex)
{
throw;
}
}
}
Maybe the reason is that you called
hc.GetAsync(requestUrl);
The doc said that this method:
Sends a GET request to the specified Uri as an asynchronous operation.
Try:
PostAsync(Uri, HttpContent)
https://msdn.microsoft.com/en-us/library/system.net.http.httpclient(v=vs.118).aspx
Hope this help you.
Your variable request contains an HttpRequestMessage object that you have created, but your code presently doesn't do anything with it.
Try replacing the line
HttpResponseMessage hrm = await hc.GetAsync(requestUrl);
(which, as pointed out by the other answer, makes a GET request), with
HttpResponseMessage hrm = await hc.SendAsync(request);

Categories

Resources