Rest API Post Json using C# with two parameters - c#

I need to do a Post request on a REST api, the api accepts JSON data type. I have two parameters to include, startdate and enddate. Any guide in C#? Im getting error (415) Unsupported Media Type. I believe its because my post request doesnt have a proper json body
var request = WebRequest.Create(url) as HttpWebRequest;
request.Method = "POST";
request.Headers.Add(HttpRequestHeader.Authorization, "Bearer xxx");
request.ContentType = "application/json; charset=utf-8";
// Get response here
var response = request.GetResponse() as HttpWebResponse;
if (response.StatusCode == HttpStatusCode.OK)
{
Console.WriteLine(response.ToString());
Console.ReadKey();
// ....
}

This is how I do it with an example of how to set a header.
using Newtonsoft.Json;
// e.g. update a user's email address via REST POST
dynamic user = new JObject();
user.Email = "testuser#test.com";
var json = user.ToString();
// json is then
// {"Email":"testuser#test.com"}
// and the json is POSTed to the appropriate REST url
var client = new HttpClient
{
Timeout = TimeSpan.FromSeconds(10)
};
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("User-Agent", "user agent name");
var request = GetRequestMessage(uri, accessToken, json);
var response = await client.SendAsync(request);
var content = await response.Content.ReadAsStringAsync();
private HttpRequestMessage GetRequestMessage(string uri, string accessToken, string jsonPayload)
{
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, uri)
{
Headers = { { "Authorization", $"Bearer {accessToken}" } }
};
httpRequestMessage.Content = new StringContent(jsonPayload, Encoding.UTF8, "application/json");
return httpRequestMessage;
}

Related

ASP.NET Web API post to an external api

I would like to ask if it is possible for a created ASP.NET Web API (written in C#) to post to an external API?
If it is possible, please share sample code that can post to an url with adding headers and receive a callback from the external API.
A simple way to make HTTP-Request out of a .NET-Application is the System.Net.Http.HttpClient (MSDN). An example usage would look something like this:
// Should be a static readonly field/property, wich is only instanciated once
var client = new HttpClient();
var requestData = new Dictionary<string, string>
{
{ "field1", "Some data of the field" },
{ "field2", "Even more data" }
};
var request = new HttpRequestMessage() {
RequestUri = new Uri("https://domain.top/route"),
Method = HttpMethod.Post,
Content = new FormUrlEncodedContent(requestData)
};
request.Headers // Add or modify headers
var response = await client.SendAsync(request);
// To read the response as string
var responseString = await response.Content.ReadAsStringAsync();
// To read the response as json
var responseJson = await response.Content.ReadAsAsync<ResponseObject>();
Essentially you need use an instance of HttpClient to send an HttpRequestMessage to an endpoint.
Here is an example to post some jsonData to someEndPointUrl:
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, someEndPointUrl);
request.Headers.Accept.Clear();
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
request.Content = new StringContent(jsonData, Encoding.UTF8, "application/json");
var response = await client.SendAsync(request, CancellationToken.None);
var str = await response.Content.ReadAsStringAsync();
if (response.StatusCode == HttpStatusCode.OK)
{
// handle your response
}
else
{
// or failed response ?
}

Forge Api PATCH request returns 415 "unsupported media type"

