c# http post request with basic authentication - c#

I've written a python function to move a router's IO port via a HTTP post request with Basic Authentivation. This works fine. But now I'd like to implement the sam with C#.
Here is my python function:
def io_on(ip='192.168.2.1', username='adm', password='123456'):
if not isinstance(ip, str):
print('not string')
try:
payload ='_ajax=1&_web_cmd=%21%0Aio%20output%201%20on%0A'
r = requests.post('http://{}/apply.cgi'.format(ip), auth=HTTPBasicAuth(username, password), data=payload, timeout=3)
if r.status_code == 200:
print('{} : IO ON'.format(ip))
elif r.status_code == 401:
print('{} : Auth error'.format(ip))
else:
print(r.status_code)
except Exception as e:
print(e)
I've experimented with NetWorkCredentials with no success.

Something like this :
try
{
string username = "adm", password = "123456";
string payload = "http://192.168.2.1/apply.cgi/?_ajax=1&_web_cmd=%21%0Aio%20output%201%20on%0A";
HttpClient client = new HttpClient();
var byteArray = Encoding.ASCII.GetBytes($"{username}:{password}");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
HttpResponseMessage response = await client.GetAsync(payload);
HttpContent content = response.Content;
if (response.IsSuccessStatusCode)
{
Console.WriteLine("Success");
}
else if (response.StatusCode == HttpStatusCode.Unauthorized)
{
Console.WriteLine("Auth error");
}
else
{
Console.WriteLine(response.StatusCode);
}
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}

Here's my way to make POST with basic authentication.
var authValue = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.UTF8.GetBytes($"{login}:{password}")));
using (var client = new HttpClient() { DefaultRequestHeaders = { Authorization = authValue } })
{
HttpResponseMessage response = client.PostAsync("https://localhost:44396/Documentation/All?pageNumber=0&pageSize=10", httpContent).Result;
if (response.IsSuccessStatusCode)
{
response = await response.Content.ReadAsStringAsync();
}
}

Related

How can I translate Webrequest method in HttpClient

I have this code for recovering Http code and description, but Visual Studio says that WebRequest is obsolete and that I have to use HttpClient. I'm not familiar with HttpClient can you help me?
IConfigurationRoot config;
myRequest = WebRequest.CreateHttp($"{config["BASE_URL"]}{link}");
myResponse = (HttpWebResponse)myRequest.GetResponse();
Check_load($"{config["BASE_URL"]}{link}");
var code = ((int)myResponse.StatusCode);
var desc = myResponse.StatusDescription;
var client = new HttpClient();
var response = await client.GetAsync(url);
var statusCode = response.StatusCode;
var content = response.Content;
if(statusCode != HttpStatusCode.OK && statusCode != HttpStatusCode.Created){
//return something, error, description
}
Update
From comment #Charlieface pointed out where I haven't declared HttpClient as static field. To avoid creating instances of HttpClient every time it is called, the complete workground as below.
public class HttpHelper{
private static HttpClent client = new HttpClient();
public static async Task<string> GetAsync(string url)
{
var response = await client.GetAsync(url);
var statusCode = response.StatusCode;
var content = response.Content;
if(statusCode != HttpStatusCode.OK && statusCode != HttpStatusCode.Created)
{
//return something, error, description
//return $"error with status code: {statusCode}";
}
else
{
//return "success";
}
}
}
The use of HttpClient is very simple. See the code below
try
{
using (HttpClient client = new HttpClient())
{
var res = await client.GetAsync(url);
var response = await res.Content.ReadAsStringAsync();
var data = JsonConvert.DeserializeObject<MyObject>(response);
// use the new data retreived...
}
}
catch (Exception)
{
responseMessage = new BadRequestObjectResult("error retreiving data");
}
This suppose your data are sent in JSON format

Bad Request error setting header in Ebay API

