Bad Request error setting header in Ebay API - c#

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;
}

Related

Resolve Incident in D365 Online via OData

I have created a controller for one of our customers to use. It should run on POST and receive a JSON body with two parameters: id and statuscode.
The logic is simple - I wish to fetch the incident with guid equals id and change its statuscode based on the received value for statuscode.
Code of controller:
public async Task<MyCustomResponse> CloseIncident([FromBody] MyCustomRequest _request)
{
try
{
// Some logic here to check if both Id and StatusCode exist in _request ...
if(Guid.TryParse(_request.Id, out Guid guid))
{
// Construct OData request
JObject incidentResolution = new JObject();
incidentResolution.Add("subject", "testing");
incidentResolution.Add("incidentid#odata.bind", $"/incidents({guid})");
incidentResolution.Add("timespent", 2); //This is billable time in minutes
incidentResolution.Add("description", "description");
JObject parameters = new JObject();
parameters.Add("IncidentResolution", incidentResolution);
if (_request.StatusCode == 1)
{
parameters.Add("Status", (int)IncidentStatusCode.ProblemSolved);
}
else
{
parameters.Add("Status", (int)IncidentStatusCode.SomeOtherRejectedStatusCode);
}
RegenerateAccess(); // Connect to Microsoft Online
string urlAPI = "/api/data/v9.1/CloseIncident";
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri(_serviceUrl);
client.Timeout = new TimeSpan(0, 2, 0); //2 minutes
client.DefaultRequestHeaders.Add("OData-MaxVersion", "4.0");
client.DefaultRequestHeaders.Add("OData-Version", "4.0");
//client.DefaultRequestHeaders.Add("Prefer", "return=representation");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpMethod method = HttpMethod.Post;
HttpRequestMessage request = new HttpRequestMessage(method, urlAPI);
request.Content = new StringContent(parameters.ToString(), Encoding.UTF8, "application/json");
// Set the access token
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _authResult.AccessToken);
HttpResponseMessage response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
return new MyCustomResponse()
{
Status = Status.Success,
Message = "..."
};
}
return new MyCustomResponse()
{
Status = Status.Error,
Message = "..."
};
}
else throw new Exception("Guid is invalid.");
}
catch(Exception ex)
{
return new MyCustomResponse() { Status = Status.Error, Message = ex.Message };
}
}
I'm getting a "Bad Request" from the client.SendAsync line. I think the OData body request is incorrect, but I can't figure out why.
Code looks perfect. I’ll try to add the below header and see the response.
client.DefaultRequestHeaders.Add("Content-Type", "application/json; charset=utf-8");
While trying to debug, if you see any useful error response in exception that will help troubleshooting.

How to send a post request in dotnet with a list of request headers

public static async Task<HttpResponseMessage> Post(string endPoint, string data){
HttpContent c = new StringContent(data, Encoding.UTF8, "application/json");
using (var client = new HttpClient())
{
HttpRequestMessage request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri(VodapayBaseUrl + endPoint),
Content = c,
};
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage result = await client.SendAsync(request).ConfigureAwait(false); // The code fails here
if (result.IsSuccessStatusCode)
{
Console.WriteLine("got here");
return result;
}
else
{
Console.WriteLine("failled");
return result;
}
}
// return result;
}
Here is an updated version:
public static async Task Post()
{
using (var httpClient = new HttpClient())
{
var requestString = "{\"authCode\": \"0000000001Nk1EEhZ3pZ73z700271891\" }";
httpClient.BaseAddress = new Uri("https://bounties-backend-mini-program.herokuapp.com");
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var request = new HttpRequestMessage(HttpMethod.Post, $"/api/userInfo");
request.Content = new StringContent(requestString, System.Text.Encoding.UTF8, "application/json");
var response = await httpClient.SendAsync(request);
var responseContent = await response.Content.ReadAsStringAsync();
Console.WriteLine(JsonConvert.SerializeObject(response.Headers.ToList()));
if (response.IsSuccessStatusCode)
{
Console.WriteLine("Successful");
Console.WriteLine(responseContent);
}
else
{
Console.WriteLine("Not successful");
}
}
}
class Program
{
private static void Main(string[] args)
{
Post().Wait();
Console.WriteLine();
}
}
}
Can someone please help with this I am new to c# and relatively new to coding. I am trying to send a request using httpclient I need to send data in a json format I also need to send a list of headers. How can I do this and also return json data at the end your help will be appreciated.I am getting an error when i run this:
Your code isn't far off, here's an example that I had in one of my projects ...
using (var httpClient = new HttpClient())
{
var requestString = "{\"authCode\": \"0000000001Nk1EEhZ3pZ73z700271891\" }";
// Setup the HttpClient and make the call and get the relevant data.
httpClient.BaseAddress = new Uri("https://bounties-backend-mini-program.herokuapp.com");
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var request = new HttpRequestMessage(HttpMethod.Post, $"/api/userInfo");
request.Content = new StringContent(requestString, System.Text.Encoding.UTF8, "application/json");
var response = await httpClient.SendAsync(request);
var responseContent = await response.Content.ReadAsStringAsync();
Console.WriteLine(JsonConvert.SerializeObject(response.Headers.ToList()));
if (response.IsSuccessStatusCode)
{
Console.WriteLine("Successful");
Console.WriteLine(responseContent);
}
else
{
Console.WriteLine("Not successful");
}
}
... obviously, it has varying degrees of thought for the scenario at hand but just adapt it as need be.

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.

