Looking for the correct syntax for a swagger /document POST from a REST client - rest

I am sending a post to /document (swagger), which should upload a document using the body content of
{
"Application": "tickets",
"File": "some binary data"
}
The back in is using swagger /document so I believe my headers are not coming over correctly.
The problem is I am not getting the correct combination of the headers that need to be sent over:
Authorization : xxxx;
Content-Type : multipart/form-data;
Content-Type : image/png;
Content-Type : application/json;
FileName : file_name
Response:
415 Unsupported Media Type

FileInfo fi = new FileInfo(#"file");
byte[] fileContents = File.ReadAllBytes(fi.FullName);
ByteArrayContent byteArrayContent = new ByteArrayContent(fileContents);
byteArrayContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
byteArrayContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
FileName = fi.Name,
};
MultipartFormDataContent multiPartContent = new MultipartFormDataContent();
multiPartContent.Add(new StringContent("document storage"), "Application");
multiPartContent.Add(byteArrayContent, "File");
string header = string.Format("WRAP access_token=\"{0}\"", "xxxx");
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "/document");
request.Headers.Add("Authorization", header);
request.Content = multiPartContent;
HttpClient httpClient = new HttpClient();
try
{
Task<HttpResponseMessage> httpRequest = httpClient.SendAsync(request, HttpCompletionOption.ResponseContentRead, CancellationToken.None);
HttpResponseMessage httpResponse = httpRequest.Result;
HttpStatusCode statusCode = httpResponse.StatusCode;
HttpContent responseContent = httpResponse.Content;
if (responseContent != null)
{
Task<String> stringContentsTask = responseContent.ReadAsStringAsync();
String stringContents = stringContentsTask.Result;
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}

Related

Uploading files to sharepoint with RestSharp and their rest API is adding header and trailer lines to every file

I'm uploading to sharepoint using a c# client, and every file I Upload gets extra data included. A one line CSV file gets turned into a 7 line file that isn't usable. This is what my one line file upload turned into:
-----------AEE7A299-297A-41E0-B1CC-A72050FCDD28
Content-Disposition: form-data; name="ControlFile_RCTI_statement_20220218_145832.csv"; filename="ControlFile_RCTI_statement_20220218_145832.csv"
Content-Type: application/octet-stream
File;Class;Account Number;Effective Date;Product;Account Type;Document Name
-----------AEE7A299-297A-41E0-B1CC-A72050FCDD28--
My upload code is using restSharp
public async Task UploadFile(string filePath, string list, string folderPath)
{
await CheckTokenAsync();
var fileName = Path.GetFileName(filePath);
var endpoint = $"{spCredentials.sharepointSubSiteFullUrl}/_api/web/GetFolderByServerRelativeUrl('{list}/{folderPath}')/Files/Add(url='{fileName}', overwrite=false)";
var client = new RestClient(endpoint);
client.Timeout = 30000;
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", $"Bearer {token}");
request.AddHeader("Accept", "application/json;odata=verbose");
request.AddFile(fileName, filePath);
var response = await client.ExecuteAsync(request);
if (response.StatusCode == HttpStatusCode.OK)
{
var fileData = JsonConvert.DeserializeObject<SPSingleResultContainer>(response.Content);
var link = fileData.d.__metadata.uri;
await SendRequest<string>($"{link}/CheckIn()", Method.POST);
}
else
throw new Exception($"Upload Failed with message: " + response.ErrorMessage);
}
I've also added this question to the sharepoint SE at https://sharepoint.stackexchange.com/questions/300550/uploading-files-to-sharepoint-with-restsharp-and-their-rest-api-is-adding-header
Turned out RestSharp was doing a multipart upload, and sharepoint doesn't like that sort of thing. Other people have had This Issue with RestSharp
public async Task UploadFile(string filePath, string list, string folderPath)
{
var bytes = File.ReadAllBytes(filePath);
await UploadFileData(Path.GetFileName(filePath), list, folderPath, bytes);
return;
}
public async Task UploadFileData(string fileName, string list, string folderPath, byte[] fileData)
{
await CheckTokenAsync();
var endpoint = $"{spCredentials.sharepointSubSiteFullUrl}/_api/web/GetFolderByServerRelativeUrl('{list}/{folderPath}')/Files/Add(url='{fileName}', overwrite=false)";
var client = new RestClient(endpoint);
client.Timeout = 30000;
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", $"Bearer {token}");
request.AddHeader("Accept", "application/json;odata=verbose");
string contentType = "";
var fileType = Path.GetExtension(fileName).ToLower();
switch (fileType)//there are better ways to get the MIME type, I was just getting desperate and trying everything
{
case ".csv":
contentType = "text/csv";
break;
case ".xlsx":
contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
break;
case ".pdf":
contentType = "application/pdf";
break;
case ".html":
contentType = "text/html";
break;
default:
throw new NotImplementedException($"File type {fileType} not supported");
}
request.AddHeader("Content-Type", contentType);
request.AddParameter(contentType, fileData, ParameterType.RequestBody);
var response = await client.ExecuteAsync(request);
var test = JsonConvert.SerializeObject(request);
if (response.StatusCode == HttpStatusCode.OK)
{
var fileMetaData = JsonConvert.DeserializeObject<SPSingleResultContainer>(response.Content);
var link = fileMetaData.d.__metadata.uri;
await SendRequest<string>($"{link}/CheckIn()", Method.POST);
}
else
throw new Exception($"Upload {fileName} Failed with status {response.StatusCode} and message: " + response.ErrorMessage);
}
For anyone coming here that doesn't care about sharepoint, replacing .addfile with
request.AddHeader("Content-Type", contentType);
request.AddParameter(contentType, fileData, ParameterType.RequestBody);
where contentType is the MIME format of your file extension (or an empty string seems to work as well) solved the issue for me.

Unable to get token from tableau server

I am following below link to integrate tableau report on web application(asp .net mvc),
https://onlinehelp.tableau.com/current/server/en-us/trusted_auth.htm
https://onlinehelp.tableau.com/current/server/en-us/trusted_auth_webrequ.htm
Code :
var uri = "http://<server ip>:8000/trusted";
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add("username ", "<user>");
parameters.Add("target_site", "<site>");
var bodyParameters = new ArrayList();
foreach (var parameter in parameters)
{
bodyParameters.Add(string.Format("{0}={1}", HttpUtility.UrlEncode(parameter.Key), HttpUtility.UrlEncode(Convert.ToString(parameter.Value))));
}
string requestBody = String.Join("&", bodyParameters.ToArray());
var request = WebRequest.CreateHttp(uri);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
try
{
using (var writer = new StreamWriter(request.GetRequestStream()))
{
writer.Write(requestBody);
}
var response = (HttpWebResponse)request.GetResponse();
using (var reader = new StreamReader(response.GetResponseStream()))
{
String body = reader.ReadToEnd();
}
}
catch (Exception ex)
{
string str = ex.Message.ToString();
}
My machine is registered as trusted host on tableau server, still i am getting -1 when i request for token.

400 Bad Request when posting to Rest API over https

I'm trying to post a file in a json object to an external rest api over https. I have confirmed the json object is formatted correctly, do I have to do anything special to post to a rest api over https? I'm using the answer found over here as a guide: How to post JSON to the server?
private static void PostDatatoFTP(string FileName,
string fileString, string centerCode, string fileType) {
try {
byte[] plainTextBytes = Encoding.ASCII.GetBytes(fileString);
string base64File = Convert.ToBase64String(plainTextBytes);
FileInfo fileInfo = new FileInfo {
FileData = base64File,
FileName = FileName,
FileType = fileType,
FileVersion = _fileVersion
};
FileInfo[] transmitFileInfo = new FileInfo[1];
transmitFileInfo[0] = fileInfo;
Json jsonObject = new Json {
RequestType = _RequestType,
APIVersion = _apiVersion,
SubmissionId = Guid.NewGuid().ToString(),
UserId = _ftpUsername,
Password = _ftpPassword,
Vendor = _vendor,
CenterCode = centerCode,
FileInfo = transmitFileInfo
};
var json = JsonConvert.SerializeObject(jsonObject);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_uploadPath);
request.Method = "POST";
request.ContentType = "application/json";
using (var streamWriter = new StreamWriter(request.GetRequestStream())) {
streamWriter.Write(json);
}
var httpResponse = (HttpWebResponse)request.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream() ?? throw new InvalidOperationException())) {
var result = streamReader.ReadToEnd();
Console.WriteLine(result);
}
}
catch (WebException e) {
Console.WriteLine(e.Message);
String status = ((HttpWebResponse)e.Response).StatusDescription;
Console.WriteLine(status);
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
}
}

