Post rest web api working from Postman but not returning any response from code in C# project - c#

There is a POST rest api which used to work from code before. But recently it is broken and is not returning any response. However if I try to call the api from the Postman, then it works fine.
In what way can I debug this to find the root cause of the issue ?
Following is the C# code which I am using to call this post rest api
public async Task SaveToServerAsync()
{
string filePath = #"<filePath>";
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
// tried this line of code from another SO answer, but this didn't work either
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("https://<server name>/");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "d2ebf9aefbaa416adcd0");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Add("Accept", "*/*");
client.DefaultRequestHeaders.Add("Connection", "keep-alive");
using (var fileStream = new FileStream(filePath, FileMode.Open))
{
var content = new MultipartFormDataContent();
content.Add(new StreamContent(fileStream), "file", filePath);
content.Add(new StringContent("e8d002f9-f381-44c2-bce0-13416929f14d"), "Id");
try
{
var response = await client.PostAsync("<rest api end point>", content).ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
Debug.Write("Response received");
}
}
catch (Exception ex)
{
Debug.Write("Exception occured");
Debug.Write(ex.Message);
}
finally
{
}
}
}
}
It always goes to the exception block with exception as "The task was cancelled"
Not sure how can I debug it when it anyway works from the Postman.

So the problem was related to ExpectContinue header which goes as true by default. Somehow server was not handling it properly and client was waiting for continue (100) message for indefinite time.
For the time being manually setting this header to be false worked for us:
httpClient.DefaultRequestHeaders.ExpectContinue = false;

Related

C# HttpClient Server rejects Multipart Content Type Calls

