Call and consume Web API in winform using C#.net - c#

I am beginner and creating winform application. In which i have to use API for Simple CRUD operation. My client had shared API with me and asked to send data in form of JSON.
API : http://blabla.com/blabla/api/login-valida
KEY : "HelloWorld"
Value : { "email": "user#gmail.com","password": "123456","time": "2015-09-22 10:15:20"}
Response : Login_id
How can i convert data to JSON, call API using POST method and get response?
EDIT
Somewhere on stackoverflow i found this solution
public static void POST(string url, string jsonContent)
{
url="blabla.com/api/blala" + url;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(baseURL);
request.Method = "POST";
System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
Byte[] byteArray = encoding.GetBytes(jsonContent);
request.ContentLength = byteArray.Length;
request.ContentType = #"application/json";
using (Stream dataStream = request.GetRequestStream())
{
dataStream.Write(byteArray, 0, byteArray.Length);
}
long length = 0;
try
{
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
length = response.ContentLength;
}
}
catch
{
throw;
}
}
//on my login button click
private void btnLogin_Click(object sender, EventArgs e)
{
CallAPI.POST("login-validate", "{ \"email\":" + txtUserName.Text + " ,\"password\":" + txtPassword.Text + ",\"time\": " + DateTime.Now.ToString("yyyy-MM-dd h:mm tt") + "}");
}
I got exception that says "The remote server returned an error: (404) Not Found."