Rest API call for delete entity returns 403 error

Following code is aimed at deleting a row from table with given partition key and rowkey. But I get following request/response in fiddler. How can I correct the error?
Request
DELETE https://hireazurestorageacct.table.core.windows.net/mytable(PartitionKey='sample1',%20RowKey='0001')?timeout=20 HTTP/1.1
Accept: application/json;odata=nometadata
x-ms-date: Mon, 08 May 2017 17:59:14 GMT
x-ms-version: 2015-04-05
Accept-Charset: UTF-8
MaxDataServiceVersion: 3.0;NetFx
DataServiceVersion: 1.0;NetFx
If-Match: *
Content-Type: application/json
Authorization: SharedKeyLite hireazurestorageacct:3ZHX8lYBec+/9ytiNQb+JV5dpFkLAieuwB5veMkLVUU=
Host: hireazurestorageacct.table.core.windows.net
Response
HTTP/1.1 403 Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
Content-Length: 299
Content-Type: application/json
Server: Microsoft-HTTPAPI/2.0
x-ms-request-id: a9244f7f-0002-0048-0824-c8afc5000000
Date: Mon, 08 May 2017 17:59:14 GMT
{"odata.error":{"code":"AuthenticationFailed","message":{"lang":"en-US","value":"Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.\nRequestId:a9244f7f-0002-0048-0824-c8afc5000000\nTime:2017-05-08T17:59:14.9335100Z"}}}
Code
public static int DeleteEntity(string storageAccount, string accessKey, string tableName, string partitionkey, string rowkey)
{
string uri = $#"https://{storageAccount}.table.core.windows.net/{tableName}(PartitionKey='{partitionkey}', RowKey='{rowkey}')?timeout=20";
string resource = $#"{tableName}";
// Web request
var request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "DELETE";
request.Accept = "application/json;odata=nometadata";
request.Headers.Add("x-ms-date", DateTime.UtcNow.ToString("R", System.Globalization.CultureInfo.InvariantCulture));
request.Headers.Add("x-ms-version", "2015-04-05");
request.Headers.Add("Accept-Charset", "UTF-8");
request.Headers.Add("MaxDataServiceVersion", "3.0;NetFx");
request.Headers.Add("DataServiceVersion", "1.0;NetFx");
request.Headers.Add("If-Match", "*");
request.ContentType = "application/json";
// Signature string for Shared Key Lite Authentication must be in the form
// StringToSign = Date + "\n" + CanonicalizedResource
// Date
string stringToSign = request.Headers["x-ms-date"] + "\n";
// Canonicalized Resource in the format /{0}/{1} where 0 is name of the account and 1 is resources URI path
stringToSign += "/" + storageAccount + "/" + resource;
// Hash-based Message Authentication Code (HMAC) using SHA256 hash
var hasher = new HMACSHA256(Convert.FromBase64String(accessKey));
// Authorization header
string strAuthorization = "SharedKeyLite " + storageAccount + ":" + Convert.ToBase64String(hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes(stringToSign)));
// Add the Authorization header to the request
request.Headers.Add("Authorization", strAuthorization);
Thread.Sleep(1000);
// Execute the request
try
{
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (var r = new StreamReader(response.GetResponseStream()))
{
return (int)response.StatusCode;
}
}
}
catch (WebException ex)
{
// get the message from the exception response
using (var sr = new StreamReader(ex.Response.GetResponseStream()))
{
var res = sr.ReadToEnd();
// Log res if required
}
return (int)ex.Status;
}
}
Status 403 means you need to authenticate to access a resource. Any decent server will not give you anything that includes any information about the resource. So you will get the same reply, whether the resource is there or not.
According to your codes, I guess there are something wrong with your authorization token when you use the resource to generate the authorization token.
I suggest you could try below codes to delete the table entity.
Call method:
AzureTableHelper.DeleteEntity("{storageaccount}", "{accesskey}", "{tablename}", "{partitionkey}", "{rowkey}" );
Delete method:
public static int DeleteEntity(string storageAccount, string accessKey, string tableName, string partitionkey, string rowkey)
{
string host = string.Format(#"https://{0}.table.core.windows.net/", storageAccount);
string resource = string.Format(#"{0}", tableName) + string.Format("(PartitionKey='{0}',RowKey='{1}')", partitionkey, rowkey);
string uri = host + resource;
//if you want to check the etag you need firstly get the etag then delete the entity
//string jsonData = "";
//int responseCode = RequestResource(
// storageAccount,
// accessKey,
// resource,
// out jsonData);
//var jsonObject = JObject.Parse(jsonData);
//string time = jsonObject.GetValue("odata.etag").ToString();
//string time = obj.Timestamp;
// Web request
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri);
request.Method = "DELETE";
request.ContentType = "application/json";
request.Accept = "application/json;odata=nometadata";
request.Headers.Add("x-ms-date", DateTime.UtcNow.ToString("R", System.Globalization.CultureInfo.InvariantCulture));
request.Headers.Add("x-ms-version", "2015-04-05");
request.Headers.Add("If-Match", "*");
request.Headers.Add("Accept-Charset", "UTF-8");
request.Headers.Add("MaxDataServiceVersion", "3.0;NetFx");
request.Headers.Add("DataServiceVersion", "1.0;NetFx");
// Signature string for Shared Key Lite Authentication must be in the form
// StringToSign = Date + "\n" + CanonicalizedResource
// Date
string stringToSign = request.Headers["x-ms-date"] + "\n";
// Canonicalized Resource in the format /{0}/{1} where 0 is name of the account and 1 is resources URI path
stringToSign += "/" + storageAccount + "/" + resource;
// Hash-based Message Authentication Code (HMAC) using SHA256 hash
System.Security.Cryptography.HMACSHA256 hasher = new System.Security.Cryptography.HMACSHA256(Convert.FromBase64String(accessKey));
// Authorization header
string strAuthorization = "SharedKeyLite " + storageAccount + ":" + System.Convert.ToBase64String(hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes(stringToSign)));
// Add the Authorization header to the request
request.Headers.Add("Authorization", strAuthorization);
// Execute the request
try
{
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (System.IO.StreamReader r = new System.IO.StreamReader(response.GetResponseStream()))
{
string jsonResponse = r.ReadToEnd();
return (int)response.StatusCode;
}
}
}
catch (WebException ex)
{
// get the message from the exception response
using (System.IO.StreamReader sr = new System.IO.StreamReader(ex.Response.GetResponseStream()))
{
string res = sr.ReadToEnd();
// Log res if required
}
return (int)ex.Status;
}
}

