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!
Related
I am doing a bit of research into building a program to use the Australian crypto trading platform Coinspot. I have used API's in the past but barley used "POST" method, Coinspots information and documentation is sooooooo poor (probs because they don't want you to use it) but i figured ill give it a whirl anyways.
Question:
How do you use a POST method if you do not know the order in which to send data? (is there a standard or is every API different).
i have an API key and a secret API key to send for authorisation but still get access denied.
Is there anyway you can use code to request an order or something like you do when you pull a json to string?
WebRequest request = WebRequest.Create("https://www.coinspot.com.au/api/ro/balances");
request.Method = "POST";
request.Headers.Add("key", APIKEY);
request.ContentType = "application/json";
request.GetResponse(); //THIS IS WHERE IT ERRORS WITH AUTHENTICATION
sorry if its a scrub question but i think im looking at this the right way, i am also using .NET library json newtonsoft so any information on this would be fantastic!!
.NET Core interpretation of the somewhat dated yet functional CoinSpot node.js api client
var nonce = Utility.GetEpochTime();
var postData = new { nonce };
var jsonMessage = postData.ToJson();
var hmac = new HMACSHA512(Encoding.ASCII.GetBytes("CoinSpotSecret"));
var byteArray = Encoding.ASCII.GetBytes(jsonMessage);
using (var stream = new MemoryStream(byteArray)) {
var hash = hmac.ComputeHash(stream).Aggregate("", (s, e) => s + String.Format("{0:x2}", e), s => s);
var uri = new Uri("https://www.coinspot.com.au/api/ro/my/balances", UriKind.Absolute);
var content = new StringContent(
jsonMessage,
System.Text.Encoding.UTF8,
"application/json"
);
content.Headers.Add("sign", hash);
content.Headers.Add("key", "CoinSpotKey");
var response = await httpClient.PostAsync(uri, content);
if (response.IsSuccessStatusCode) {
return await response.Content.ReadAsStringAsync();
}
}
Due to the fact that I need to convert this C# dll into a tlp file to be called from Visual Basic 6, I need avoid using external dependencies. I have used RestSharp to consume a WebAPI by doing the following (working):
using RestSharp;
using Newtonsoft.Json;
..
public string GetToken (string Key, string Password) {
var client = new RestClient (BaseUrl + "auth/GetToken");
var request = new RestRequest (Method.POST);
request.AddHeader ("cache-control", "no-cache");
request.AddHeader ("Content-Type", "application/json");
Dictionary<string, string> data = new Dictionary<string, string> {
{ "APIKey", Key },
{ "APIPassword", Password }
};
var dataJSON = JsonConvert.SerializeObject (data);
request.AddParameter ("undefined", dataJSON, ParameterType.RequestBody);
IRestResponse response = client.Execute (request);
GetTokenResults g = JsonConvert.DeserializeObject<GetTokenResults> (response.Content);
return g.Token;
}
where GetTokenResults was a struct that contained a declaration for the string Token. I want to achieve this same functionality without using RestSharp. Here is my unsuccessful attempt:
using System.Net.Http;
using System.Net.Http.Headers;
..
public async void GetToken (string Key, string Password) {
var client = new HttpClient ( );
client.DefaultRequestHeaders.Accept.Clear ( );
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue ("application/json"));
client.BaseAddress = new Uri (BaseUrl + "auth/GetToken");
Dictionary<string, string> data = new Dictionary<string, string> {
{ "APIKey", Key },
{ "APIPassword", Password }
};
var dataJSON = JsonConvert.SerializeObject (data);
var content = new StringContent (dataJSON, Encoding.UTF8, "application/json");
var response = await client.PostAsync ("", content);
}
I am unclear on how to achieve the same results (send API key and password, return token as string) using HttpClient as I did using RestSharp earlier. Anything that can point me in the right direction is greatly appreciated!
I think you got stung by this issue. In short, the URI in client.BaseAddress needs a slash at the end of it.
However, I wouldn't simply add it, I'd consider doing it a little different. Presumably your BaseUrl already has a trailing slash, given you're appending "auth/GetToken" to it. I'd do it this way:
client.BaseAddress = new Uri(BaseUrl);
...
var response = await client.PostAsync("auth/GetToken", content);
As you can see, HttpClient fits very cleanly with how your code is already set up, i.e. you have a "base" address with a trailing slash and you want to append to it for a specific call.
That should get you un-stuck to this point. The next thing you'll need to tackle is deserializing the JSON response so you can get the token out of it. It's similar to how you did it in RestSharp, except that response.Content is not a string in the HttpClient world, so you need one more step to get that:
var json = await response.Content.ReadAsStringAsync();
GetTokenResults g = JsonConvert.DeserializeObject<GetTokenResults>(json);
return g.Token;
Last thing you'll need to do to get this to compile is change the method signature to:
public async Task<string> GetTokenAsync
One final note: you are now in the async world, and that's a good thing, but you need to know how to use it correctly or you could end up with deadlocks and other mysterious bugs. In short, don't block on async code by calling .Result or .Wait() anywhere up the call stack. That's by far most common mistake people make. Use async/await all the way down.
I think you are missing first parameter in the method PostAsync i.e. requestUri=Client.BaseAddress (see my implementation below).
Try with this first, if did not work, read below. I have a little different implementation where I passed client.BaseAddress as first parameter and I am passing my content as ByteArrayContent. In my case I have to pass my content as "application/x-www-form-urlencoded" excerpt of my code:
var buffer = Encoding.UTF8.GetBytes(content);
var byteContent = new ByteArrayContent(buffer);
//as I can't send JSON, probably, you can skip as it's already JSON
byteContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/x-www-form-urlencoded");
//requestUri=client.BaseAddress
await client.PostAsync(requestUri, byteContent).ConfigureAwait(false);
We have somewhat different need but I think you are pretty close. If it does not help, write me I will share my code. After reading the comment, I would like to share how I have made my HttpClient. The code is as it is:
using (var client = CreateMailClientForPOST($"{BaseUrl}/"))
{
//removed code, you can call above code as method like
var response= await client.DoThingAsAsync($"{client.BaseAddress}, content").ConfigureAwait(false);
}
protected HttpClient CreateMailClientForPOST(string resource)
{
var handler = new HttpClientHandler();
if (handler.SupportsAutomaticDecompression)
{
handler.AutomaticDecompression = System.Net.DecompressionMethods.GZip | System.Net.DecompressionMethods.Deflate;
}
var client = new HttpClient(handler)
{
BaseAddress = new Uri($"https://api.address.com/rest/{resource}")
};
return client;
}
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.
I'm trying to download a string from ANY webpage within my portable class library. I've created the most basic setup:
created a new PCL project
compatible with WP8 and WinRT as well as the compulsory components such as Silverlight
As WebClient is not compatible across these systems, it is not possible to use:
string data = new WebClient().DownloadString();
I've tried using this as well (uses this):
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = HttpMethod.Get;
HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync();
string data = ""
using (var sr = new StreamReader(response.GetResponseStream()))
{
data = sr.ReadToEnd();
}
However, when I call the second set of code from an external C# application referencing the PCL, the debugger simply fails with NO warning or error message on:
request.GetResponseAsync();
Is there an easy way to download a string that I'm missing?
*also, why would the debugger simply exit with no explanation?
Edit:
Here is another method I have attempted - based on an answer already provided. Again, this method simply exits and force closes the debugger.
PCL Method:
public static async Task<string> DownloadString()
{
var url = "http://google.com";
var client = new HttpClient();
var data = await client.GetStringAsync(url);
return data;
}
Calling method:
private static async void Method()
{
string data = await PCLProject.Class1.DownloadString();
return data;
}
Install the NuGet packages:
Microsoft.Bcl.Async, which adds async/await support to PCLs.
Microsoft.Net.Http, which adds HttpClient support to PCLs.
Then you can do it the easy way:
var client = new HttpClient();
var data = await client.GetStringAsync(url);
This method worked for me, it returned the HTML source code from google.com:
public async void GetStringFromWebpage()
{
using (HttpClient wc = new HttpClient())
{
var data = await wc.GetStringAsync("http://google.com/");
Debug.WriteLine("string:" + data);
}
}
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