I would like to ask help how can I fix the issue in the header of my httpclient request.
This is ebay restful api in creating a fulfillment shipment. I am able to create in Postman but when I tried it in VS, it won't work with error bad request. Screenshot below using postman.
Codes below in ASP.NET
private HttpClient CreateHttpClient()
{
var client = new HttpClient();
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
string baseAddress = WebApiBaseAddress;
client.Timeout = new TimeSpan(0, 5, 59);
client.BaseAddress = new Uri(baseAddress);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Add("Authorization", string.Format("Bearer {0}", _cred.eBayToken));
client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");
return client;
}
public HttpResponseMessage PostHttpResponse(string requestUri, object data)
{
var stringPayload = JsonConvert.SerializeObject(data);
var httpContent = new StringContent(stringPayload, Encoding.UTF8, "application/json");
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
httpContent.Headers.Add("Content-Language", "en-US");
using (var client = CreateHttpClient())
{
try
{
HttpResponseMessage response = client.PostAsJsonAsync(requestUri, httpContent).Result;
if (response.IsSuccessStatusCode)
{
return response;
}
else
{
GetErrorsResponse(response);
throw new HttpRequestException(string.Format("There was an exception trying to post a request. response: {0}", response.ReasonPhrase));
}
}
catch (HttpRequestException ex)
{
throw ex;
//return null;
}
}
}
I was able to fix the issue by not converting the request to json but send as object. Though the error provided is very generic and could not identify the main issue. Upon asking to someone has experienced in ebay integration, the main issue is to provide all the needed in the headers.
public HttpResponseMessage PostHttpResponse(string requestUri, object data)
{
using (var client = CreateHttpClient())
{
try
{
HttpResponseMessage response = client.PostAsJsonAsync(requestUri, data).Result;
if (response.IsSuccessStatusCode)
{
return response;
}
else
{
GetErrorsResponse(response);
throw new HttpRequestException(string.Format("There was an exception trying to post a request. response: {0}", response.ReasonPhrase));
}
}
catch (HttpRequestException ex)
{
throw ex;
//return null;
}
}
}
And in the httpclient needs to add the header.
private HttpClient CreateHttpClient()
{
var client = new HttpClient();
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
string baseAddress = WebApiBaseAddress;
if (string.IsNullOrEmpty(baseAddress))
{
throw new HttpRequestException("There is no base address specified in the configuration file.");
}
client.Timeout = new TimeSpan(0, 5, 59);
client.BaseAddress = new Uri(baseAddress);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Add("Authorization", string.Format("Bearer {0}", _cred.eBayToken));
client.DefaultRequestHeaders.Add("Accept-Language", "en-US");
client.DefaultRequestHeaders.Add("Accept-Charset", "utf-8");
client.DefaultRequestHeaders.Add("Accept", "application/json");
client.DefaultRequestHeaders.Add("LegacyUse", "true");
return client;
}

HttpClient post returns bad request in c#, works in postman

I'm trying to access a rest endpoint, https://api.planet.com/auth/v1/experimental/public/users/authenticate. It is expecting json in the request body.
I can get the request to work in Postman but not using c#. Using postman I get the expected invalid email or password message but with my code I get "Bad Request" no matter I try.
Here is the code that makes the request
private void Login()
{
try
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("https://api.planet.com/");
client.DefaultRequestHeaders.Accept.Clear();
//ClientDefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*"));
Data.User user = new Data.User
{
email = "myemail#company.com",
password = "sdosadf"
};
var requestMessage = JsonConvert.SerializeObject(user);
var content = new StringContent(requestMessage, Encoding.UTF8, "application/json");
var response = client.PostAsync("auth/v1/experimental/public/users/authenticate", content).Result;
Console.WriteLine(response.ToString());
}
catch (WebException wex )
{
MessageBox.Show(wex.Message) ;
}
}
class User
{
public string email;
public string password;
}
Here are screen grabs form Postman that are working
The way to get this to work was to alter the content header "content-type". By default HTTPClient was creating content-type: application/json;characterset= UTF8. I dropped and recreated the content header without the characterset section and it worked.
content.Headers.Remove("Content-Type");
content.Headers.Add("Content-Type", "application/json");
The issue is you are trying to call an async method without waiting for the response using await method or var task = method; task.Wait() Therefore, when you end up doing response.ToString() it returns the text you are seeing.
One way to handle this within a non-async method would be to do the following:
var task = client.PostAsync("auth/v1/experimental/public/users/authenticate", content);
task.Wait();
var responseTask = task.Content.ReadAsStringAsync();
responseTask.Wait();
Console.WriteLine(responseTask.Result);
Another way is to make the current method async by doing private async void Login() and then do:
var postResp = await client.PostAsync("auth/v1/experimental/public/users/authenticate", content);
var response = await postResp.Content.ReadAsStringAsync();
Console.WriteLine(response);
Create a Method Like this...
static async Task<string> PostURI(Uri u, HttpContent c)
{
var response = string.Empty;
var msg = "";
using (var client = new HttpClient())
{
HttpResponseMessage result = await client.PostAsync(u, c);
msg = await result.Content.ReadAsStringAsync();
if (result.IsSuccessStatusCode)
{
response = result.StatusCode.ToString();
}
}
return response;
}
call In your Method
public void Login()
{
string postData ="{\"email\":\"your_email\",\"password\":\"your_password\"}";
Uri u = new Uri("yoururl");
var payload = postData;
HttpContent c = new StringContent(payload, Encoding.UTF8,"application/json");
var t = Task.Run(() => PostURI(u, c));
t.Wait();
Response.Write(t.Result);
}

Xamarin POST method not returning correct value