I am using the Forge API.
I need to execute PATCH request.
When I send it using Postman everything is fine, but when I build request using HttpRequestMessage I get a response - "415 unsupported media type".
By API documentation Content-Type I set to "application/vnd.api+json".
Body of request in Postman
Headers of request in Postman
request object structure
JObject jsonApi = new JObject();
jsonApi.Add("version", "1.0");
JObject attributes = new JObject();
attributes.Add("displayName", file.FileName);
JObject data = new JObject();
data.Add("type", "items");
data.Add("id", file.ExternalFileId);
data.Add("attributes", attributes);
JObject request = new JObject();
request.Add("jsonapi", jsonApi);
request.Add("data", data);
using (var httpClient = new HttpClient())
{
HttpRequestMessage http = new HttpRequestMessage
{
RequestUri = new Uri(url),
Method = new HttpMethod("PATCH"),
Headers =
{
{ HttpRequestHeader.Authorization.ToString(), "Bearer " + userLastAccessToken },
{ HttpRequestHeader.Accept.ToString(), "application/vnd.api+json" }
}
};
http.Content = new StringContent(request.ToString(), Encoding.UTF8, "application/vnd.api+json");
HttpResponseMessage responseMessage = await httpClient.SendAsync(http);
}
Try again with "application/json" or use HttpHeaders.TryAddWithoutValidation ("application/vnd.api+json" might not sit well with the internal validation of HttpHeaders):
http.Content = new StringContent(request.ToString(), Encoding.UTF8, "application/json");
Or:
http.Content = new StringContent(request.ToString(), Encoding.UTF8);
http.Headers.TryAddWithoutValidation("Content-Type", "application/vnd.api+json");
Ok, I solved the problem by setting ContentType in this way
http.Content = new StringContent(request.ToString(), Encoding.UTF8);
http.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/vnd.api+json");

Why there's no Request.Content in ASP .NET MVC 5?