We decide to move our API to a server with SSL, before that everything works fine, but since we change to the server with SSL the calls with content-type: multipart/form-data just dont work (403 forbidden), the ones with Content-Type: application/json works fine, i think is a problem with the server/Apache but i dont want to stay arms crossed while the one in the team who has the access to that tries to solve it, so i want to discard any problem with my code
HttpClient call
using (var content = new MultipartFormDataContent())
{
if (EmailText.Text.Contains("#") && EmailText.Text.Contains("."))
{
content.Add(new StringContent(EmailText.Text), "\"email\"");
}
else
{
content.Add(new StringContent(EmailText.Text), "\"username\"");
}
content.Add(new StringContent(PasswordText.Password), "\"password\"");
var hand = new HttpClientHandler();
hand.UseDefaultCredentials = true;
hand.AllowAutoRedirect = true;
using (var httpClient = new HttpClient(hand))
{
var Uri = new Uri("https://kuwai.tech");
httpClient.BaseAddress = Uri;
httpClient.DefaultRequestHeaders.Accept.ParseAdd("application/json; charset=utf-8");
httpClient.DefaultRequestHeaders.Add("appName","MetaPrinter");
httpClient.DefaultRequestHeaders.Add("latitude", SettingsHelper.Settings.APISettings.Latitude);
httpClient.DefaultRequestHeaders.Add("longitude", SettingsHelper.Settings.APISettings.Longitude);
httpClient.DefaultRequestHeaders.Add("hostname", SettingsHelper.Settings.APISettings.IP);
httpClient.DefaultRequestHeaders.Add("hostType", "PC");
var httpResponse = httpClient.PostAsync("/apis/" + api + "/auth/login", content);
responseContent = await httpResponse.Result.Content.ReadAsStringAsync();
Result result = JsonConvert.DeserializeObject<Result>(responseContent);
i think everything in my code its ok, but i want to make sure, as i said before using the SSL server it worked well.

The await httpClient.GetByteArrayAsync() in HttpClient suddenly stop after many videos downloaded?

After 2-4 downloading of videos data from API using HttpClient suddenly prompt error.
Here's my code:
public async Task<byte[]> GetMedia(string id)
{
var api = $"/api/v1/download/{id}";
var Uri = $"{MccBaseURL}{api}";
byte[] responseBody;
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("No");
try
{
HttpResponseMessage response = await httpClient.GetAsync(Uri);
response.EnsureSuccessStatusCode();
responseBody = await response.Content.ReadAsByteArrayAsync();
if (response.IsSuccessStatusCode)
{
return responseBody;
}
}
catch (Exception ex)
{
Debug.Print(ex.Message);
throw;
}
}
Then below is the error faced:
Additional error info:
Error
Please help me?
First, you should dispose your HttpResponseMessage, as you have in your answer, but not in the original question.
The most likely issue, though, is your use of DefaultRequestHeaders. You should only use this for headers that apply to every request that the HttpClient instance will send, and then you should set them only once, when you create the client, as the documentation implies ("Headers set on this property don't need to be set on request messages again").
While HttpClient is essentially thread-safe, the DefaultRequestHeaders (and BaseAddress) properties are not. You're changing these values while the client instance is potentially busy using them elsewhere. It's not clear whether you're using the singleton HttpClient elsewhere as well, possibly changing the default headers there too, but if so that would significantly increase the chances of issues arising.
Some additional references about the non-thread-safety of these properties:
https://github.com/dotnet/dotnet-api-docs/issues/1085
http://www.michaeltaylorp3.net/httpclient-is-it-really-thread-safe/
https://github.com/MicrosoftDocs/architecture-center/issues/935
I found an answer which is:
public async Task<bool> GetMedia(string saveDir, string id)
{
var api = $"/api/v1/download/{id}";
var Uri = $"{MccBaseURL}{api}";
using (HttpClient client = new HttpClient())
{
using (HttpResponseMessage response = await client.GetAsync(Uri, HttpCompletionOption.ResponseHeadersRead))
using (System.IO.Stream streamToReadFrom = await response.Content.ReadAsStreamAsync())
{
string fileToWriteTo = System.IO.Path.GetTempFileName();
using (System.IO.FileStream streamToWriteTo = new System.IO.FileStream(saveDir, System.IO.FileMode.Create))
{
await streamToReadFrom.CopyToAsync(streamToWriteTo);
return true;
}
}
}
}
It was really memory something problem which continuously using same HttpClient over and over again. So I created a new instance. I'm a super noob! Sorry!

Xamarin Android POSTing to WebAPI

I have a WebAPI service running on a server, and I am able to hit against it all day long in an MVC app I have. I am now trying to create an Xamarin Android app that also hits against the same WebAPI. I put together some code in a console app to test, and it works just fine. However, when I put the same code in my Xamarin Android app, it cannot connect to the service, I get back an aggregate exception that basically wraps a WebException. Digging into the exception further, it seems it is a System.Net.WebExceptionStatus.ConnectFailure type of error.
Here is the code:
using (HttpClient webAPI = new HttpClient())
{
// hardcode the request to try and see why it errors
AuthUserRequest thisUser = new AuthUserRequest
{
UserName = "username",
Password = "password",
AppName = "Dashboard"
};
webAPI.MaxResponseContentBufferSize = 256000;
string json = Newtonsoft.Json.JsonConvert.SerializeObject(thisUser);
var content = new StringContent(json, Encoding.UTF8, "application/json");
HttpResponseMessage response;
try
{
response = await webAPI.PostAsync("It'sOurURL", content);
}
catch (Exception err)
{
string sHold = err.Message;
throw;
}
response.EnsureSuccessStatusCode();
if (response.IsSuccessStatusCode)
{
Context thisContext = Application.Context;
Toast toast = Toast.MakeText(thisContext, "Successful", ToastLength.Short);
toast.Show();
}
}
As I said it's weird it works just fine from a Console app, just not the Xamarin Android app. Any insight at all into this?
All looks pretty good. My API calls are working in Xamarin Android and iOS. My code is pretty much the same with two real minor differences. I have set ConfigureAwait(false) on the PostAsync call. Additionally I have created a URI variable with the address for the API endpoint and passed that into the PostAsync method, rather then using a hard coded string.
using (var client = new HttpClient())
{
var user = new CredentialsModel
{
Password = password,
Username = username,
};
var uri = new Uri("YOUR_URL_GOES_HERE");
var json = JsonConvert.SerializeObject(user);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync(uri, content).ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
var responseContent = await response.Content.ReadAsStringAsync();
var authData = JsonConvert.DeserializeObject<ResponseModel>(responseContent);
return authData;
}
return null;
}
It was my own bone-headed mistake... When I tried the URL this morning, it was there, but the IT department has been mucking about with the server, so it's no longer available externally. Sorry to bother everyone with this.

Concur V3 Api not working for Users

I configured a Concur Sandbox and played around with the api. Since the User api is not supported by the .Net SDK I wrote following code.
Issue is that code for Expenses work (returns 200 with valida result), but code for users returns 401 Unauthorized.
Expenses
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("OAuth", oauthAccessToken);
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
var requestUri = "https://www.concursolutions.com/api/v3.0/expense/receiptimages";
var respone = await httpClient.GetAsync(requestUri);
if (respone.IsSuccessStatusCode)
{
var result = respone.Content.ReadAsStringAsync();
//throw new InvalidUriException(string.Format("Invalid uri: {0}", requestUri));
}
}
Ideally this should also work as the previous code works,
Users
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("OAuth", oauthAccessToken);
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
var requestUri = "http://www.concursolutions.com/api/v3.0/common/users?user=user1%40company.net";
var respone = await httpClient.GetAsync(requestUri);
if (!respone.IsSuccessStatusCode)
{
//throw new InvalidUriException(string.Format("Invalid uri: {0}", requestUri));
}
}
}
I thought it's a permission issue, but I given allowed enough permission.
Here is the Administration->Webservice app configuration,
Issue is that the User Api call needs to be https.

