I'm referencing the url https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_sobject_insert_update_blob.htm#inserting_a_contentversion and I see the curl methods, but c# can't use c#. So I've attempted creating the multiPartForm request with no avail.
Below are the two specific curl calls I'm attempting to recreate in C#.
--boundary_string
Content-Disposition: form-data; name="entity_content";
Content-Type: application/json
{
"ContentDocumentId" : "069D00000000so2",
"ReasonForChange" : "Marketing materials updated",
"PathOnClient" : "Q1 Sales Brochure.pdf"
}
--boundary_string
Content-Type: application/octet-stream
Content-Disposition: form-data; name="VersionData"; filename="Q1 Sales Brochure.pdf"
Binary data goes here.
--boundary_string--
and
--boundary_string
Content-Disposition: form-data; name="entity_document";
Content-Type: application/json
{
"Description" : "Marketing brochure for Q1 2011",
"Keywords" : "marketing,sales,update",
"FolderId" : "005D0000001GiU7",
"Name" : "Marketing Brochure Q1",
"Type" : "pdf"
}
--boundary_string
Content-Type: application/pdf
Content-Disposition: form-data; name="Body"; filename="2011Q1MktgBrochure.pdf"
Binary data goes here.
--boundary_string--
Here are my code attempts, with the byte[] and in some case a base64 string. I've switched out the base[] and the base64 string in each case and I have had no luck, the json string is correctly formatted, the token is valid, just keep getting back a 400 error. (bad request) from salesforce.
public async Task<HttpResponseMessage> PostBlobAsync(string url, string token, string json, byte[] pdfBase64)
{
try
{
using (var httpContent = new MultipartFormDataContent("boundary_string"))
{
httpContent.Headers.ContentType.MediaType = "multipart/form-data";
httpContent.Add(new StringContent(json, System.Text.Encoding.UTF8, "application/json"));
//var content = new StringContent(pdfBase64.ToString(), System.Text.Encoding.UTF8, "application/octet-stream");
var content = new ByteArrayContent(pdfBase64, 0, pdfBase64.Length - 1);
content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/octet-stream");
_logger.LogInformation("HTTP Client PostAsync calling URL:{0} at {1}", url, DateTime.UtcNow);
_httpClient.UseBearerToken(token);
var response = await _httpClient.PostAsync(url, httpContent);
if (!response.IsSuccessStatusCode)
{
var ex = CreateException(response);
throw ex;
}
return response;
}
}
catch (Exception ex)
{
_logger.LogInformation(ex.Message, url, DateTime.UtcNow);
throw ex;
}
}
public async Task<HttpResponseMessage> PostBlobAsync2(string url, string token, string json, string fileBytes)
{
try
{
using (var httpContent = new MultipartFormDataContent("boundary_string"))
{
httpContent.Headers.ContentType.MediaType = "multipart/form-data";
var content1 = new StringContent(json, System.Text.Encoding.UTF8, "application/json");
var contentDisposition1 = new ContentDispositionHeaderValue("form-data");
contentDisposition1.Name = "entity_content";
content1.Headers.ContentDisposition = contentDisposition1;
httpContent.Add(content1);
//var content2 = new StringContent(pdfBase64.ToString(), System.Text.Encoding.UTF8, "application/octet-stream");
//var content2 = new StringContent(fileBytes, System.Text.Encoding.UTF8, "application/pdf");
var content2 = new StringContent(fileBytes);
content2.Headers.ContentType = MediaTypeHeaderValue.Parse("application/octet-stream");
var contentDisposition2 = new ContentDispositionHeaderValue("form-data");
contentDisposition2.Name = "VersionData";
contentDisposition2.FileName = "Change Request.pdf";
httpContent.Add(content2);
_logger.LogInformation("HTTP Client PostAsync calling URL:{0} at {1}", url, DateTime.UtcNow);
_httpClient.UseBearerToken(token);
var response = await _httpClient.PostAsync(url, httpContent);
if (!response.IsSuccessStatusCode)
{
var ex = CreateException(response);
throw ex;
}
return response;
}
}
catch (Exception ex)
{
_logger.LogInformation(ex.Message, url, DateTime.UtcNow);
throw ex;
}
}
public async Task<HttpResponseMessage> PostBlobAsync3(string url, string token, string caseId, string fileBytes)
{
try
{
using (var httpContent = new MultipartFormDataContent("boundary_string"))
{
//httpContent.Headers.ContentType.MediaType = "multipart/form-data";
var dictionary = new Dictionary<string, string>();
dictionary.Add("Description", "New Change Request");
dictionary.Add("Keywords", "Change,Request");
dictionary.Add("FolderId", caseId);
dictionary.Add("Type", "pdf");
var json = JsonConvert.SerializeObject(dictionary);
var content1 = new StringContent(json);
content1.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
var contentDisposition1 = new ContentDispositionHeaderValue("form-data");
contentDisposition1.Name = "entity_document";
content1.Headers.ContentDisposition = contentDisposition1;
httpContent.Add(content1);
//var content2 = new StringContent(pdfBase64.ToString(), System.Text.Encoding.UTF8, "application/octet-stream");
//var content2 = new StringContent(fileBytes, System.Text.Encoding.UTF8, "application/pdf");
var content2 = new StringContent(fileBytes);
content2.Headers.ContentType = MediaTypeHeaderValue.Parse("application/pdf");
var contentDisposition2 = new ContentDispositionHeaderValue("form-data");
contentDisposition2.Name = "Body";
contentDisposition2.FileName = "Change Request.pdf";
httpContent.Add(content2);
_logger.LogInformation("HTTP Client PostAsync calling URL:{0} at {1}", url, DateTime.UtcNow);
_httpClient.UseBearerToken(token);
var response = await _httpClient.PostAsync(url, httpContent);
if (!response.IsSuccessStatusCode)
{
var ex = CreateException(response);
throw ex;
}
return response;
}
}
catch (Exception ex)
{
_logger.LogInformation(ex.Message, url, DateTime.UtcNow);
throw ex;
}
}
public async Task<bool> PostBlobAsync4(string url, string token, string caseId, byte[] fileBytes)
{
string boundary = "boundary_string";
var req = System.Net.WebRequest.Create(url);
req.Headers.Add("Authorization: OAuth " + token);
req.ContentType = "multipart/form-data; boundary=" + boundary;
req.Method = "POST";
var os = req.GetRequestStream();
string body = "";
body += $"\r\n--{boundary}\r\n";
body += "Content-Disposition: form-data; name='entity_document'\r\n";
body += "Content-Type: application/json\r\n\r\n";
var dictionary = new Dictionary<string, string>();
dictionary.Add("Description", "New Change Request");
dictionary.Add("Keywords", "Change,Request");
dictionary.Add("FolderId", caseId);
dictionary.Add("Type", "pdf");
dictionary.Add("Name", "Change Request");
var json = JsonConvert.SerializeObject(dictionary);
body += json;
// Add header for binary part
body += "\r\n--" + boundary + "\r\n";
body += "Content-Disposition: form-data; name='Body'; filename='1.txt'\r\n";
body += "Content-Type: binary/octet-stream\r\n\r\n";
byte[] data = System.Text.Encoding.ASCII.GetBytes(body);
os.Write(data, 0, data.Length);
os.Write(fileBytes, 0, fileBytes.Length);
byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
os.Write(trailer, 0, trailer.Length);
os.Close();
WebResponse resp;
try
{
resp = await req.GetResponseAsync();
}
catch(WebException ex)
{
return false;
}
return true;
}
Related
So I am using the Dailymotion API for uploading the video and use the code I get from the GitHub and it works perfectly but after 4 videos it gives the exception:
{"The remote server returned an error: (403) Forbidden."}
And I am getting an error in PublishVideo method
var response = request.GetResponse();
Main Code
var accessToken = GetAccessToken();
Authorize(accessToken);
Console.WriteLine("Access token is " + accessToken);
var fileToUpload = #"E:\Courses\[FreeCourseSite.com] Udemy - Entity Framework in Depth The Complete Guide\3. Building a Model using Database-First Workflow\11. Summary.mp4";
Console.WriteLine("File to upload is " + fileToUpload);
var uploadUrl = GetFileUploadUrl(accessToken);
Console.WriteLine("Posting to " + uploadUrl);
var response = GetFileUploadResponse(fileToUpload, accessToken, uploadUrl);
Console.WriteLine("Response:\n");
Console.WriteLine(response + "\n");
Console.WriteLine("Publishing video.\n");
var uploadedResponse = PublishVideo(response, accessToken);
Console.WriteLine(uploadedResponse);
Console.WriteLine("Done. Press enter to exit.");
Console.ReadLine();
}
private static UploadResponse GetFileUploadResponse(string fileToUpload, string accessToken, string uploadUrl)
{
var client = new WebClient();
client.Headers.Add("Authorization", "OAuth " + accessToken);
var responseBytes = client.UploadFile(uploadUrl, fileToUpload);
var responseString = Encoding.UTF8.GetString(responseBytes);
var response = JsonConvert.DeserializeObject<UploadResponse>(responseString);
return response;
}
private static UploadedResponse PublishVideo(UploadResponse uploadResponse, string accessToken)
{
var request = WebRequest.Create("https://api.dailymotion.com/me/videos?url=" + HttpUtility.UrlEncode(uploadResponse.url));
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.Headers.Add("Authorization", "OAuth " + accessToken);
var requestString = String.Format("title={0}&tags={1}&channel={2}&private={3}&published={4}",
HttpUtility.UrlEncode("123123123"),
HttpUtility.UrlEncode("tag1"),
HttpUtility.UrlEncode("news"),
HttpUtility.UrlEncode("true"),
HttpUtility.UrlEncode("true"));
var requestBytes = Encoding.UTF8.GetBytes(requestString);
var requestStream = request.GetRequestStream();
requestStream.Write(requestBytes, 0, requestBytes.Length);
var response = request.GetResponse();
var responseStream = response.GetResponseStream();
string responseString;
using (var reader = new StreamReader(responseStream))
{
responseString = reader.ReadToEnd();
}
var uploadedResponse = JsonConvert.DeserializeObject<UploadedResponse>(responseString);
return uploadedResponse;
}
private static string GetAccessToken()
{
var request = WebRequest.Create("https://api.dailymotion.com/oauth/token");
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
var requestString = String.Format("grant_type=password&client_id={0}&client_secret={1}&username={2}&password={3}",
HttpUtility.UrlEncode(SettingsProvider.Key),
HttpUtility.UrlEncode(SettingsProvider.Secret),
HttpUtility.UrlEncode(SettingsProvider.Username),
HttpUtility.UrlEncode(SettingsProvider.Password));
var requestBytes = Encoding.UTF8.GetBytes(requestString);
var requestStream = request.GetRequestStream();
requestStream.Write(requestBytes, 0, requestBytes.Length);
var response = request.GetResponse();
var responseStream = response.GetResponseStream();
string responseString;
using (var reader = new StreamReader(responseStream))
{
responseString = reader.ReadToEnd();
}
var oauthResponse = JsonConvert.DeserializeObject<OAuthResponse>(responseString);
return oauthResponse.access_token;
}
private static void Authorize(string accessToken)
{
var authorizeUrl = String.Format("https://api.dailymotion.com/oauth/authorize?response_type=code&client_id={0}&scope=read+write+manage_videos+delete&redirect_uri={1}",
HttpUtility.UrlEncode(SettingsProvider.Key),
HttpUtility.UrlEncode(SettingsProvider.CallbackUrl));
Console.WriteLine("We need permissions to upload. Press enter to open web browser.");
Console.ReadLine();
Process.Start(authorizeUrl);
var client = new WebClient();
client.Headers.Add("Authorization", "OAuth " + accessToken);
Console.WriteLine("Press enter once you have authenticated and been redirected to your callback URL");
Console.ReadLine();
}
private static string GetFileUploadUrl(string accessToken)
{
var client = new WebClient();
client.Headers.Add("Authorization", "OAuth " + accessToken);
var urlResponse = client.DownloadString("https://api.dailymotion.com/file/upload");
var response = JsonConvert.DeserializeObject<UploadRequestResponse>(urlResponse).upload_url;
return response;
}
}
It could be related to many causes. I suggest you to catch the error and get the response stream from our API:
try{
var response = request.GetResponse();
var responseStream = response.GetResponseStream();
string responseString;
using (var reader = new StreamReader(responseStream))
{
responseString = reader.ReadToEnd();
}
var uploadedResponse = JsonConvert.DeserializeObject<UploadedResponse>(responseString);
return uploadedResponse;
}
catch(WebException e){
var rs = e.Response.GetResponseStream();
string errorResponseString;
using (var reader = new StreamReader(rs))
{
errorResponseString = reader.ReadToEnd();
}
Console.WriteLine(errorResponseString);
return null;
}
You will get a message explaining you why your access is forbidden.
I also invite you to check our API rate limit rules which can be a cause of forbidden call: https://developer.dailymotion.com/api/#rate-limit
I am attempting to consume a Data source from Plex a cloud ERP System with Rest. I am receiving a forbidden status code upon sending the PUT
public static string Put(string url,string Body,PCNModel pcn)
{
HttpClient client = new HttpClient();
int timeOutSec = 90;
string accept = "application/json";
string acceptEncoding = "gzip, deflate";
string contentType = "application/json";
var credentials = pcn.UserName + ":" + pcn.Password;
var bytes = Encoding.UTF8.GetBytes(credentials);
var encodedCredentials = Convert.ToBase64String(bytes);
var authorizationHeaderValue = encodedCredentials;
HttpResponseMessage response = new HttpResponseMessage();
client.Timeout = new TimeSpan(0, 0, timeOutSec);
//client.DefaultRequestHeaders.Add("Accept", string.Format(accept));
client.DefaultRequestHeaders.Add("Accept", (accept));
client.DefaultRequestHeaders.Add("Accept-Encoding", string.Format(acceptEncoding));
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(contentType));
client.DefaultRequestHeaders.Add("Authorization", string.Format("Basic {0}", authorizationHeaderValue));
HttpContent httpBody = Body;
httpBody.Headers.ContentType = new MediaTypeHeaderValue(contentType);
response = client.PutAsync(url, httpBody).Result;
var error = response.StatusCode.ToString();
var requestMessage = response.RequestMessage;
var responseContent = response.Content;
var responseReasonPhrase = response.ReasonPhrase;
var responseHeader = response.Headers;
MessageBox.Show(error);
MessageBox.Show(requestMessage.ToString());
//MessageBox.Show(responseContent.ToString());
//MessageBox.Show(responseReasonPhrase.ToString());
//MessageBox.Show(responseHeader.ToString());
var content = response.Content.ReadAsStringAsync().Result;
return content;
}
I am not sure where it is bouncing back at me.
You need to parse body to json before calling PutAsync here is a small code sinppet
client.DefaultRequestHeaders.Add("authKey", authKey);
var json = JsonConvert.SerializeObject(product, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PutAsync(url, content);
if (response.IsSuccessStatusCode)
{
}
else
{
var result = response.Content.ReadAsStringAsync().Result;
throw new Exception("Error Occured in Update Product" + result);
}
It turns out that the credentials I was provided were incorrect. Which prevented me from processing web services calls to the endpoint.
I've been trying to use RestSharp Library in order to make requests, but when I've tried to make a POST request this error keeps emerging!!
Here is the code:
private readonly string contentType = "application/json";
try
{
var restClient = new RestClient(new Uri(InvoiceExpressURLS.URL_createClient));
string clientJsonRequest =
JsonConvert.SerializeObject(
JsonConvert.DeserializeObject("{\"client\":" + JsonConvert.SerializeObject(newClient) + "}")
);
var request = new RestRequest(Method.POST);
request.RequestFormat = DataFormat.Json;
request.AddHeader("Content-Type", contentType);
request.AddJsonBody(clientJsonRequest);
var restResponse = await restClient.ExecuteTaskAsync<object>(request);
if (restResponse.IsSuccessful)
{
response.responseObject = restResponse.Data;
response.responseMessage = string.Format("The client \"{0}\" was successfuly created.", newClient.name);
}
else
{
response.responseStatus = restResponse.StatusCode;
response.responseMessage = restResponse.ErrorMessage;
}
}
catch (Exception e)
{
response.responseStatus = HttpStatusCode.InternalServerError;
response.responseMessage = e.Message;
response.responseObject = e;
}
I'm trying to upload image and json in one request using c# code, but server always returns 400- bad request. Executing same request using fiddler returns status code 200. help...
Here is my fiddler code :
------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name="application/json" Content-Type: application/json
{"type": "Personal","comments": ["Lorem", "Ipsum" ] }
------WebKitFormBoundary7MA4YWxkTrZu0gW-- Content-Disposition: form-data; name="fieldNameHere"; filename="1111.jpg"
Content-Type: image/jpeg
<#INCLUDE C:\Users\user\Desktop\New folder\1111.jpg#>
And implementation in c#:
var boundary = "Upload----" + DateTime.Now.Ticks.ToString();
MultipartFormDataContent form = new MultipartFormDataContent(boundary);
StringContent content = new StringContent(bodyJson);
content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
form.Add(content, "application/json");
var imageContent = new ByteArrayContent(image);
imageContent.Headers.ContentType = MediaTypeHeaderValue.Parse("image/jpeg");
form.Add(imageContent, "image/jpeg", "image.jpg");
var responseTask = _httpClient.PostAsync(url, form).Result;
the response is always same :
You can pass the parameter as a string content , check the below sample.
public async Task<JObject> ExecutePostAsync(Stream myStreem, string url, string token, string parameter1, string parameter2, string parameter3)
{
try
{
using (var content = new MultipartFormDataContent("----MyBoundary"))
{
using (var memoryStream = myStreem)
{
using (var stream = new StreamContent(memoryStream))
{
content.Add(stream, "file", Guid.NewGuid().ToString() + ".jpg");
content.Add(new StringContent(parameter1), "parameter1");
content.Add(new StringContent(parameter3), "parameter2");
content.Add(new StringContent(parameter3), "parameter3");
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
var responce = await client.PostAsync(url, content);
string contents = await responce.Content.ReadAsStringAsync();
return (JObject.Parse(contents));
}
}
}
}
}
catch (Exception ex)
{
throw ex;
}
}
In API get the data from FORM request
public async Task<IHttpActionResult> UploadFile()
{
string parameter1 = HttpContext.Current.Request.Form["parameter1"];
string parameter2 = HttpContext.Current.Request.Form["parameter2"];
string parameter3 = HttpContext.Current.Request.Form["parameter3"];
}
I have done POSTING and GETing from server using string post data, but now i have the next WebService:
submitFeedback(String token, String subject, String body, byte[] photo, byte[] video);
private void PostFeedbackData()
{
if (GS.online != true)
{
MessageBox.Show(GS.translations["ErrorMsg0"]);
}
else
{
HttpWebRequest request = HttpWebRequest.CreateHttp("https://****/feedback");
request.Method = "POST";
request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), request);
}
}
void GetRequestStreamCallback(IAsyncResult callbackResult)
{
HttpWebRequest myRequest = (HttpWebRequest)callbackResult.AsyncState;
// End the stream request operation
Stream postStream = myRequest.EndGetRequestStream(callbackResult);
// Create the post data
string postData = "";
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
postData = "{\"jsonrpc\": \"2.0\", \"method\": \"getUserSchedule\", \"params\":[" + "\"" + (App.Current as App).UserToken + "\",\"" + FeedbackTitle.Text + "\",\"" + FeedbackContent.Text + "\",\"" + imageBytes + "\"], \"id\": 1}";
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
// Add the post data to the web request
postStream.Write(byteArray, 0, byteArray.Length);
postStream.Close();
// Start the web request
myRequest.BeginGetResponse(new AsyncCallback(GetResponsetStreamCallback), myRequest);
});
}
Look at post data - it is a string, i can't place there imageBytes array. How to do it?
Is there any reason for using HttpWebRequest ?
I am asking that because i think that the correct way of sending files to a service is by multipartform data. With HttpWebRequest you have to manually implement that.
Here is an example that is using Microsoft's HttpClient that might work for you:
public async Task<string> submitFeedback(String token, String subject, String body, byte[] photo, byte[] video) {
var client = new HttpClient();
var content = new MultipartFormDataContent();
// Some APIs do not support quotes in boundary field
foreach (var param in content.Headers.ContentType.Parameters.Where(param => param.Name.Equals("boundary")))
param.Value = param.Value.Replace("\"", String.Empty);
var tok = new StringContent(token);
content.Add(tok, "\"token\"");
var sub = new StringContent(subject);
content.Add(tok, "\"subject\"");
// Add the Photo
var photoContent = new StreamContent(new MemoryStream(photo));
photoContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "\"photo\"",
FileName = "\"photoname.jpg\""
};
photoContent.Headers.ContentType = MediaTypeHeaderValue.Parse("image/jpeg");
content.Add(photoContent);
// Add the video
var videoContent = new StreamContent(new MemoryStream(video));
videoContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "\"video\"",
FileName = "\"videoname.jpg\""
};
videoContent.Headers.ContentType = MediaTypeHeaderValue.Parse("video/mp4");
content.Add(videoContent);
HttpResponseMessage resp;
try {
resp = await client.PostAsync("SERVER_URL_GOES_HERE", content);
}
catch (Exception e)
{
return "EXCEPTION ERROR";
}
if (resp.StatusCode != HttpStatusCode.OK)
{
return resp.StatusCode.ToString();
}
var reponse = await resp.Content.ReadAsStringAsync();
return reponse;
}
Change accordingly.
Note: HttpClient is also using HttpWebRequest under the hood.
Also I don't think its a good idea to have the UI thread making the request. That makes no sense since you are blocking the interface and making the async theory useless.