REST POST to WCF Service

I'm trying to post to WCF service. I get this error
"You must write ContentLength bytes to the request stream before calling [Begin]GetResponse."
Code:
ASCIIEncoding encoding = new ASCIIEncoding();
string postData = "patron=WTM";
byte[] data = encoding.GetBytes(postData);
var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://localhost:8733/FileShareWebServices/UploadFile");
httpWebRequest.ContentType = "application/json; charset=utf-8";
httpWebRequest.Method = "POST";
httpWebRequest.ContentLength = data.Length;
httpWebRequest.GetRequestStream();
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}
Your posted code doesn't write anything to the request stream which is most likely the cause of the error. Once you get the request stream you should write to it the contents and the length, like this:
using (Stream requestStream = httpWebRequest.GetRequestStream)
{
requestStream.Write(data, 0, data.Length);
}
The complete code would look like this:
ASCIIEncoding encoding = new ASCIIEncoding();
string postData = "patron=WTM";
byte[] data = encoding.GetBytes(postData);
var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://localhost:8733/FileShareWebServices/UploadFile");
httpWebRequest.ContentType = "application/json; charset=utf-8";
httpWebRequest.Method = "POST";
httpWebRequest.ContentLength = data.Length;
//httpWebRequest.GetRequestStream();
// Code to write data to the stream
using (Stream requestStream = httpWebRequest.GetRequestStream)
{
requestStream.Write(data, 0, data.Length);
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}