Have a WebAPI Controller send an http request to another REST service

I'm creating WebAPI service, and I want it to redirect all incoming requests (GET,POST) to an external REST service and return the response (Json/html) to the original request to my WebAPI.
What is the best way to go about doing this? HttpResponseMessage or HttpWebResponse
[HttpGet]
[Route("api/Geocoder")]
public HttpWebResponse GetCandidates(string query)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://externalRestService.com/arcgis/rest/services/Geocode" + query);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
return response;
}
I also tried
[HttpGet]
public HttpResponseMessage Get()
{
try
{
HttpClient httpClient = new HttpClient()
{
BaseAddress = new Uri(""https://externalRestService.com/arcgis/rest/services/Geocode")
};
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
response = httpClient.GetAsync(requestUrl).Result;
return response;
}
catch
{
return new HttpResponseMessage()
{
StatusCode = HttpStatusCode.InternalServerError,
ReasonPhrase = "Internal Server Error"
};
}
}
Thanks in advance for any help. I'm newbie at .Net Core and webapis
The following approach worked for me.
public async Task<IHttpActionResult> GET(string query)
{
string _apiUrl = "http://foo.com/rest/services/Geocode?";
string _baseAddress = "http://foo.com/rest/services/Geocode?";
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(_baseAddress);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var responseMessage = await client.GetAsync(_apiUrl + query);
if (responseMessage.IsSuccessStatusCode)
{
var response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = responseMessage.Content;
return ResponseMessage(response);
}
}
return NotFound();
}

How to Async httpclient with Patch Method

I am trying to consume [this API] (https://learn.microsoft.com/en-us/rest/api/vsts/release/approvals/update). Below is my code, but i am getting 400 bad request.
HttpContent z = new StringContent("{\"status\": \"approved\",\"comments\": \"" + Request.QueryString["comment"].ToString() + "\"}", Encoding.UTF8, "application/json");
public static async Task PatchAsync(Uri requestUri, HttpContent content)
{
try
{
using (HttpClient client = new HttpClient())
{
var method = new HttpMethod("PATCH");
var request = new HttpRequestMessage(method, requestUri)
{
Content = content
};
client.DefaultRequestHeaders.Accept.Add(
new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(
System.Text.ASCIIEncoding.ASCII.GetBytes(
string.Format("{0}:{1}", "", "XXXXXXXXX"))));
//using (HttpResponseMessage response = await client.PostAsync(requestUri, content))
using (HttpResponseMessage response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
respApproval = responseBody;
}
}
}
catch (Exception ex)
{
respApproval = ex.ToString();
}
}
Since you only provide part of the code, I posted my code (which can update approvals successfully) below for your refernce:
public static async void ApproveRelease()
{
try
{
var username = "alternate auth or PAT";
var password = "password";
string accountName = "https://account.visualstudio.com";
string projectName = "projectname";
int approvalid = id;
var approveReleaseUri = "https://accountname.vsrm.visualstudio.com/projectname/_apis/release/approvals/approvlID?api-version=4.1-preview.3";
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(
System.Text.ASCIIEncoding.ASCII.GetBytes(
string.Format("{0}:{1}", username, password))));
var method = new HttpMethod("PATCH");
string approvveReleaseMetaData = "{\"status\":\"approved\", \"comments\":\"Good to go\"}";
var request = new HttpRequestMessage(method, string.Format(approveReleaseUri, accountName, projectName, approvalid, apiVersion))
{
Content = new StringContent(approvveReleaseMetaData, Encoding.UTF8, "application/json")
};
using (HttpResponseMessage response = client.SendAsync(request).Result)
{
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
By referring the blog Using ReleaseManagement REST API’s.
Note: you can only update a release approval which status is pending. If you try to update a release approval which approval status is approved or rejected, you will also get the 400 bad request response.

Categories