ASP.Net Web API Request URI Error

I have an ASP.Net Web API that generally works fine. I have a Winforms client application that does GET requests. The client application runs on our corporate network (the API is hosted as an Azure Website). Occasionally, and inconsistently, the HttpClient calls I make add what seem to be corporate URLs in front of my GET call.
Example: I try to call send an HttpClient request to the following URL: 'http://xyzxyz.azurewebsites.net/api/user/1'
but the actual request made is:
'http://usgaabc1iru01/B0000D0000N0001F0000S0000R0004/http://xyzxyz.azurewebsites.net/api/user/1'
This obviously causes an error.
I've asked our IT department what may be happening and they are at a loss. Hoping someone could point me in the right direction.
Edit:
Here's the code I use. First I have a static method I call everything I make a call to the API to get the HttpClient (is this awkward/bad perhaps):
public static HttpClient GetHttpClient()
{
var credentials = new NetworkCredential(GlobalVariables.CurrentUser.UserName, GlobalVariables.CurrentUser.Password);
HttpClientHandler handler = new HttpClientHandler();
handler.UseDefaultCredentials = false;
handler.Credentials = credentials;
HttpClient client = new HttpClient(handler);
client.BaseAddress = new Uri(PublicClasses.GlobalVariables.BaseUriString);
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
GlobalVariables.CredentialedHttpClient = client;
}
return GlobalVariables.CredentialedHttpClient;
}
}
Here's a simple GET call I use:
public static List<Project> GetAllProjects()
{
try
{
HttpClient client = GetHttpClient();
HttpResponseMessage response = client.GetAsync("api/project").Result; // Blocking call!
if (response.IsSuccessStatusCode)
{
var projects = response.Content.ReadAsAsync<IEnumerable<Project>>().Result;
return (List<Project>)projects;
}
else
{
Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
return null;
}
}
catch (Exception)
{
throw;
}
}
I don't have an answer for why is this happening but I came across similar issue in a web form (not a win forms client). That is solved by using base meta tag.I am not sure if that solves your problem, but you can give a try.
You can use base address with HttpClient like this (if you are not already doing this):
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://xyzxyz.azurewebsites.net/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync("api/user/1");
if (response.IsSuccessStatusCode)
{
//add your code
}
}

Categories