recently i discovered this amazing cms called Directus, where you can manage your database and Tables with web request and Json.
Everything worked fine creating,updating,reading...till i came to the point where i want to Create (Upload) a Image using WebRequest.
Im basicly reading a image as Base64 and writing the data along with the parameters in the Uri using a simple GET request exactly like described in API.
Regardless what i try and use the Images Never show up in my Files.
Am i doing something wrong or forgetting something?
Or does directus want something else from me?
My first try:
public static async void UploadUserImage() {
var uri = "http://IP/Directus/api/1/files?access_token=SecretApiKey";
var data = GetImageData();
var finalUri = $"{uri}&data={data}";
using (var client = new HttpClient()) {
var responseString = await client.GetStringAsync(finalUri);
Console.Write(responseString);
}
}
My Second try with Json:
public static async void UploadUserImage() {
var uri = "http://IP/Directus/api/1/files?access_token=SecretApiKey";
var data = GetImageData();
var finalUri = $"{uri}&data={data}";
var postModel = new PictureModel {
data = data,
title = "Test",
name = "test"
};
using (var client = new HttpClient())
{
// Serialize our concrete class into a JSON String
var content = JsonConvert.SerializeObject(postModel);
var contenta = new StringContent(content, Encoding.UTF8, "application/json");
var response = await client.PostAsync(finalUri, contenta);
var result = await response.Content.ReadAsByteArrayAsync();
Console.Write(System.Text.Encoding.UTF8.GetString(result));
}
}
The docs is incorrect it's actually a POST request. Thanks for pointing that out.
To upload a new file you need three provide three values:
{
"name": "image.png",
"type": "image/png",
"data": "base64content"
}
The data content has to be in this format data:<mime-type>;base64,<data-content> so it will look something like this: data:image/png;base64,ThisIsABase64Content
We are updating the docs and removing the data:image/png which is unnecessary.
Related
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!
As title says, can find plenty of resources on posting to an endpoint (from JS, for example), but how do I construct a HttpRequest (in C# .Net core) with files?
What I've Tried
var myRequest = new DefaultHttpContext().Request;
myRequest.Form.Files // GET only!
I can't seem to set the Files collection (IFormFileCollection), I can only get it.
Further Context
This is to integration test an endpoint. Except I have to hit the method, not reach it via URL (for one reason or another). The method accepts a HttpRequest and parses out the Form.Files collection. Hence I need to add some files for my assertions.
Did you already try something like this:
using (var stream = new MemoryStream(fileBytes))
{
var bla = new DefaultHttpContext().Request;
bla.Form.Files.Append(new Microsoft.AspNetCore.Http.Internal.FormFile(stream, 0, stream.Length, "file.txt", "file.txt"));
}
you can achieve this by take advantage of the following Method
public async Task<string> UploadFile(string filePath)
{
if (string.IsNullOrWhiteSpace(filePath))
{
throw new ArgumentNullException(nameof(filePath));
}
if (!File.Exists(filePath))
{
throw new FileNotFoundException($"File [{filePath}] not found.");
}
using var form = new MultipartFormDataContent();
using var fileContent = new ByteArrayContent(await File.ReadAllBytesAsync(filePath));
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");
form.Add(fileContent, "file", Path.GetFileName(filePath));
form.Add(new StringContent("789"), "userId");
form.Add(new StringContent("some comments"), "comment");
form.Add(new StringContent("true"), "isPrimary");
var response = await _httpClient.PostAsync($"{_url}/api/files", form);
response.EnsureSuccessStatusCode();
var responseContent = await response.Content.ReadAsStringAsync();
var result = JsonSerializer.Deserialize<FileUploadResult>(responseContent);
return result.Guid;
}
this method was snipped from a good blog: https://codeburst.io/upload-download-files-using-httpclient-in-c-f29051dea40c
It would look something like this:
var context = new DefaultHttpContext();
var formFiles = new FormFileCollection();
var formValues = new Dictionary<string, StringValues>() { };
var formCollection = new FormCollection(formValues, formFiles);
context.Features.Set<IFormFeature>(new FormFeature(formCollection));
Fill in the formFiles and formValues variables based on what you're trying to test. The key here is setting the feature to your custom FormFeature. That will cleanly plug into the default behavior of .Form and ReadFormAsync
PS: This is for unit testing assuming you're not trying to send a real file to the server side, otherwise mustafa hassan's answer works
I'm working on an application to get some API experience with C#. I'm pulling data from a site involving jokes, but no matter what I try I can't seem to get the actual response.
I've gone over several different methods, this is the farthest I've gotten. I'm using the RestSharp library, and it's returning RestSharp.RestResponse. I've tried several different methods of deserializing this as that's what I believe is needed. From the API I'm using, the default response format is text/html. Any tips on extracting this to a string containing the joke itself would be most appreciated.
public void CreateJoke()
{
var client = new RestClient("https://icanhazdadjoke.com/");
client.AddDefaultHeader("user-agent", "Dadbot");
var request = new RestRequest("https://icanhazdadjoke.com/");
var response = client.Get(request);
lblJoke.Text = response.ToString();
}
Expected result: getting a string I can put into a label. Actual result: RestSharp.RestResponse.
Try instead accessing the Content property of response:
public void CreateJoke()
{
var client = new RestClient("https://icanhazdadjoke.com/");
client.AddDefaultHeader("user-agent", "Dadbot");
var request = new RestRequest("https://icanhazdadjoke.com/");
var response = client.Get(request);
lblJoke.Text = response.Content;
}
Hopefully that helps!
I guess this is what you want.
public string CreateJoke()
{
var request = (HttpWebRequest)WebRequest.Create("https://icanhazdadjoke.com/");
request.Method = "GET";
request.Accept = "text/plain";
var jokeResponse = request.GetResponse();
var joke = string.Empty;
using (var sr = new StreamReader(jokeResponse.GetResponseStream()))
{
joke = sr.ReadToEnd();
}
//Console.WriteLine(joke);
return joke;
}
I'm trying to send a post variable to the url which I'm redirecting to.
I'm currently using the Get method and sending it like this:
// Redirect to page with url parameter (GET)
Response.Redirect("web pages/livestream.aspx?address="+ ((Hardwarerecorders.Device)devices[arrayIndex]).streamAddress);
And retrieving it like this:
// Get the url parameter here
string address = Request.QueryString["address"];
How do I convert my code to use the POST method?
B.T.W., I don't want to use a form to send the post variable.
Using HttpClient:
To send POST query:
using System.Net.Http;
public string sendPostRequest(string URI, dynamic content)
{
var client = new HttpClient();
client.BaseAddress = new Uri("http://yourBaseAddress");
var valuesAsJson = JsonConvert.SerializeObject(content);
HttpContent contentPost = new StringContent(valuesAsJson, Encoding.UTF8, "application/json");
var result = client.PostAsync(URI, contentPost).Result;
return result.Content.ReadAsStringAsync().Result;
}
Where 'client.PostAsync(URI, contentPost)' is where the content is being sent to the other website.
On the other website, an API Controller needs to be established to receive the result, something like this:
[HttpPost]
[Route("yourURI")]
public void receivePost([FromBody]dynamic myObject)
{
//..
}
However, you might also want to look into using a 307 re-direct, especially if this is a temporary solution.
https://softwareengineering.stackexchange.com/a/99966
using System.Net.Http;
POST
using (var client = new HttpClient())
{
var values = new Dictionary<string, string>
{
{ "thing1", "hello" },
{ "thing2", "world" }
};
var content = new FormUrlEncodedContent(values);
var response = await client.PostAsync("http://www.example.com/recepticle.aspx", content);
var responseString = await response.Content.ReadAsStringAsync();
}
GET
using (var client = new HttpClient())
{
var responseString = client.GetStringAsync("http://www.example.com/recepticle.aspx");
}
My Personal Choice is Restsharp it's fast but for basic operations you can use this
I am developing an website for my company and in there I want to tag skills to specific people. So the programming tags that shows in stackoverflow is a valuable source. SO I want to get the tag db of the stackoverflow.
I found an API for that.
API for the TAGS
So what I am trying to do is read this json string and forloop through the pages to get the tags and save them in a DB.
private static void ReadJson()
{
HttpClient client = new HttpClient();
//DefaultRequestHeader to Json
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
//Create an instance of HttpResponse & invoke the service asynchronously
HttpResponseMessage response = client.GetAsync("https://api.stackexchange.com/2.2/tags?page=400&pagesize=100&order=desc&sort=popular&site=stackoverflow").Result;
//Http Status code 200
if (response.IsSuccessStatusCode)
{
//Read response content result into string variable
string JSON = response.Content.ReadAsStringAsync().Result;
//Deserialize the string(JSON) object
var jObj = (JObject)JsonConvert.DeserializeObject(JSON);
//access items from anonymous (Json object) type and add to the list
var result = jObj["items"].Select(item => new
{
name = item["name"]
}).ToList();
//output the data || NOTE: **NSERT into database table**
foreach (var item in result)
{
Console.WriteLine(item.name);
}
}
}
So at string JSON = response.Content.ReadAsStringAsync().Result;
method it shows some weired charachters ( triangels and shapes ) because of that process is stopping there.
0\0\0�Z�n�8\f��<�E/S��,-�cYtuI�\f�ߗf\a�g�
What I am doing wrong here?
If there any way to make this happen please contribute your answer.
Thanks.
What you're getting is a compressed response. So instead of reading it as a string, read it as a byte[], decompress it and you'll find your JSON string.
static async void DoStuff()
{
HttpClient client = new HttpClient();
var bytes = await client.GetByteArrayAsync("https://api.stackexchange.com/2.2/tags?page=400&pagesize=100&order=desc&sort=popular&site=stackoverflow");
var decompressedJson = new StreamReader(new GZipStream(new MemoryStream(bytes), CompressionMode.Decompress)).ReadToEnd();
// decompressedJson will now contain '{"items":[{"has_synonyms":false, .....'
// Continue with deserialization of JSON
}
static void Main(string[] args)
{
Task t = new Task(DoStuff);
t.Start();
Console.WriteLine("Doing stuff");
Console.ReadLine();
}
}
You can continue with the deserialization from there. Keep in mind that the API will throw an error when you're sending too many requests.