You can take a look at the following docs tutorial:
Call a Web API From a .NET Client
But as an answer, here I will share a quick and short a step by step guide about how to call and consume web API in Windows forms:
Install Package - Install the Microsoft.AspNet.WebApi.Client NuGet package (Web API Client Libraries).
Open Tools menu → NuGet Package Manager → Package Manager Console → In the Package Manager Console window, type the following command:
Install-Package Microsoft.AspNet.WebApi.Client
You can install package by right click on project and choosing Manage NuGet Packages as well.
Set up HttpClient - Create an instance of HttpClient and set up its BaseAddress and DefaultRequestHeaders. For example:
// In the class
static HttpClient client = new HttpClient();
// Put the following code where you want to initialize the class
// It can be the static constructor or a one-time initializer
client.BaseAddress = new Uri("http://localhost:4354/api/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
Send Request - To send the requests, you can use the following methods of the HttpClient:
GET: GetAsync, GetStringAsync, GetByteArrayAsync, GetStreamAsync
POST: PostAsync, PostAsJsonAsync, PostAsXmlAsync
PUT: PutAsync, PutAsJsonAsync, PutAsXmlAsync
DELETE: DeleteAsync
Another HTTP method: Send
Note: To set the URL of the request for the methods, keep in mind, since you have specified the base URL when you defined the client, then here for these methods, just pass path, route values and query strings, for example:
// Assuming http://localhost:4354/api/ as BaseAddress
var response = await client.GetAsync("products");
or
// Assuming http://localhost:4354/api/ as BaseAddress
var product = new Product() { Name = "P1", Price = 100, Category = "C1" };
var response = await client.PostAsJsonAsync("products", product);
Get the Response
To get the response, if you have used methods like GetStringAsync, then you have the response as string and it's enough to parse the response. If the response is a Json content which you know, you can easily use JsonConvert class of Newtonsoft.Json package to parse it. For example:
// Assuming http://localhost:4354/api/ as BaseAddress
var response = await client.GetStringAsync("product");
var data = JsonConvert.DeserializeObject<List<Product>>(response);
this.productBindingSource.DataSource = data;
If you have used methods like GetAsync or PostAsJsonAsync and you have an HttpResponseMessage then you can use ReadAsAsync, ReadAsByteArrayAsync, ReadAsStreamAsync, `ReadAsStringAsync, for example:
// Assuming http://localhost:4354/api/ as BaseAddress
var response = await client.GetAsync("products");
var data = await response.Content.ReadAsAsync<IEnumerable<Product>>();
this.productBindingSource.DataSource = data;
Performance Tip
HttpClient is a type that is meant to be created once and then shared. So don't try to put it in a using block every time that you want to use it. Instead, create an instance of the class and share it through a static member. To read more about this, take a look at Improper Instantiation antipattern
Design Tip
Try to avoid mixing the Web API related code with your application logic. For example let's say you have a product Web API service. Then to use it, first define an IProductServieClient interface, then as an implementation put all the WEB API logic inside the ProductWebAPIClientService which you implement to contain codes to interact with WEB API. Your application should rely on IProductServieClient. (SOLID Principles, Dependency Inversion).

Just use the following library.
https://www.nuget.org/packages/RestSharp
GitHub Project: https://github.com/restsharp/RestSharp
Sample Code::
public Customer GetCustomerDetailsByCustomerId(int id)
{
var client = new RestClient("http://localhost:3000/Api/GetCustomerDetailsByCustomerId/" + id);
var request = new RestRequest(Method.GET);
request.AddHeader("X-Token-Key", "dsds-sdsdsds-swrwerfd-dfdfd");
IRestResponse response = client.Execute(request);
var content = response.Content; // raw content as string
dynamic json = JsonConvert.DeserializeObject(content);
JObject customerObjJson = json.CustomerObj;
var customerObj = customerObjJson.ToObject<Customer>();
return customerObj;
}

Use Json.Net to convert data into JSON
Use WebClient to POST data

Use This code:
var client = new HttpClient();
client.BaseAddress = new Uri("http://www.mywebsite.com");
var request = new HttpRequestMessage(HttpMethod.Post, "/path/to/post/to");
var keyValues = new List<KeyValuePair<string, string>>();
keyValues.Add(new KeyValuePair<string, string>("site", "http://www.google.com"));
keyValues.Add(new KeyValuePair<string, string>("content", "This is some content"));
request.Content = new FormUrlEncodedContent(keyValues);
var response = await client.SendAsync(request);

Here is another example using an online REST service (https://northwind.vercel.app) which allows interaction with Northwind API.
This example uses HttpClient and JsonConvert to get or post data. Here is a very quick example:
Install Newtonsoft.Json nuget package. And add the following using statements to your form:
using System.Net.Http;
using Newtonsoft.Json
Define an instance of the HttpClient, at class level:
private static HttpClient client = new HttpClient();
To send a GET request, for example getting list of all data:
var url = "https://northwind.vercel.app/api/categories";
var response = await client.GetAsync(url);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
var content = await response.Content.ReadAsStringAsync();
var categories = JsonConvert.DeserializeObject<List<Category>>(content);
dataGridView1.DataSource = categories;
}
You can also use other overloads of Get, like GetStringAsync, GetStreamAsync, and etc. But GetAsync is a more generic method allowing you to get the status code as well.
To send a POST request, for example posting a new data:
var url = "https://northwind.vercel.app/api/categories";
var data = new Category() { Name = "Lorem", Description = "Ipsum" };
var jsonData = Newtonsoft.Json.JsonConvert.SerializeObject(data);
var requestContent = new StringContent(jsonData, Encoding.Unicode, "application/json");
var response = await client.PostAsync(url, requestContent);
if (response.StatusCode == System.Net.HttpStatusCode.Created)
{
var content = await response.Content.ReadAsStringAsync();
var createdCategory = JsonConvert.DeserializeObject<Category>(content);
MessageBox.Show(createdCategory.Id.ToString())
}
To learn more and see some best practices or see an example without JsonConvert, see my other post.

Related

Get Data of online API

I want to download data of this website into a json file but as I am quite new to coding with C# I cant manage to get the data. I want to get Data of https://discosweb.esoc.esa.int/api/objects the authorization via token works but I dont know how I can send a request so the server gives me a json back and I cant find a solution online. I cant give you a screenshot of the API because you have to be logged in to see it. Plz ask me for detailed information if you can help me. Thank you realy for trying.
The code I want to run is here.
class Program
{
static HttpClient client = new HttpClient();
static void Main(string[] args)
{
client.BaseAddress = new Uri("https://discosweb.esoc.esa.int");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/vnd.api+json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("my_token");
var httpRequest = (HttpWebRequest)WebRequest.Create(client.BaseAddress);
var httpResponse = (HttpWebResponse)httpRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var streamReaderResult = streamReader.ReadToEnd();
}
Console.WriteLine("Status https://discosweb.esoc.esa.int : " + httpResponse.StatusCode);
}
}
Try this
var url = "https://discosweb.esoc.esa.int/api/objects";
var httpRequest = (HttpWebRequest)WebRequest.Create(url);
httpRequest.Method = "POST";
httpRequest.Headers["Authorization"] = "Basic XXXx";
httpRequest.ContentType = "";
httpRequest.Headers["Content-Length"] = "0";
var httpResponse = (HttpWebResponse)httpRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}
Console.WriteLine(httpResponse.StatusCode);
Where XXXx is user:password in base64.
Here is a basic implementation for making that API call to get the JSON result. You will need to parse that JSON into something other than a string but I'll assume you can handle that part.
This uses System.Net.HttpClient which is the modern HTTP api provided by .NET. Its operations are async so hopefully your code is or can be written to properly await async operations.
//Someplace convenient, create a shared HttpClient to avoid
//creating and disposing for each request.
HttpClient client = new HttpClient();
string data = await GetObjects(client);
//Example implementation
public async Task<string> GetObjects(HttpClient client)
{
string url = "https://discosweb.esoc.esa.int/api/objects";
using (HttpRequestMessage msg = new HttpRequestMessage(HttpMethod.Get, url))
{
msg.Headers.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "your personal access token here");
using (var result = await client.SendAsync(msg))
{
string content = await result.Content.ReadAsStringAsync();
return content;
}
}
}
While I may be a month late, I've actually developed an SDK for this particular API.
So, if you use this SDK it's pretty simple to do what you want. You can essentially forget about handling anything HTTP related, my SDK abstracts all of that away.
For example, to fetch Sputnik's data (which has an ID of 1) you'd run.
HttpClient innerClient = new();
innerClient.BaseAddress = "https://discosweb.esoc.esa.int/api/"
innerClient.DefaultRequestHeaders.Authorization = new("bearer", yourApiKey);
DiscosClient client = new();
DiscosObject sputnik = await client.GetSingle<DiscosObject>("1");
If you're using ASP.NET, there's a set of DI extensions that can actually set it all up for you, so you can skip the first three lines.
If you do choose to use it, please let me know, as it would be nice knowing my SDK is getting some use. If you have any issues, please just reach out through the GitHub issues page and I'll try to help!

Trying to pass several headers in get request [duplicate]

I'm trying to set the Content-Type header of an HttpClient object as required by an API I am calling.
I tried setting the Content-Type like below:
using (var httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri("http://example.com/");
httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
httpClient.DefaultRequestHeaders.Add("Content-Type", "application/json");
// ...
}
It allows me to add the Accept header but when I try to add Content-Type it throws the following exception:
Misused header name. Make sure request headers are used with
HttpRequestMessage, response headers with HttpResponseMessage, and
content headers with HttpContent objects.
How can I set the Content-Type header in a HttpClient request?
The content type is a header of the content, not of the request, which is why this is failing. AddWithoutValidation as suggested by Robert Levy may work, but you can also set the content type when creating the request content itself (note that the code snippet adds application/json in two places-for Accept and Content-Type headers):
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://example.com/");
client.DefaultRequestHeaders
.Accept
.Add(new MediaTypeWithQualityHeaderValue("application/json"));//ACCEPT header
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "relativeAddress");
request.Content = new StringContent("{\"name\":\"John Doe\",\"age\":33}",
Encoding.UTF8,
"application/json");//CONTENT-TYPE header
client.SendAsync(request)
.ContinueWith(responseTask =>
{
Console.WriteLine("Response: {0}", responseTask.Result);
});
For those who didn't see Johns comment to carlos solution ...
req.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
If you don't mind a small library dependency, Flurl.Http [disclosure: I'm the author] makes this uber-simple. Its PostJsonAsync method takes care of both serializing the content and setting the content-type header, and ReceiveJson deserializes the response. If the accept header is required you'll need to set that yourself, but Flurl provides a pretty clean way to do that too:
using Flurl.Http;
var result = await "http://example.com/"
.WithHeader("Accept", "application/json")
.PostJsonAsync(new { ... })
.ReceiveJson<TResult>();
Flurl uses HttpClient and Json.NET under the hood, and it's a PCL so it'll work on a variety of platforms.
PM> Install-Package Flurl.Http
try to use TryAddWithoutValidation
var client = new HttpClient();
client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");
.Net tries to force you to obey certain standards, namely that the Content-Type header can only be specified on requests that have content (e.g. POST, PUT, etc.). Therefore, as others have indicated, the preferred way to set the Content-Type header is through the HttpContent.Headers.ContentType property.
With that said, certain APIs (such as the LiquidFiles Api, as of 2016-12-19) requires setting the Content-Type header for a GET request. .Net will not allow setting this header on the request itself -- even using TryAddWithoutValidation. Furthermore, you cannot specify a Content for the request -- even if it is of zero-length. The only way I could seem to get around this was to resort to reflection. The code (in case some else needs it) is
var field = typeof(System.Net.Http.Headers.HttpRequestHeaders)
.GetField("invalidHeaders", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static)
?? typeof(System.Net.Http.Headers.HttpRequestHeaders)
.GetField("s_invalidHeaders", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
if (field != null)
{
var invalidFields = (HashSet<string>)field.GetValue(null);
invalidFields.Remove("Content-Type");
}
_client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "text/xml");
Edit:
As noted in the comments, this field has different names in different versions of the dll. In the source code on GitHub, the field is currently named s_invalidHeaders. The example has been modified to account for this per the suggestion of #David Thompson.
For those who troubled with charset
I had very special case that the service provider didn't accept charset, and they refuse to change the substructure to allow it...
Unfortunately HttpClient was setting the header automatically through StringContent, and no matter if you pass null or Encoding.UTF8, it will always set the charset...
Today i was on the edge to change the sub-system; moving from HttpClient to anything else, that something came to my mind..., why not use reflection to empty out the "charset"? ...
And before i even try it, i thought of a way, "maybe I can change it after initialization", and that worked.
Here's how you can set the exact "application/json" header without "; charset=utf-8".
var jsonRequest = JsonSerializeObject(req, options); // Custom function that parse object to string
var stringContent = new StringContent(jsonRequest, Encoding.UTF8, "application/json");
stringContent.Headers.ContentType.CharSet = null;
return stringContent;
Note: The null value in following won't work, and append "; charset=utf-8"
return new StringContent(jsonRequest, null, "application/json");
EDIT
#DesertFoxAZ suggests that also the following code can be used and works fine. (didn't test it myself, if it work's rate and credit him in comments)
stringContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
Some extra information about .NET Core (after reading erdomke's post about setting a private field to supply the content-type on a request that doesn't have content)...
After debugging my code, I can't see the private field to set via reflection - so I thought I'd try to recreate the problem.
I have tried the following code using .Net 4.6:
HttpRequestMessage httpRequest = new HttpRequestMessage(HttpMethod.Get, #"myUrl");
httpRequest.Content = new StringContent(string.Empty, Encoding.UTF8, "application/json");
HttpClient client = new HttpClient();
Task<HttpResponseMessage> response = client.SendAsync(httpRequest); //I know I should have used async/await here!
var result = response.Result;
And, as expected, I get an aggregate exception with the content "Cannot send a content-body with this verb-type."
However, if i do the same thing with .NET Core (1.1) - I don't get an exception. My request was quite happily answered by my server application, and the content-type was picked up.
I was pleasantly surprised about that, and I hope it helps someone!
Call AddWithoutValidation instead of Add (see this MSDN link).
Alternatively, I'm guessing the API you are using really only requires this for POST or PUT requests (not ordinary GET requests). In that case, when you call HttpClient.PostAsync and pass in an HttpContent, set this on the Headers property of that HttpContent object.
The trick is that you can just set all kinds of headers like:
HttpRequestMessage request = new HttpRequestMessage();
request.Headers.Add("Accept-Language", "en"); //works OK
but not any header. For example:
request.Headers.Add("Content-Type", "application/json");//wrong
will raise the run-time exception Misused header name. It may seem that this will work:
request.Headers.Add(
HttpRequestHeader.ContentType.ToString(), //useless
"application/json"
);
but this gives a useless header named ContentType, without the hyphen. Header names are not case-sensitive, but are very hyphen-sensitive.
The solution is to declare the encoding and type of the body when adding the body to the Content part of the http request:
string Body = "...";
request.Content =
new StringContent(Body, Encoding.UTF8, "application/json");
Only then the applicable http header is automatically added to the request:
Content-Type: application/json; charset=utf-8
It was hard to find this out, with Fiddler, on a machine without a proxy server. Visual Studio used to have a Network Tool where you could inspect all headers, but only in version 2015, not in newer versions 2017 or 2022. If you use the debugger to inspect request.Headers, you will not find the header added automagically by StringContent().
var content = new JsonContent();
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
content.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("charset", "utf-8"));
content.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("IEEE754Compatible", "true"));
It's all what you need.
With using Newtonsoft.Json, if you need a content as json string.
public class JsonContent : HttpContent
{
private readonly MemoryStream _stream = new MemoryStream();
~JsonContent()
{
_stream.Dispose();
}
public JsonContent(object value)
{
Headers.ContentType = new MediaTypeHeaderValue("application/json");
using (var contexStream = new MemoryStream())
using (var jw = new JsonTextWriter(new StreamWriter(contexStream)) { Formatting = Formatting.Indented })
{
var serializer = new JsonSerializer();
serializer.Serialize(jw, value);
jw.Flush();
contexStream.Position = 0;
contexStream.WriteTo(_stream);
}
_stream.Position = 0;
}
private JsonContent(string content)
{
Headers.ContentType = new MediaTypeHeaderValue("application/json");
using (var contexStream = new MemoryStream())
using (var sw = new StreamWriter(contexStream))
{
sw.Write(content);
sw.Flush();
contexStream.Position = 0;
contexStream.WriteTo(_stream);
}
_stream.Position = 0;
}
protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
{
return _stream.CopyToAsync(stream);
}
protected override bool TryComputeLength(out long length)
{
length = _stream.Length;
return true;
}
public static HttpContent FromFile(string filepath)
{
var content = File.ReadAllText(filepath);
return new JsonContent(content);
}
public string ToJsonString()
{
return Encoding.ASCII.GetString(_stream.GetBuffer(), 0, _stream.GetBuffer().Length).Trim();
}
}
It appears that Microsoft tries to force the developers to follow their standards, without even giving any options or settings to do otherwise, which is really a shame especially given that this is a client and we are dictated by the server side requirements, especially given that Microsoft server side frameworks themselves require it!
So basically Microsoft tries to force us good habits when connecting to their server technologies that force us non good habits...
If anyone from Microsoft is reading this, then please fix it...
Either way for anyone that needs the content-type header for Get etc., while in an older .Net version it is possible to use the answer of #erdomke at https://stackoverflow.com/a/41231353/640195 this unfortunately no longer works in the newer .Net core versions.
The following code has been tested to work with .Net core 3.1 and from the source code on GitHub it looks like it should work with newer .Net versions as well.
private void FixContentTypeHeaders()
{
var assembly = typeof(System.Net.Http.Headers.HttpRequestHeaders).Assembly;
var assemblyTypes = assembly.GetTypes();
var knownHeaderType = assemblyTypes.FirstOrDefault(n => n.Name == "KnownHeader");
var headerTypeField = knownHeaderType?
.GetFields(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
.FirstOrDefault(n => n.Name.Contains("HeaderType"));
if (headerTypeField is null) return;
var headerTypeFieldType = headerTypeField.FieldType;
var newValue = Enum.Parse(headerTypeFieldType, "All");
var knownHeadersType = assemblyTypes.FirstOrDefault(n => n.Name == "KnownHeaders");
var contentTypeObj = knownHeadersType.GetFields().FirstOrDefault(n => n.Name == "ContentType").GetValue(null);
if (contentTypeObj is null) return;
headerTypeField.SetValue(contentTypeObj, newValue);
}
You can use this it will be work!
HttpRequestMessage msg = new HttpRequestMessage(HttpMethod.Get,"URL");
msg.Content = new StringContent(string.Empty, Encoding.UTF8, "application/json");
HttpResponseMessage response = await _httpClient.SendAsync(msg);
response.EnsureSuccessStatusCode();
string json = await response.Content.ReadAsStringAsync();
Ok, it's not HTTPClient but if u can use it, WebClient is quite easy:
using (var client = new System.Net.WebClient())
{
client.Headers.Add("Accept", "application/json");
client.Headers.Add("Content-Type", "application/json; charset=utf-8");
client.DownloadString(...);
}
try to use HttpClientFactory
services.AddSingleton<WebRequestXXX>()
.AddHttpClient<WebRequestXXX>("ClientX", config =>
{
config.BaseAddress = new System.Uri("https://jsonplaceholder.typicode.com");
config.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
config.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");
});
======================
public class WebRequestXXXX
{
private readonly IHttpClientFactory _httpClientFactory;
public WebRequestXXXX(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
public List<Posts> GetAllPosts()
{
using (var _client = _httpClientFactory.CreateClient("ClientX"))
{
var response = _client.GetAsync("/posts").Result;
if (response.IsSuccessStatusCode)
{
var itemString = response.Content.ReadAsStringAsync().Result;
var itemJson = System.Text.Json.JsonSerializer.Deserialize<List<Posts>>(itemString,
new System.Text.Json.JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
});
return itemJson;
}
else
{
return new List<Posts>();
}
}
}
}
I got the answer whith RestSharp:
private async Task<string> GetAccessTokenAsync()
{
var client = new RestClient(_baseURL);
var request = new RestRequest("auth/v1/login", Method.POST, DataFormat.Json);
request.AddHeader("Content-Type", "application/json");
request.AddHeader("x-api-key", _apiKey);
request.AddHeader("Accept-Language", "br");
request.AddHeader("x-client-tenant", "1");
...
}
It worked for me.
You need to do it like this:
HttpContent httpContent = new StringContent(#"{ the json string }");
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage message = client.PostAsync(#"{url}", httpContent).Result;
For those wanting to set the Content-Type to Json specifically, you can use the extension method PostAsJsonAsync.
using System.Net.Http.Json; //this is needed for PostAsJsonAsync to work
//....
HttpClient client = new HttpClient();
HttpResponseMessage response = await
client.PostAsJsonAsync("http://example.com/" + "relativeAddress",
new
{
name = "John Doe",
age = 33
});
//Do what you need to do with your response
The advantage here is cleaner code and you get to avoid stringified json. More details can be found at: https://learn.microsoft.com/en-us/previous-versions/aspnet/hh944339(v=vs.118)
I find it most simple and easy to understand in the following way:
async Task SendPostRequest()
{
HttpClient client = new HttpClient();
var requestContent = new StringContent(<content>);
requestContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var response = await client.PostAsync(<url>, requestContent);
var responseString = await response.Content.ReadAsStringAsync();
}
...
SendPostRequest().Wait();
I end up having similar issue.
So I discovered that the Software PostMan can generate code when clicking the "Code" button at upper/left corner. From that we can see what going on "under the hood" and the HTTP call is generated in many code language; curl command, C# RestShart, java, nodeJs, ...
That helped me a lot and instead of using .Net base HttpClient I ended up using RestSharp nuget package.
Hope that can help someone else!
Api returned
"Unsupported Media Type","status":415
Adding ContentType to the jsonstring did the magic and this is my script working 100% as of today
using (var client = new HttpClient())
{
var endpoint = "api/endpoint;
var userName = "xxxxxxxxxx";
var passwd = "xxxxxxxxxx";
var content = new StringContent(jsonString, Encoding.UTF8, "application/json");
var authToken = Encoding.ASCII.GetBytes($"{userName}:{passwd}");
client.BaseAddress = new Uri("https://example.com/");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(authToken));
HttpResponseMessage response = await client.PostAsync(endpoint, content);
if (response.IsSuccessStatusCode)
{
// Get the URI of the created resource.
Uri returnUrl = response.Headers.Location;
Console.WriteLine(returnUrl);
}
string responseBody = await response.Content.ReadAsStringAsync();
return responseBody;
}
For my scenario, a third-party API was creating the HttpRequestMessage, so I was not able to use the top-voted answers to resolve the issue. And I didn't like the idea of messing with reflection so the other answers didn't work either.
Instead, I extended from AndroidMessageHandler and used this new class as a parameter to HttpClient. AndroidMessageHandler contains the method SendAsync which can be overridden in order to make changes to the HttpRequestMessage object before it is sent. If you don't have access to the Android Xamarin libaries, you may be able to figure something out with HttpMessageHandler.
public class XamarinHttpMessageHandler : global::Xamarin.Android.Net.AndroidMessageHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
// Here I make check that I'm only modifying a specific request
// and not all of them.
if (request.RequestUri != null && request.RequestUri.AbsolutePath.EndsWith("download") && request.Content != null)
{
request.Content.Headers.Add("Content-Type", "text/plain");
}
return base.SendAsync(request, cancellationToken);
}
}
Then to use:
var client = new HttpClient(new XamarinHttpMessageHandler());
So if you're trying to do a /$batch OData request like this Microsoft article demonstrates where you're supposed to have a Content-Type header like:
Content-Type: multipart/mixed;boundary=batch_d3bcb804-ee77-4921-9a45-761f98d32029
string headerValue = "multipart/mixed;boundary=batch_d3bcb804-ee77-4921-9a45-761f98d32029";
//You need to set it like thus:
request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse(headerValue);
Again, the magic you need is: MediaTypeHeaderValue.Parse(...)
stringContent.Headers.ContentType = new MediaTypeHeaderValue(contentType);
And 🎉 YES! 🎉 ... that cleared up the problem with ATS REST API: SharedKey works now! 😄 👍 🍻
Source: https://github.com/dotnet/runtime/issues/17036#issuecomment-212046628

How to add the header Xamarin Forms using System.Net.Http; [duplicate]

I'm trying to set the Content-Type header of an HttpClient object as required by an API I am calling.
I tried setting the Content-Type like below:
using (var httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri("http://example.com/");
httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
httpClient.DefaultRequestHeaders.Add("Content-Type", "application/json");
// ...
}
It allows me to add the Accept header but when I try to add Content-Type it throws the following exception:
Misused header name. Make sure request headers are used with
HttpRequestMessage, response headers with HttpResponseMessage, and
content headers with HttpContent objects.
How can I set the Content-Type header in a HttpClient request?
The content type is a header of the content, not of the request, which is why this is failing. AddWithoutValidation as suggested by Robert Levy may work, but you can also set the content type when creating the request content itself (note that the code snippet adds application/json in two places-for Accept and Content-Type headers):
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://example.com/");
client.DefaultRequestHeaders
.Accept
.Add(new MediaTypeWithQualityHeaderValue("application/json"));//ACCEPT header
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "relativeAddress");
request.Content = new StringContent("{\"name\":\"John Doe\",\"age\":33}",
Encoding.UTF8,
"application/json");//CONTENT-TYPE header
client.SendAsync(request)
.ContinueWith(responseTask =>
{
Console.WriteLine("Response: {0}", responseTask.Result);
});
For those who didn't see Johns comment to carlos solution ...
req.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
If you don't mind a small library dependency, Flurl.Http [disclosure: I'm the author] makes this uber-simple. Its PostJsonAsync method takes care of both serializing the content and setting the content-type header, and ReceiveJson deserializes the response. If the accept header is required you'll need to set that yourself, but Flurl provides a pretty clean way to do that too:
using Flurl.Http;
var result = await "http://example.com/"
.WithHeader("Accept", "application/json")
.PostJsonAsync(new { ... })
.ReceiveJson<TResult>();
Flurl uses HttpClient and Json.NET under the hood, and it's a PCL so it'll work on a variety of platforms.
PM> Install-Package Flurl.Http
try to use TryAddWithoutValidation
var client = new HttpClient();
client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");
.Net tries to force you to obey certain standards, namely that the Content-Type header can only be specified on requests that have content (e.g. POST, PUT, etc.). Therefore, as others have indicated, the preferred way to set the Content-Type header is through the HttpContent.Headers.ContentType property.
With that said, certain APIs (such as the LiquidFiles Api, as of 2016-12-19) requires setting the Content-Type header for a GET request. .Net will not allow setting this header on the request itself -- even using TryAddWithoutValidation. Furthermore, you cannot specify a Content for the request -- even if it is of zero-length. The only way I could seem to get around this was to resort to reflection. The code (in case some else needs it) is
var field = typeof(System.Net.Http.Headers.HttpRequestHeaders)
.GetField("invalidHeaders", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static)
?? typeof(System.Net.Http.Headers.HttpRequestHeaders)
.GetField("s_invalidHeaders", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
if (field != null)
{
var invalidFields = (HashSet<string>)field.GetValue(null);
invalidFields.Remove("Content-Type");
}
_client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "text/xml");
Edit:
As noted in the comments, this field has different names in different versions of the dll. In the source code on GitHub, the field is currently named s_invalidHeaders. The example has been modified to account for this per the suggestion of #David Thompson.
For those who troubled with charset
I had very special case that the service provider didn't accept charset, and they refuse to change the substructure to allow it...
Unfortunately HttpClient was setting the header automatically through StringContent, and no matter if you pass null or Encoding.UTF8, it will always set the charset...
Today i was on the edge to change the sub-system; moving from HttpClient to anything else, that something came to my mind..., why not use reflection to empty out the "charset"? ...
And before i even try it, i thought of a way, "maybe I can change it after initialization", and that worked.
Here's how you can set the exact "application/json" header without "; charset=utf-8".
var jsonRequest = JsonSerializeObject(req, options); // Custom function that parse object to string
var stringContent = new StringContent(jsonRequest, Encoding.UTF8, "application/json");
stringContent.Headers.ContentType.CharSet = null;
return stringContent;
Note: The null value in following won't work, and append "; charset=utf-8"
return new StringContent(jsonRequest, null, "application/json");
EDIT
#DesertFoxAZ suggests that also the following code can be used and works fine. (didn't test it myself, if it work's rate and credit him in comments)
stringContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
Some extra information about .NET Core (after reading erdomke's post about setting a private field to supply the content-type on a request that doesn't have content)...
After debugging my code, I can't see the private field to set via reflection - so I thought I'd try to recreate the problem.
I have tried the following code using .Net 4.6:
HttpRequestMessage httpRequest = new HttpRequestMessage(HttpMethod.Get, #"myUrl");
httpRequest.Content = new StringContent(string.Empty, Encoding.UTF8, "application/json");
HttpClient client = new HttpClient();
Task<HttpResponseMessage> response = client.SendAsync(httpRequest); //I know I should have used async/await here!
var result = response.Result;
And, as expected, I get an aggregate exception with the content "Cannot send a content-body with this verb-type."
However, if i do the same thing with .NET Core (1.1) - I don't get an exception. My request was quite happily answered by my server application, and the content-type was picked up.
I was pleasantly surprised about that, and I hope it helps someone!
Call AddWithoutValidation instead of Add (see this MSDN link).
Alternatively, I'm guessing the API you are using really only requires this for POST or PUT requests (not ordinary GET requests). In that case, when you call HttpClient.PostAsync and pass in an HttpContent, set this on the Headers property of that HttpContent object.
The trick is that you can just set all kinds of headers like:
HttpRequestMessage request = new HttpRequestMessage();
request.Headers.Add("Accept-Language", "en"); //works OK
but not any header. For example:
request.Headers.Add("Content-Type", "application/json");//wrong
will raise the run-time exception Misused header name. It may seem that this will work:
request.Headers.Add(
HttpRequestHeader.ContentType.ToString(), //useless
"application/json"
);
but this gives a useless header named ContentType, without the hyphen. Header names are not case-sensitive, but are very hyphen-sensitive.
The solution is to declare the encoding and type of the body when adding the body to the Content part of the http request:
string Body = "...";
request.Content =
new StringContent(Body, Encoding.UTF8, "application/json");
Only then the applicable http header is automatically added to the request:
Content-Type: application/json; charset=utf-8
It was hard to find this out, with Fiddler, on a machine without a proxy server. Visual Studio used to have a Network Tool where you could inspect all headers, but only in version 2015, not in newer versions 2017 or 2022. If you use the debugger to inspect request.Headers, you will not find the header added automagically by StringContent().
var content = new JsonContent();
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
content.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("charset", "utf-8"));
content.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("IEEE754Compatible", "true"));
It's all what you need.
With using Newtonsoft.Json, if you need a content as json string.
public class JsonContent : HttpContent
{
private readonly MemoryStream _stream = new MemoryStream();
~JsonContent()
{
_stream.Dispose();
}
public JsonContent(object value)
{
Headers.ContentType = new MediaTypeHeaderValue("application/json");
using (var contexStream = new MemoryStream())
using (var jw = new JsonTextWriter(new StreamWriter(contexStream)) { Formatting = Formatting.Indented })
{
var serializer = new JsonSerializer();
serializer.Serialize(jw, value);
jw.Flush();
contexStream.Position = 0;
contexStream.WriteTo(_stream);
}
_stream.Position = 0;
}
private JsonContent(string content)
{
Headers.ContentType = new MediaTypeHeaderValue("application/json");
using (var contexStream = new MemoryStream())
using (var sw = new StreamWriter(contexStream))
{
sw.Write(content);
sw.Flush();
contexStream.Position = 0;
contexStream.WriteTo(_stream);
}
_stream.Position = 0;
}
protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
{
return _stream.CopyToAsync(stream);
}
protected override bool TryComputeLength(out long length)
{
length = _stream.Length;
return true;
}
public static HttpContent FromFile(string filepath)
{
var content = File.ReadAllText(filepath);
return new JsonContent(content);
}
public string ToJsonString()
{
return Encoding.ASCII.GetString(_stream.GetBuffer(), 0, _stream.GetBuffer().Length).Trim();
}
}
It appears that Microsoft tries to force the developers to follow their standards, without even giving any options or settings to do otherwise, which is really a shame especially given that this is a client and we are dictated by the server side requirements, especially given that Microsoft server side frameworks themselves require it!
So basically Microsoft tries to force us good habits when connecting to their server technologies that force us non good habits...
If anyone from Microsoft is reading this, then please fix it...
Either way for anyone that needs the content-type header for Get etc., while in an older .Net version it is possible to use the answer of #erdomke at https://stackoverflow.com/a/41231353/640195 this unfortunately no longer works in the newer .Net core versions.
The following code has been tested to work with .Net core 3.1 and from the source code on GitHub it looks like it should work with newer .Net versions as well.
private void FixContentTypeHeaders()
{
var assembly = typeof(System.Net.Http.Headers.HttpRequestHeaders).Assembly;
var assemblyTypes = assembly.GetTypes();
var knownHeaderType = assemblyTypes.FirstOrDefault(n => n.Name == "KnownHeader");
var headerTypeField = knownHeaderType?
.GetFields(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
.FirstOrDefault(n => n.Name.Contains("HeaderType"));
if (headerTypeField is null) return;
var headerTypeFieldType = headerTypeField.FieldType;
var newValue = Enum.Parse(headerTypeFieldType, "All");
var knownHeadersType = assemblyTypes.FirstOrDefault(n => n.Name == "KnownHeaders");
var contentTypeObj = knownHeadersType.GetFields().FirstOrDefault(n => n.Name == "ContentType").GetValue(null);
if (contentTypeObj is null) return;
headerTypeField.SetValue(contentTypeObj, newValue);
}
You can use this it will be work!
HttpRequestMessage msg = new HttpRequestMessage(HttpMethod.Get,"URL");
msg.Content = new StringContent(string.Empty, Encoding.UTF8, "application/json");
HttpResponseMessage response = await _httpClient.SendAsync(msg);
response.EnsureSuccessStatusCode();
string json = await response.Content.ReadAsStringAsync();
Ok, it's not HTTPClient but if u can use it, WebClient is quite easy:
using (var client = new System.Net.WebClient())
{
client.Headers.Add("Accept", "application/json");
client.Headers.Add("Content-Type", "application/json; charset=utf-8");
client.DownloadString(...);
}
try to use HttpClientFactory
services.AddSingleton<WebRequestXXX>()
.AddHttpClient<WebRequestXXX>("ClientX", config =>
{
config.BaseAddress = new System.Uri("https://jsonplaceholder.typicode.com");
config.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
config.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");
});
======================
public class WebRequestXXXX
{
private readonly IHttpClientFactory _httpClientFactory;
public WebRequestXXXX(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
public List<Posts> GetAllPosts()
{
using (var _client = _httpClientFactory.CreateClient("ClientX"))
{
var response = _client.GetAsync("/posts").Result;
if (response.IsSuccessStatusCode)
{
var itemString = response.Content.ReadAsStringAsync().Result;
var itemJson = System.Text.Json.JsonSerializer.Deserialize<List<Posts>>(itemString,
new System.Text.Json.JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
});
return itemJson;
}
else
{
return new List<Posts>();
}
}
}
}
I got the answer whith RestSharp:
private async Task<string> GetAccessTokenAsync()
{
var client = new RestClient(_baseURL);
var request = new RestRequest("auth/v1/login", Method.POST, DataFormat.Json);
request.AddHeader("Content-Type", "application/json");
request.AddHeader("x-api-key", _apiKey);
request.AddHeader("Accept-Language", "br");
request.AddHeader("x-client-tenant", "1");
...
}
It worked for me.
You need to do it like this:
HttpContent httpContent = new StringContent(#"{ the json string }");
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage message = client.PostAsync(#"{url}", httpContent).Result;
For those wanting to set the Content-Type to Json specifically, you can use the extension method PostAsJsonAsync.
using System.Net.Http.Json; //this is needed for PostAsJsonAsync to work
//....
HttpClient client = new HttpClient();
HttpResponseMessage response = await
client.PostAsJsonAsync("http://example.com/" + "relativeAddress",
new
{
name = "John Doe",
age = 33
});
//Do what you need to do with your response
The advantage here is cleaner code and you get to avoid stringified json. More details can be found at: https://learn.microsoft.com/en-us/previous-versions/aspnet/hh944339(v=vs.118)
I find it most simple and easy to understand in the following way:
async Task SendPostRequest()
{
HttpClient client = new HttpClient();
var requestContent = new StringContent(<content>);
requestContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var response = await client.PostAsync(<url>, requestContent);
var responseString = await response.Content.ReadAsStringAsync();
}
...
SendPostRequest().Wait();
I end up having similar issue.
So I discovered that the Software PostMan can generate code when clicking the "Code" button at upper/left corner. From that we can see what going on "under the hood" and the HTTP call is generated in many code language; curl command, C# RestShart, java, nodeJs, ...
That helped me a lot and instead of using .Net base HttpClient I ended up using RestSharp nuget package.
Hope that can help someone else!
Api returned
"Unsupported Media Type","status":415
Adding ContentType to the jsonstring did the magic and this is my script working 100% as of today
using (var client = new HttpClient())
{
var endpoint = "api/endpoint;
var userName = "xxxxxxxxxx";
var passwd = "xxxxxxxxxx";
var content = new StringContent(jsonString, Encoding.UTF8, "application/json");
var authToken = Encoding.ASCII.GetBytes($"{userName}:{passwd}");
client.BaseAddress = new Uri("https://example.com/");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(authToken));
HttpResponseMessage response = await client.PostAsync(endpoint, content);
if (response.IsSuccessStatusCode)
{
// Get the URI of the created resource.
Uri returnUrl = response.Headers.Location;
Console.WriteLine(returnUrl);
}
string responseBody = await response.Content.ReadAsStringAsync();
return responseBody;
}
For my scenario, a third-party API was creating the HttpRequestMessage, so I was not able to use the top-voted answers to resolve the issue. And I didn't like the idea of messing with reflection so the other answers didn't work either.
Instead, I extended from AndroidMessageHandler and used this new class as a parameter to HttpClient. AndroidMessageHandler contains the method SendAsync which can be overridden in order to make changes to the HttpRequestMessage object before it is sent. If you don't have access to the Android Xamarin libaries, you may be able to figure something out with HttpMessageHandler.
public class XamarinHttpMessageHandler : global::Xamarin.Android.Net.AndroidMessageHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
// Here I make check that I'm only modifying a specific request
// and not all of them.
if (request.RequestUri != null && request.RequestUri.AbsolutePath.EndsWith("download") && request.Content != null)
{
request.Content.Headers.Add("Content-Type", "text/plain");
}
return base.SendAsync(request, cancellationToken);
}
}
Then to use:
var client = new HttpClient(new XamarinHttpMessageHandler());
So if you're trying to do a /$batch OData request like this Microsoft article demonstrates where you're supposed to have a Content-Type header like:
Content-Type: multipart/mixed;boundary=batch_d3bcb804-ee77-4921-9a45-761f98d32029
string headerValue = "multipart/mixed;boundary=batch_d3bcb804-ee77-4921-9a45-761f98d32029";
//You need to set it like thus:
request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse(headerValue);
Again, the magic you need is: MediaTypeHeaderValue.Parse(...)
stringContent.Headers.ContentType = new MediaTypeHeaderValue(contentType);
And 🎉 YES! 🎉 ... that cleared up the problem with ATS REST API: SharedKey works now! 😄 👍 🍻
Source: https://github.com/dotnet/runtime/issues/17036#issuecomment-212046628

Connecting to PHP api from c# project

I have an api
http://cbastest.cadvilpos.com/module/posmodule/customapi
with parameters
{
"action":4,
"device_token": "3e8ea119a90ee6d2",
"key":"9475962085b3a1b8c475d52.95782804",
"shop":1,
"language":1
}
This is working fine in postman. But when I try to connect from c# project its showing an error {"success":0,"error":"Missing the action parameter."}. Please give a working C# code to get the json result.
The code I tried:
var request = (HttpWebRequest)WebRequest.Create("http://cbastest.cadvilpos.com/module/posmodule/customapi");
var postData = "{ 'action':'4', 'device_token':'3e8ea119a90ee6d2','key':'9475962085b3a1b8c475d52.95782804','shop':'1','language':'1'}";
var data = Encoding.ASCII.GetBytes(postData);
request.Method = "POST";
request.ContentType = "application/json";
request.ContentLength = data.Length;
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
var response2 = (HttpWebResponse)request.GetResponse();
var responseString = new StreamReader(response2.GetResponseStream()).ReadToEnd();
You don't need to use a raw HttpWebRequest object to make an HTTP call. HttpClient was introduced in 2012 to allow easy asynchronous HTTP calls.
You could do something as simple as :
var content=new StringContent(postData,Encoding.UTF8, "application/json");
HttpResponseMessage response=await httpClient.PostAsync(url,content);
//Now process the response
if (response.IsSuccessCode)
{
var body=await response.Content.ReadAsStringAsync();
var responseDTO=JsonConvert.DeserializeObject<MyDTO>(body);
}
Instead of building a JSON string by hand you could use a strongly typed class or an anonymous object and serialize it to JSON with JSON.NET :
var data=new {
action=4,
device_token="3e8ea119a90ee6d2",
key = "9475962085b3a1b8c475d52.95782804",
shop=1,
language=1
};
var postData=JsonConvert.SerializeObject(data);
var content=new StringContent(postData,Encoding.UTF8, "application/json");
var response=await httpClient.PostAsync(url,content);
...
You can read a response body in one go as a string, using ReadAsStringAsync or you can get the response stream with ReadAsStreamAsync. You could copy the response data directly to another stream, eg a file or memory stream with HttpContent.CopyToAsync
Check Call a Web API from a .NET Client for more examples. Despite the title, the examples work to call any HTTP/REST API.
The Microsoft.AspNet.WebApi.Client package mentioned in that article is another thing that applies to any call, not just calls to ASP.NET Web API. The extension method PostAsJsonAsync for example, combines serializing and posting a request to a url. Using it, posting the action DTO could be reduced to a single line:
var data=new {
action=4,
device_token="3e8ea119a90ee6d2",
key = "9475962085b3a1b8c475d52.95782804",
shop=1,
language=1
};
var response=await httpClient.PostAsJsonAsync(url,data);
There is a button in Postman that will generate code for the currently defined request. The link is here:
And this is what the code looks like. You'll need to pull in RestSharp from Nuget

HTTP POST Though C#

I want to code an auto bot for an online game (tribalwars.net). I'm learning C# in school, but haven't covered networking yet.
Is it possible to make HTTP POSTs though C#? Can anyone provide an example?
Trivial with System.Net.WebClient:
using(WebClient client = new WebClient()) {
string responseString = client.UploadString(address, requestString);
}
There is also:
UploadData - binary (byte[])
UploadFile - from a file
UploadValues - name/value pairs (like a form)
You can use System.Net.HttpWebRequest:
Request
HttpWebRequest request= (HttpWebRequest)WebRequest.Create(url);
request.ContentType="application/x-www-form-urlencoded";
request.Method = "POST";
request.KeepAlive = true;
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(BytePost,0,BytePost.Length);
requestStream.Close();
}
Response
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
using(StreamReader sr = new StreamReader(response.GetResponseStream()))
{
responseString = sr.ReadToEnd();
}
Here's a good example. You want to use the WebRequest class in C#, which will make this easy.
I understand this is old question, but posting this for someone looking for quick example on how to send Http Post request with json body in latest .NET (Core 5), using HttpClient (part of System.Net.Http namespace). Example:
//Initialise httpClient, preferably static in some common or util class.
public class Common
{
public static HttpClient HttpClient => new HttpClient
{
BaseAddress = new Uri("https://example.com")
};
}
public class User
{
//Function, where you want to post data to api
public void CreateUser(User user)
{
try
{
//Set path to api
var apiUrl = "/api/users";
//Initialize Json body to be sent with request. Import namespaces Newtonsoft.Json and Newtonsoft.Json.Linq, to use JsonConvert and JObject.
var jObj = JObject.Parse(JsonConvert.SerializeObject(user));
var jsonBody = new StringContent(jObj.ToString(), Encoding.UTF8, "application/json");
//Initialize the http request message, and attach json body to it
var request = new HttpRequestMessage(HttpMethod.Post, apiUrl)
{
Content = jsonBody
};
// If you want to send headers like auth token, keys, etc then attach it to request header
var apiKey = "qwerty";
request.Headers.Add("api-key", apiKey);
//Get the response
using var response = Common.HttpClient.Send(request);
//EnsureSuccessStatusCode() checks if response is successful, else will throw an exception
response.EnsureSuccessStatusCode();
}
catch (System.Exception ex)
{
//handle exception
}
}
}
Why is HttpClient static or recommended to be instantiated once per application:
HttpClient is intended to be instantiated once and re-used throughout
the life of an application. Instantiating an HttpClient class for
every request will exhaust the number of sockets available under heavy
loads. This will result in SocketException errors.
HttpClient class has async methods too. More info on HttpClient class: https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpclient?view=net-5.0

Categories