REST POST to WCF Service - rest

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();
}

Related

How to call PUT on Moodle with PutAsync?

I am trying to modernize some calls to Moodle REST APIs.
Everything is doing OK as long as I use querystring, but I can't pinpoint why using a PutAsync doesn't work in this case (tested with Postman, it works):
using (var httpClient = _httpClientFactory.CreateClient())
{
var url = "http://127.0.0.1/moodle/webservice/rest/server.php";
var urlFunction = UrlFunction.core_user_create_users.ToString();
var urlFormat = UrlFormat.json.ToString();
var requestModel = new GetCoursesRequestModel()
{
wstoken = [token],
wsfunction = urlFunction,
moodlewsrestformat = urlFormat
};
var jsonRequest = JsonConvert.SerializeObject(requestModel);
var stringContentRequest = new StringContent(jsonRequest, Encoding.UTF8, "application/json");
var response = await httpClient.PutAsync(url, stringContentRequest);
response.EnsureSuccessStatusCode();
var courseDtos = await response.Content.ReadFromJsonAsync<List<MoodleAPIDtosCourseDto>>();
if (courseDtos is null)
throw new InputFormatterException(
$"Pb with response format.");
}
ยดยดยดยด
The error is generated when I try to read my response at await response.Content.ReadFromJsonAsync()

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);
}
}

Azure Storage Service throws 403 forbidden error when trying to call REST API to clear queue messages

I'm trying to clear all azure storage queue message via Queue Service REST API. I've verified that the code is correct, but it still returns a 403 forbidden error. The "StorageSharedKey" and "StorageAccountName" are correct since I'm able to connect to the azure queue using those values in the connection string for the azure queue client. The storage version I'm using is "2015-12-11".
Here is the code:
internal void ClearStorageQueueMessages(string queueName)
{
const string requestMethod = "DELETE";
string urlPath = $"{queueName}/messages";
var dateInRfc1123Format = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);
var canonicalizedHeaders = $"x-ms-date:{dateInRfc1123Format}\nx-ms-version:{StorageVersion}";
var canonicalizedResource = $"/{StorageAccountName}/{urlPath}";
var uri = new Uri($"https://{StorageAccountName}.queue.core.windows.net/{urlPath}");
var response = MakeDeleteRestCall(uri, requestMethod, dateInRfc1123Format, canonicalizedHeaders, canonicalizedResource);
}
internal RestResponse MakeDeleteRestCall(Uri uri, string requestMethod, string dateInRfc1123Format, string canonicalizedHeaders,
string canonicalizedResource)
{
var restResponse = new RestResponse();
var stringToSign = $"{requestMethod}\n\n\n\n\n\n\n\n\n\n\n\n{canonicalizedHeaders}\n{canonicalizedResource}";
var authorizationHeader = CreateAuthorizationHeader(stringToSign);
var request = (HttpWebRequest) WebRequest.Create(uri);
request.Method = requestMethod;
request.Headers.Add("x-ms-date", dateInRfc1123Format);
request.Headers.Add("x-ms-version", StorageVersion);
request.Headers.Add("Authorization", authorizationHeader);
//request.Accept = "application/atom+xml,application/xml";
request.Accept = "application/json";
//request.ContentType = "application/json";
using (var response = (HttpWebResponse) request.GetResponse())
{
restResponse.StatusCode = response.StatusCode;
var responseStream = response.GetResponseStream();
if (responseStream == null)
return restResponse;
using (var reader = new StreamReader(responseStream))
{
restResponse.ReturnedContent = reader.ReadToEnd();
}
}
return restResponse;
}
internal static string CreateAuthorizationHeader(string canonicalizedString)
{
string signature;
using (var hmacSha256 = new HMACSHA256(Convert.FromBase64String(StorageSharedKey)))
{
var dataToHmac = Encoding.UTF8.GetBytes(canonicalizedString);
signature = Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac));
}
var authorizationHeader = string.Format(CultureInfo.InvariantCulture, "{0} {1}:{2}", StorageSharedKey,
StorageAccountName, signature);
return authorizationHeader;
}
The problem seems to be with the header Authorization. Please check the format according to the documentation:
Authorization="[SharedKey|SharedKeyLite] :"
https://msdn.microsoft.com/en-us/library/azure/dd179428.aspx
Your function adds the shared key in plain text instead of the authorization scheme "SharedKey" or "SharedKeyLite".