How to get access to content data?
I can get Request.ContentLength , ContentType, but Content I can't.
I tried to add [FromBody] attribute before my string parameter, but it returns null anyway.
[HttpPost]
public string CreateItemType([System.Web.Http.FromBody] string json) // still returns null
{
var Content = Request.Content; // Error: 'HttpRequestBase' doesn't have a definition for 'Content'
if (IsAuthorized(Request) == false) return "Authorization Error"; ...
Are there some ways to access sent data?
My app for sending data:
using (var client = new HttpClient())
using (var request = new HttpRequestMessage())
{
request.Method = HttpMethod.Post;
request.RequestUri = new Uri(Link);
request.Content = new StringContent(json, Encoding.UTF8, "application/json");
request.Headers.TryAddWithoutValidation("Authorization", ApiKey);
client.Timeout = TimeSpan.FromSeconds(10);
var MyResponse = await client.SendAsync(request);
MyResponse.EnsureSuccessStatusCode();
content = await MyResponse.Content.ReadAsStringAsync();
return content;
}
P.S: I could pass all the parameters into the request link, but my JSON-string is too big.

Why HttpClient uses an incorrect requestUri in post request?

When I use HttpClient class to send a POST request to an API URL, it modifies the URL that I've passed to it. For example, when I use the main API URL the RequestUri is incorrect and I receive the not found response. This problem happens when I use api word in the URL !!
Concept:
The Incorrect, modified URL:
Url: https://sandbox-api.alopeyk.com/api/v2/order
Request Url: https://sandbox-api.alopeyk.com
The Correct, and expected URL (This is the one I specify)
Url: https://google.com/api/v2/order
Request Url: https://google.com/api/v2/order
Code:
public async Task<CreateOrderResponse> CreateOrderAsync(CreateOrderRequest request)
{
var endPoint = EndPointFactory<CreateOrderResponse>.Build(HttpMethod.Post);
var jsonString = JsonConvert.SerializeObject(request);
var url = new Uri("https://sandbox-api.alopeyk.com");
var encodedFrom = new StringContent(jsonString);
var httpClient = endPoint.GetHttpClient(url);
var httpResponse = await httpClient.PostAsync("api/v2/orders", encodedFrom).ConfigureAwait(false);
// when use api it's https://sandbox-api.alopeyk.com it should be https://sandbox-api.alopeyk.com/api/v2/orders
// when use other host name for example it's correct
var requesturl = httpResponse.RequestMessage.RequestUri;
return await httpResponse.Content.ReadAsAsync<CreateOrderResponse>().ConfigureAwait(false);
}
// in the EndPoint class
public HttpClient GetHttpClient(Uri url)
{
return new Http.HttpClientFactory().GetOrCreate(Url, Headers);
}
If you want to see HttpClientFactory it's here.
The HttpClient have a problem with my main hostname that it's https://sandbox-api.alopeyk.com
Your Uri must end with a slash like this:
var url = new Uri("https://sandbox-api.alopeyk.com/");
That's a rather silly restriction of HttpClient.
Try this code:
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("https://sandbox-api.alopeyk.com");
HttpResponseMessage response = client.PostAsync("api/v2/orders", new StringContent(jsonString, Encoding.UTF8, "text/json")).Result;
if (response.IsSuccessStatusCode)
{
// Parse the response body. Blocking!
var responseData = response.Content.ReadAsStringAsync().Result;
}
You can try with this code
HttpResponseMessage response = null;
using (var client = new HttpClient())
{
using (var request = new HttpRequestMessage(HttpMethod.Post,"https://sandbox-api.alopeyk.com/api/v2/orders"))
{
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", /*token herer*/);
var data = new StringContent(JsonConvert.SerializeObject(request, Encoding.UTF8, "application/json"));
request.Content = data;
response = await client.SendAsync(request);
}
}

Call REST Service from WebAPi and transfer HttpResponseMessage

I have to call a REST Service from Web API.
Call and retrieve data works well but the return method crash.
I have tried several method that return an async HttpResponseMessage, but I can return this object as well (error socket on chrome ERR_SPDY_PROTOCOL_ERROR).
I've tried too with just a plain json as string, but no more success.
Here some tries :
[Route("{id}")]
public async Task<JObject> Get(string id)
{
dynamic client = new RestClient($"https://...../accounts/{id}/summary",
new Dictionary<string, string> {
//some KVP for access Rest API
});
//await client.Get() returns HttpResponseMessage 200 and Content is well populated
JObject result = JObject.FromObject(await client.Get());
return result;
//Request.CreateResponse(HttpStatusCode.OK, await result.Content.ReadAsAsync<string>());
//HttpResponseMessage result = await client.Get(); => HttpResponseMessage is well filled
//Request.CreateResponse(HttpStatusCode.OK, await result.Content.ReadAsAsync<string>()); => test with wrapping inside a new HttpResponseMessage but no more success
//using (var client = new HttpClient())
//{
// client.BaseAddress = new Uri($"https://....../v1/accounts/{id}/summary");
// client.DefaultRequestHeaders.Accept.Clear();
// client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// HttpResponseMessage response = await client.GetAsync("");
// return Request.CreateResponse(HttpStatusCode.OK, response.Content.ReadAsAsync());
//}
}
Is there a simple method to retrieve json from Rest Service and transfer this as it is ?
If these calls are being performed in a Web API, and there is no logic being applied to the JSON Object, then there is little need to parse it before returning it as it will get serialized again when being returned, you can instead parse it on the front-end application and perform your logic there.
HttpClient has a method which returns the response body as a string, this is GetStringAsync. With the body returned as string, you can return that directly in your HttpResponseMessage
Here's an example using your HttpClient commented code.
[Route("{id}")]
public async Task<HttpResponseMessage> Get(string id)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri($"https://....../v1/accounts/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// Fetch the response body as a string
// Resource URI added below
string responseContent = await client.GetStringAsync($"{id}/summary");
// Create our response object and set the content to its StringContent
var response =
new HttpResponseMessage(HttpStatusCode.OK) {Content = new StringContent(responseContent)};
// Return our HttpResponseMessage containing our json text
return response;
}
}
If you just want to transfer the json response from another API, you can use code like the following in Web API:
[HttpGet]
[Route("v1/test", Name = "test")]
public HttpResponseMessage GetTest()
{
UriBuilder uriBuilder = new UriBuilder($"https://...../...");
var webRequest = (HttpWebRequest)WebRequest.Create(uriBuilder.Uri);
webRequest.Method = "GET";
webRequest.ContentType = "application/json; charset=utf-8";
webRequest.Accept = "application/json, text/javascript, */*";
using (var jsonResponse = (HttpWebResponse) webRequest.GetResponse())
{
var jsonStream = jsonResponse.GetResponseStream();
MemoryStream ms = new MemoryStream();
jsonStream.CopyTo(ms);
ms.Position = 0;
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StreamContent(ms);
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
return response;
}
}
When the only thing needed is to support authentication or authorization features, i would prefer to use an API manager and not maintain this kind of code myself.

Categories

Resources