I am having a problem with sending a POST request and getting a response. I have made local PHP script which returns some string values, and I can't get it to work with Xamarin.
This is the method I am using for to send the request:
public async Task<string> Post_Request()
{
var request = new HttpRequestMessage();
request.RequestUri = new Uri("http://localhost/server.php");
request.Method = HttpMethod.Post;
request.Headers.Add("Accept", "application/json");
var client = new HttpClient();
HttpResponseMessage response = await client.SendAsync(request).ConfigureAwait(continueOnCapturedContext: false);
if (response.StatusCode == HttpStatusCode.OK)
{
return "OK";
}
else
{
return "BAD!";
}
}
When debbuging, the program does not go into the if or else code branches on the "if (response.StatusCode == HttpStatusCode.OK)" condition.
This is my PHP script:
<?php
return
"
{
"user":"01",
"name":"ime"
}
"
//echo "OK";
?>
This is a sample post request that I have used.
var objRequest = new CustomerDetailsRequest() {
customerId = 1
};
string url = $"/api/v1/CustomerDetails";
var requestBody = await Task.Run(() => JsonConvert.SerializeObject(objRequest));
using (var httpClient = new HttpClient())
{
CustomerDetailsResponse data = new CustomerDetailsResponse();
try
{
httpClient.BaseAddress = new Uri("http://localhost:3000");
var content = new StringContent(requestBody, Encoding.UTF8, "application/json");
var result = await httpClient.PostAsync(url, content);
var response = await result.Content.ReadAsStringAsync();
data = JsonConvert.DeserializeObject<CustomerDetailsResponse>(response);
if (result.IsSuccessStatusCode && result.StatusCode == HttpStatusCode.OK)
{
return data;
}
return null;
}
catch (Exception exp)
{
return null;
}
}
Let me know if this is confusing

How do I resolve 302 Error when using HttpClient?

I've created a custom DNN module that uses HTTPClient to send information to an external API. My HttpClient method is as follows:
public static async Task<string> CreatePayerResponse()
{
var credentials = GetCredentials();
var objEventLog = new EventLogController();
var gatewaySettings = new GatewaySetting_ProPay();
SignupResult_ProPay result = new SignupResult_ProPay();
using (HttpClient client = new HttpClient(new LoggingHandler(new HttpClientHandler())))
{
HttpRequestMessage request = new HttpRequestMessage();
HttpResponseMessage response = new HttpResponseMessage();
response.EnsureSuccessStatusCode();
client.BaseAddress = new Uri("https://xmltestapi.propay.com/ProPayAPI/signup");
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
string responseBody;
GatewaySetting_ProPay gatewaySetting = new GatewaySetting_ProPay();
SignupRequest payerRequest = new SignupRequest();
HttpContent content = new StringContent(payerRequest.ToString());
try
{
request.Headers.Add("Authorization", credentials);
request.Headers.Add("accept", "application/json");
response = await client.PutAsync("https://xmltestapi.propay.com/ProPayAPI/signup", content);
responseBody = await response.Content.ReadAsStringAsync();
objEventLog.AddLog("Merchant Onboarding Request Sent", portalSettings, userId,
response.ToString(), EventLogController.EventLogType.ADMIN_ALERT);
Console.WriteLine(responseBody);
}
catch (HttpRequestException ex)
{
result.Succeeded = false;
result.Status = ex.Message;
objEventLog.AddLog("Merchant Onboarding Error!", portalSettings, userId, response.ToString(),
EventLogController.EventLogType.ADMIN_ALERT);
Console.WriteLine("\nException Caught!");
Console.WriteLine("Message :{0} ", ex.Message);
}
return response.Content.ToString();
}
}
public static string GetCredentials()
{
GatewaySetting_ProPay gatewaySettings = new GatewaySetting_ProPay();
var billerAccountId = "mycreds";
var authToken = "mycreds";
var encodedCredentials =
Convert.ToBase64String(Encoding.Default.GetBytes(billerAccountId + ":" + authToken));
var credentials = string.Format("Basic {0}", encodedCredentials);
return credentials;
}
When I wire this method up to a click event, an HTTP 302 response is received and nothing is sent to the API. What modifications are needed to ensure proper transmission?
Update
I still receive the following response:
Error code 302 was received from server response.
This is despite implementing the AllowAutoRedirect property and setting it to true. Here's the LoggingHandler class I've written:
public LoggingHandler(HttpMessageHandler innerHandler) : base(innerHandler)
{
}
protected async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken, HttpClientHandler handler)
{
Console.WriteLine("Request:");
Console.WriteLine(request.ToString());
if (request.Content != null)
{
Console.WriteLine(await request.Content.ReadAsStringAsync());
}
Console.WriteLine();
handler.AllowAutoRedirect = true;
HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
Console.WriteLine("Response:");
Console.WriteLine(response.ToString());
if (response.Content != null)
{
Console.WriteLine(await response.Content.ReadAsStringAsync());
}
Console.WriteLine();
return response;
}
Is this the proper way to implement HttpClientHandler and associated properties?
Make sure that instance of HttpClientHandler has AllowAutoRedirect property set true and is used by your HttpClient.
After implementing trace logs for System.Net.Http and related namespaces, the logs stated that the connection was forcibly closed. After further research, it turns out the .NET Framework 4.5 is not compatible with more modern Transport Layer Security (TLS) versions. As such, the approach of calling the API from our DNN application had to be jettisoned because the source code we're extending targets .NET Framework version 4.5.

Categories