Due to internal reason, I need to recode my servlet from Java to c#.
I am trying to upload a CSV file using the API PUT /marketing/contacts/imports with restsharp.
I cannot manage to send the file properly.
Code Snippet
Please fine below my java piece of code working:
File file = new File(CSV);
byte[] data;
try {
data = Files.readAllBytes(file.toPath());
HttpResponse<String> response2 = Unirest.put(URLSengrid)
.header(processSendgridHeader(headerFromSengrid).get(0), processSendgridHeader(headerFromSengrid).get(1))
//("x-amz-server-side-encryption", "aws:kms")
.body(data)
.asString();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
And here the non working c# code:
byte[] file = System.IO.File.ReadAllBytes(testPath);
var clientSecondCall = new RestClient(URLSendgrid);
var requestSecondCall = new RestRequest(Method.PUT);
requestSecondCall.AddHeader("content -type", "application/json");
requestSecondCall.AddHeader("x-amz-server-side-encryption", "aws:kms");
requestSecondCall.AddParameter("application/json", "{"file_type":"csv","field_mappings":["e1_T","e2_T","_rf2_T","e4_T","e5_T","e12_T","e13_T","e14_T","e15_T","e16_T"]}", ParameterType.RequestBody);
requestSecondCall.AddFile("file", file, testPath);
I spent a long time looking for an answer without success. Any help would be appreciated
Technical details:
sendgrid-csharp version: 9.*
csharp version: v4.0.303190
I believe the problem is the way you send the file in your c# code.
The Java code is clearly using the Body of the request, while the c# code is using RestSharp.
Restsharp is sending files in as a Multipart form, which your server is probably not qualified to handle.
I would recommend using HttpClient object:
HttpClient client = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage();
request.Method = HttpMethod.Put;
request.RequestUri = new Uri( "Your Url");
request.Content = new StringContent(File.ReadAllText(yourFilePath));
request.Headers.Add("your header name", "your header value");
var response = client.SendAsync(request).Result;
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!
I'm programmatically uploading files to a remote server. The files are moderately large and I'd like to present a progress report to my users so they can see something happening. I was able to implement the upload using Postman which helpfully translated the whole thing to RestSharp.
But RestSharp does not provide any kind of progress tracking. I tried to implement the same functionality using HttpClient but it goes wrong somewhere the and server just throws a "400 - Bad Request" without telling exactly what is bad about it (its API documentation is also not for the faint of heart).
So, here's what Postman / RestSharp provide and which is working:
var client = new RestClient("https://opencast/ingest/addMediaPackage");
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Basic FooBarBaz=");
request.AddParameter("creator", file.Creator);
request.AddParameter("title", file.Title);
request.AddParameter("flavor", "presentation/source");
request.AddParameter("description", file.Description);
try
{
request.AddFile("BODY", path);
IRestResponse response = await client.ExecuteAsync(request);
_logger.LogInformation($"Response after file upload: {response.StatusCode}");
File.Delete(path);
}
catch (Exception ex)
{
_logger.LogError(ex, "Exception when uploading files: {Message}", ex.Message);
}
and here's what I tried to do with HttpClient (without try-catch):
var request = new HttpRequestMessage(HttpMethod.Post, $"https://opencast/ingest/addMediaPackage");
request.Headers.Add("Authorization", "Basic FooBarBaz=");
using var form = new MultipartFormDataContent();
using var fileContent = new ByteArrayContent(await File.ReadAllBytesAsync(path));
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");
form.Add(fileContent, "BODY", Path.GetFileName(path));
form.Add(new StringContent(file.Creator), "creator");
form.Add(new StringContent(file.Title), "title");
form.Add(new StringContent("presentation/source"), "flavor");
form.Add(new StringContent(file.Description), "description");
request.Content = form;
var client = clientFactory.CreateClient(); //which is a IHttpClientFactory
var response = await client.SendAsync(request);
This code sends the file to the server which, after completing the upload, throws a 400.
Currently not seeing the difference. I could intercept the requests to see where they differ but maybe someone here can see the problem right away?
Update: It gets weirder. If I just use clientFactory.PostAsync(form) and add the Auth headers through form.Add then I get a 200 (i.e. Success) but the server simply swallows the file.
Okay, I found the solution. I'm not sure whether the WTF is me or the guys behind the server but...
... you need to add the fileContent last.
Yes, the order of the parameters matters for this.
Restsharp is not giving response in Xamarin.Android but working perfact in c# CommandLine console app.
var client = new RestClient("https://shotlo.com/api");
var request = new RestRequest("getProfile", Method.POST);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddParameter("token", "00");
request.AddParameter("userId", "00");
IRestResponse response = client.Execute(request);
var content = response.Content;
There is a version of RestSharp that should work 105.2.2, if you are on monoandroid10?
Is the code in a PCL or an actual Xamarin.Android library? If it is not in a PCL, are you developing an Android only app? Will it always be Android only? If not I'd recommend putting code like this into a PCL so you can re-use it from your Android or iOS implementations (kinda the point of using Xamarin?).
I'd also question the need for what is essentially a wrapper. I like RestSharp and use it myself but in Xamarin projects I just use System.Net.WebRequest (from inside a PCL). If you can get RestSharp working then great, go for it, otherwise drop back to WebRequest.
Start by creating the request:
var request = WebRequest.CreateHttp(url);
request.Method = method;
request.ContentType = contentType;
await AddBodyToRequest(data, request);
// add your headers here
Add the body (unedited):
protected static async Task AddBodyToRequest(byte[] data, WebRequest request)
{
Logger.Debug("AddBodyToRequest: {0}", request.ContentType);
var uri = request.RequestUri.AbsoluteUri;
try
{
using (Stream stream = await Task<Stream>.Factory.FromAsync(request.BeginGetRequestStream, request.EndGetRequestStream, null))
{
stream.Write(data, 0, data.Length);
}
}
catch (Exception ex)
{
Logger.Info(string.Format("[{0}] {1}. AddBodyToRequest [{2}]"
, ex.GetType().Name, ex.Message, uri));
}
}
Then send using something like:
using (var response = await request.GetResponseAsync(TimeSpan.FromSeconds(timeout)))
{
try
{
return new ServiceCallResult<TR>(response);
You can just return the response, personally I prefer to wrap the response (ServiceCallResult is a customer wrapper)...
I also check I 'can send' before trying...essentially checking the device still has a connection, not necessary but given you're on a device it's generally a good ideal (IMHO).
Good luck!
UPDATE: I figured it out and posted the answer below.
All I'm trying to do is update any file attribute. Description, name, anything, but no matter how I format it I get a 403.
I need to be able to modify a file so it can be shared via the Box API from a cloud app. I'm updating someone else's code from V1, but they are no longer available... I've tried many things but mostly just get 403 Forbidden errors.
There are no issues with OAuth2, that works fine and I can list files and folders, but can not modify them. This question is about sharing, but I can't change a description either. The box account is mine and I authenticate with my admin credentials. Any suggestions would be appreciated.
Here is the method I am using. I pass in the fileId and token and I've left out try/catch etc. for brevity.
string uri = string.Format("https://api.box.com/2.0/files/{0}", fileId);
string body = "{\"shared_link\": {\"access\": \"open\"}}";
byte[] postArray = Encoding.ASCII.GetBytes(body);
using (var client = new WebClient())
{
client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
client.Headers.Add("Authorization: Bearer " + token);
var response = client.UploadData(uri, postArray);
var responseString = Encoding.Default.GetString(response);
}
Thanks.
Okay, My Homer Simpson moment...
UploadData is a POST, I needed to do a PUT. Here is the solution.
string uri = String.Format(UriFiles, fileId);
string response = string.Empty;
string body = "{\"shared_link\": {\"access\": \"open\"}}";
byte[] postArray = Encoding.ASCII.GetBytes(body);
try
{
using (var client = new WebClient())
{
client.Headers.Add("Authorization: Bearer " + token);
client.Headers.Add("Content-Type", "application/json");
response = client.UploadString(uri, "PUT", body);
}
}
catch (Exception ex)
{
return null;
}
return response;
try changing your content type to 'multipart/form-data'?
I just looked up the api at: https://developers.box.com/docs/#files-upload-a-file
and it looks like the server is expecting a multipart post
here is stack overflow post on posting multipart data:
ASP.NET WebApi: how to perform a multipart post with file upload using WebApi HttpClient
I'm developing a C# app that uses Redmine REST API, it uses RestSharp Client. All other REST calls I make work fine but I cannot find a way to upload attachments. I've widely searched the web and tried many solutions but nothing worked.
Redmine documentiation on attachments: http://www.redmine.org/projects/redmine/wiki/Rest_api#Attaching-files
The code actually looks like:
RestClient client = new RestClient("http://myclient/redmine/");
client.Authenticator = new HttpBasicAuthenticator("myuser", "mypsw");
var request2 = new RestRequest("uploads.json", Method.POST);
request2.AddHeader("Content-Type", "application/octet-stream");
request2.RequestFormat = RestSharp.DataFormat.Json;
byte[] dataToSend = File.ReadAllBytes(AddIssue.attach.Text);
request2.AddBody(dataToSend);
IRestResponse response2 = client.Execute(request2);
resultbox.Text = response2.Content;
If I execute it above nothing happens and the response is empty. If I remove line 7 (the AddBody), it actually works but of course nothing is uploaded, JSON response:
{
"upload": {
"token": "11."
}
}
So actually, the real question is what to punt in AddBody() to send the file as application/octet-stream. Since RestSharp also has a request.AddFile() method, I tried it too in different ways but nothing...
Any help much appreciated!
As I mentioned in my comment, it sounds like Redmine might have requirements similar to Dropbox. Here is the solution that worked for me (based on the question Upload to dropbox using Restsharp PCL):
public static void UploadFileToDropbox(string filePath)
{
RestClient client = new RestClient("https://api-content.dropbox.com/1/");
IRestRequest request = new RestRequest("files_put/auto/{path}", Method.PUT);
FileInfo fileInfo = new FileInfo(filePath);
long fileLength = fileInfo.Length;
request.AddHeader("Authorization", "Bearer INSERT_DEVELOPER_TOKEN_HERE");
request.AddHeader("Content-Length", fileLength.ToString());
request.AddUrlSegment("path", string.Format("Public/{0}", fileInfo.Name));
byte[] data = File.ReadAllBytes(filePath);
var body = new Parameter
{
Name = "file",
Value = data,
Type = ParameterType.RequestBody,
};
request.Parameters.Add(body);
IRestResponse response = client.Execute(request);
}
Also published as a Gist.
I know this isn't your exact situation, but hopefully it gives you some ideas.