Trying to call simple POST API from console App in VS2019 - c#

I am trying to call simple POST API to create a Zendesk Ticket from Console App.
I create C# core console app in VS2019 and pasted simple code which should create New Ticket.
code work in other app but in console app, app just log out from debug...
call never goes...
using (var httpClient = new HttpClient())
{
using (var request = new HttpRequestMessage(new HttpMethod("POST"), "https://testhelp.zendesk.com/api/v2/tickets.json"))
{
try
{
var base64authorization = Convert.ToBase64String(Encoding.ASCII.GetBytes("test#test.com:testPassword"));
request.Headers.TryAddWithoutValidation("Authorization", $"Basic {base64authorization}");
request.Content = new StringContent("{\"ticket\": {\"subject\": \"My first Ticket!\", \"comment\": { \"body\": \"The ticket is from API.\" }}}");
request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
HttpResponseMessage response = await httpClient.SendAsync(request).ConfigureAwait(false);
string content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
Console.WriteLine(response);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
What am I missing?

Async calls are frigid mistresses in some cases.
A good option is to make your main program async and therefore able to await tasks. The issue here is with GUI if that is what you actually have when you get away from the command line I am not sure how well it plays with UI threads, but here is the example. Which is much more elegant.
static async Task Main(string[] args)
{
var TicketTask = await createTicket();
}
async static Task<string> createTicket()
{
var content = "unknown error";
using (var httpClient = new HttpClient())
{
using (var request = new HttpRequestMessage(new HttpMethod("POST"), "https://testhelp.zendesk.com/api/v2/tickets.json"))
{
try
{
var base64authorization = Convert.ToBase64String(Encoding.ASCII.GetBytes("test#test.com:testPassword"));
request.Headers.TryAddWithoutValidation("Authorization", $"Basic {base64authorization}");
request.Content = new StringContent("{\"ticket\": {\"subject\": \"My first Ticket!\", \"comment\": { \"body\": \"The ticket is from API.\" }}}");
request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
HttpResponseMessage response = await httpClient.SendAsync(request).ConfigureAwait(false);
content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
//Console.WriteLine(response);
}
catch (Exception ex)
{
content = ex.Message;
}
}
}
return content;
}
Quick-and-dirty-simple-solution (which I would not suggest for production) is to monitor content within the main loop as a global variable where you fill it on success or failure.
static string content = "";
static void Main(string[] args)
{
var loopcount = 0;
var t = new Task(createTicket);
t.Start();
while(content == "" && loopcount < 50000)
{
System.Threading.Thread.Sleep(100);
loopcount++;
}
}
async static void createTicket()
{
using (var httpClient = new HttpClient())
{
using (var request = new HttpRequestMessage(new HttpMethod("POST"), "https://testhelp.zendesk.com/api/v2/tickets.json"))
{
try
{
var base64authorization = Convert.ToBase64String(Encoding.ASCII.GetBytes("test#test.com:testPassword"));
request.Headers.TryAddWithoutValidation("Authorization", $"Basic {base64authorization}");
request.Content = new StringContent("{\"ticket\": {\"subject\": \"My first Ticket!\", \"comment\": { \"body\": \"The ticket is from API.\" }}}");
request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
HttpResponseMessage response = await httpClient.SendAsync(request).ConfigureAwait(false);
content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
//Console.WriteLine(response);
}
catch (Exception ex)
{
content = ex.mesage;
}
}
}
}

Related

HttpClient.PostAsJsonAsync crushed without exception

I am trying to call an api(POST method) with HttpClient.PostAsJsonAsync. However, it stopped at httpClient.PostAsJsonAsync without any exception.
The source code as below:
public static async Task<oResult> PostApi(string JSON_sObject, string sEnd_Url) {
oResult oResult = new oResult();
var Data = JsonConvert.DeserializeObject(JSON_sObject);
var Url = "http://localhost:44340/" + sEnd_Url;
HttpClient httpClient = new HttpClient();
try {
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await httpClient.PostAsJsonAsync(new Uri(Url), Data); // it stopped here
if (response.IsSuccessStatusCode)
{
var sResponse_content = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<oResult>(sResponse_content);
}
else
{
return oResult;
}
}
catch (Exception ex)
{
LogFile(ex);
return oResult;
}
}
Please advice me if any issue from the source code.
Thank you
you should not trying serialize deserialize twice
remove from your code
var Data = JsonConvert.DeserializeObject(JSON_sObject);
and replace
HttpResponseMessage response = await httpClient.PostAsJsonAsync(new Uri(Url), Data);
with this
var content = new StringContent(JSON_sObject, Encoding.UTF8, "application/json");
var response = await client.PostAsync(sEnd_Url, content);
also fix base httpclient address
var baseUri= #"http://localhost:44340";
using HttpClient client = new HttpClient { BaseAddress = new Uri(baseUri) };
try {

Refactor HttpWebRequest to HttpClient?

How would I convert this to HttpClient? What I'm looking to do is submit a Tweet to the Twitter api and get the response as Json. The HttpWebRequest is working fine but I just want to port it to HttpClient. I made an attempt at it in the second code example, but it's not actually sending or receiving the response.
HttpWebRequest request = null;
WebResponse response = null;
string responseCode = String.Empty;
try
{
string postBody = "status=" + EncodingUtils.UrlEncode(status);
request = (HttpWebRequest)HttpWebRequest.Create(resource_url);
request.ServicePoint.Expect100Continue = true;
request.UseDefaultCredentials = true;
request.PreAuthenticate = true;
request.Credentials = CredentialCache.DefaultCredentials;
request.ServicePoint.ConnectionLimit = 1;
request.Headers.Add("Authorization", authHeader);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
using (Stream stream = request.GetRequestStream())
{
using (StreamWriter writer = new StreamWriter(stream))
{
writer.Write(postBody);
}
}
using (response = request.GetResponse())
{
response.ContentType = "application/json";
responseCode = ((HttpWebResponse)response).StatusCode.ToString();
}
}
catch (WebException ex)
{
if (ex.Status != WebExceptionStatus.NameResolutionFailure)
{
request.Abort();
request = null;
}
throw ex;
}
return responseCode;
This is what I've tried to get it work:
private async Task<string> MakeWebRequest1(string status, string resource_url, string authHeader)
{
HttpClientHandler clientHandler = new HttpClientHandler();
clientHandler.Credentials = CredentialCache.DefaultCredentials;
clientHandler.PreAuthenticate = true;
clientHandler.AllowAutoRedirect = true;
string responseCode = "";
string postBody = "status=" + EncodingUtils.UrlEncode(status);
var request = new HttpRequestMessage()
{
RequestUri = new Uri(resource_url),
Method = HttpMethod.Post,
};
request.Headers.Add("Authorization", authHeader);
// request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
request.Content = new StringContent(postBody, Encoding.UTF8,"application/x-www-form-urlencoded");//CONTENT-TYPE header
using (HttpClient client = new HttpClient(clientHandler))
{
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
// Stream stuff = await client.GetStreamAsync(resource_url);
using (HttpResponseMessage response = await client.SendAsync(request))
{
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
if(response.StatusCode == HttpStatusCode.OK)
{
responseCode = "OK";
}
}
}
clientHandler.Dispose();
return responseCode;
}
enter code here
I've tried to add another parameter to the request and it's always coming back as 401 unauthorized. I'm trying to create a Twitter thread. If I remove the in_reply_to_status_id then it's fine.
data = new Dictionary<string, string> {
["status"] = "#username + status,
["in_reply_to_status_id"] = "1167588690929115136"
};
The Twitter API describes it here https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-update
Reference You're using HttpClient wrong to understand why a static client is being used.
static Lazy<HttpClient> client = new Lazy<HttpClient>(() => {
HttpClientHandler clientHandler = new HttpClientHandler {
Credentials = CredentialCache.DefaultCredentials,
PreAuthenticate = true,
AllowAutoRedirect = true
};
return new HttpClient(clientHandler);
});
private async Task<string> PostStatusRequestAsync(string status, string resource_url, string authHeader) {
using (var request = new HttpRequestMessage(HttpMethod.Post, resource_url)) {
request.Headers.TryAddWithoutValidation("Authorization", authHeader);
request.Headers.Accept.Clear();
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var data = new Dictionary<string, string> {
["status"] = status
};
request.Content = new FormUrlEncodedContent(data);
using (HttpResponseMessage response = await client.Value.SendAsync(request)) {
return response.StatusCode.ToString();
}
}
}
Note the use of the FormUrlEncodedContent for the request body, which will encode and concatenate the data as well as take care of the mime type header
...but it's not actually sending or receiving the response.
Ensure that the above is not invoked as a synchronous blocking call, like .Result, which could cause a deadlock.
For example, an async event handler can be used to make the async call
public async void onButtonClick(object sender, EventArgs args) {
//Non-blocking call
var tweetRequestCode = await PostStatusRequestAsync(TweetText, AuthUtils.GetResourceUrl(), AuthUtils.GetWebRequestHeader()));
//back on UI thread
//...
}
Reference Async/Await - Best Practices in Asynchronous Programming

HttpClient call keeps on waiting mode but works fine in Console App

Below is the code which works perfectly fine when i execute it on console application.
The line
var postResponse = await client.SendAsync(req); give the result when i run the code in console app.
But when iam using this code in WebApi controller, this code halts on this line.
using (var client = new HttpClient())
{
var auth = "MTAwNDgucnVsZXNlbmdpbmUuc2VydmljZTp2N3FuY3I4cWlz";
client.BaseAddress = new Uri("https://federation-sts-stage.accenture.com");
var req = new HttpRequestMessage(HttpMethod.Post, "https://federation-sts-stage.test.com/oauth/ls/connect/token");
var cont = new FormUrlEncodedContent(bodyContents);
cont.Headers.ContentType = new MediaTypeHeaderValue("application/json");
cont.Headers.ContentLength = Convert.ToInt64("125");
req.Content = cont;
req.Headers.Add("Authorization", "Basic " + auth);
try
{
var postResponse = await client.SendAsync(req); // this is where the code keeps on waiting but works fine in console app
postResponse.EnsureSuccessStatusCode();
responseContents = postResponse.Content.ReadAsStringAsync().Result;
}
catch (Exception ex)
{
var msg = ex.Message;
return msg;
}
var responseObject = JObject.Parse(responseContents);
return responseObject.Value<string>("access_token");
}
I have also compared the request object in both the cases (in console app and in webapi controller call) but in both the cases the request object comes out same as below :
{Method: POST, RequestUri: 'https://federation-sts-stage.test.com/oauth/ls/connect/token', Version: 1.1, Content: System.Net.Http.FormUrlEncodedContent, Headers:
{
Authorization: Basic MTAwNDgucnVsZXNlbmdpbmUuc2VydmljZTp2N3FuY3I4cWlz
Content-Type: application/json
Content-Length: 125
}}
I dont know what iam doing incorrect.
As per the comments, i am putting the whole method which gets called from apicontroller as below, this method works fine from console app but when i call this method from apicontroller its kept on running.
public async Task<string> RequestTokenFromIssuer(string username, string password)
{
var bodyContents = new Dictionary<string, string>
{
{ "grant_type", "client_credentials" },
{ "userName", username },
{ "password", password},
{ "scope", "read_rulesengine write_rulesengine" }
};
string responseContents = string.Empty;
using (var client = new HttpClient())
{
var auth = "MTAwNDgucnVsZXNlbmdpbmUuc2VydmljZTp2N3FuY3I4cWlz";
client.BaseAddress = new Uri("https://federation-sts-stage.test.com");
var req = new HttpRequestMessage(HttpMethod.Post, "https://federation-sts-stage.test.com/oauth/ls/connect/token");
var cont = new FormUrlEncodedContent(bodyContents);
cont.Headers.ContentType = new MediaTypeHeaderValue("application/json");
cont.Headers.ContentLength = Convert.ToInt64("125");
req.Content = cont;
req.Headers.Add("Authorization", "Basic " + auth);
try
{
var postResponse = await client.SendAsync(req);
postResponse.EnsureSuccessStatusCode();
responseContents = postResponse.Content.ReadAsStringAsync().Result;
}
catch (Exception ex)
{
var msg = ex.Message;
return msg;
}
var responseObject = JObject.Parse(responseContents);
return responseObject.Value<string>("access_token");
}
}
I believe your problem actually is on line
responseContents = postResponse.Content.ReadAsStringAsync().Result;
Never, ever to this in an async method. You should do it like:
responseContents = await postResponse.Content.ReadAsStringAsync();

System.Net.Http.HttpClient in [Universal Windows Platform] not working properly

I wrote simple method for getting data from (online) REST Service:
public async Task<Object> GetTask()
{
try
{
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri("http://111.111.111.111:8080/");
HttpResponseMessage result = await client.GetAsync("ABC/CDE/getsomeinfo");
if (result.IsSuccessStatusCode)
{
//Deserialize
}
}
}
catch (Exception ex)
{
Debug.WriteLine("Error" + ex);
}
return null;
}
Whenever i run this on UWP i'm getting catch exception:
The text associated with this error code could not be found.
A connection with the server could not be established
HResult 2147012867
Im trying to connect my client with restapi in internal network. In forms same code is working properly.
Try this
HttpResponseMessage response;
public async Task<string> webserviceResponse(string HttpMethod)
{
// check internet connection is available or not
if (NetworkInterface.GetIsNetworkAvailable() == true)
{
// CancellationTokenSource cts = new CancellationTokenSource(2000); // 2 seconds
HttpClient client = new HttpClient();
MultipartFormDataContent mfdc = new MultipartFormDataContent();
mfdc.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data");
string GenrateUrl = "your url";
if (HttpMethod == "POST")
{
response = await client.PostAsync(GenrateUrl, mfdc);
}
else if (HttpMethod == "PUT")
{
response = await client.PutAsync(GenrateUrl, mfdc);
}
else if (HttpMethod == "GET")
{
response = await client.GetAsync(GenrateUrl);
}
var respon = await response.Content.ReadAsStringAsync();
string convert_response = respon.ToString();
return convert_response;
}
else
{
return "0";
}
}

Paypal Rest Api With RestSharp not working in xamarin android

I have got error with RestSharp component when i am call Paypal Rest API.
I have the following code using Xamarin for Android.
public async Task<PayPalGetTokenResponse> GetAccessToken()
{
var restRequest = new RestRequest("/oauth2/token", Method.POST);
// Add headers
restRequest.AddHeader("Accept", "application/json");
restRequest.AddHeader("Accept-Language", "en_US");
// Make Authorization header
restClient.Authenticator = new HttpBasicAuthenticator(Config.ApiClientId, Config.ApiSecret);
// add data to send
restRequest.AddParameter("grant_type", "client_credentials");
var response = restClient.Execute<PayPalGetTokenResponse>(restRequest);
response.Data.DisplayError = CheckResponseStatus(response, HttpStatusCode.OK);
return response.Data;
}
But got error :"Error: SecureChannelFailure (The authentication or decryption has failed.)"
I have Also use ModernHttpClient but got same error
public async Task<PayPalGetTokenResponse> GetAccessToken()
{
string clientId = Config.ApiClientId;
string secret = Config.ApiSecret;
string oAuthCredentials = Convert.ToBase64String(Encoding.Default.GetBytes(clientId + ":" + secret));
string uriString = Config.ApiUrl+"/oauth2/token";
PayPalGetTokenResponse result;
HttpClient client = new HttpClient(new NativeMessageHandler());
var h_request = new HttpRequestMessage(HttpMethod.Post, uriString);
h_request.Headers.Authorization = new AuthenticationHeaderValue("Basic", oAuthCredentials);
h_request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
h_request.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue("en_US"));
h_request.Content = new StringContent("grant_type=client_credentials", UTF8Encoding.UTF8);
try
{
HttpResponseMessage response = await client.SendAsync(h_request);
//if call failed ErrorResponse created...simple class with response properties
if (!response.IsSuccessStatusCode)
{
var error = await response.Content.ReadAsStringAsync();
var errResp = JsonConvert.DeserializeObject<string>(error);
//throw new PayPalException { error_name = errResp.name, details = errResp.details, message = errResp.message };
}
var success = await response.Content.ReadAsStringAsync();
result = JsonConvert.DeserializeObject<PayPalGetTokenResponse>(success);
}
catch (Exception)
{
throw new HttpRequestException("Request to PayPal Service failed.");
}
return result;
}
Have you tried to force to modern day SSL protocol?
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
This works for me:
if (ServicePointManager.SecurityProtocol != SecurityProtocolType.Tls12)
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var client = new RestClient(payPalURL) {
Encoding = Encoding.UTF8
};
var authRequest = new RestRequest("oauth2/token", Method.POST) {
RequestFormat = DataFormat.Json
};
client.Authenticator = new HttpBasicAuthenticator(clientId, secret);
authRequest.AddParameter("grant_type","client_credentials");
var authResponse = client.Execute(authRequest);

Categories

Resources