This is the HTTP response I send from my API if there's an error.
return new System.Net.Http.HttpResponseMessage() { StatusCode = (System.Net.HttpStatusCode)System.Net.HttpStatusCode.BadRequest, ReasonPhrase = "Incoming element is null" };
which Postman sees correctly as
"statusCode": 400,
"reasonPhrase": "Incoming element is null",
So the API code is fine, however, when I call the API from my console application the HttpWebResponse using the following
var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://localhost/");
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
httpResponse.StatusCode is OK.
How do I get the returned StatusCode from the API to be accessible/visible in the calling console application.
The httpResponse is the "I am connected" response not the returned response from the API, that was in accessed using
using (var streamReader = new StreamReader(httpResponse.GetResponseStream())) {
string result = streamReader.ReadToEnd();
to stream the result back from the API which was the JSON response being picked up by Postman.
So instead I deserialised the returned JSON into an object and used that to make my validation checks, like so. First my storage class
public class ReturnedJSONModel {
public System.Net.HttpStatusCode statusCode { get; set; }
public string reasonPhrase { get; set; }
}
then this to populate it and handle the response (note this is a Console program so uses Console.WriteLine to report success/failure.
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
if (httpResponse.StatusCode == HttpStatusCode.OK) {
using (var streamReader = new StreamReader(httpResponse.GetResponseStream())) {
string result = streamReader.ReadToEnd();
ReturnedJSONModel objJSON = JsonConvert.DeserializeObject<ReturnedJSONModel>(result);
switch(objJSON.statusCode) {
case System.Net.HttpStatusCode.Accepted:
Console.WriteLine("Success : " + objJSON.reasonPhrase);
break;
case System.Net.HttpStatusCode.BadRequest:
Console.WriteLine("BadRequest : " + objJSON.reasonPhrase);
break;
case System.Net.HttpStatusCode.ServiceUnavailable:
Console.WriteLine("ServiceUnavailable : " + objJSON.reasonPhrase);
break;
default:
Console.WriteLine("Unknown error : " + objJSON.reasonPhrase);
break;
}
}
} else {
Console.WriteLine("Error StatusCode = " + httpResponse.StatusCode);
}
Related
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.
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);
}
}
I am having .NET code to call the google api in batch request for getting the message details for multiple Ids. The request I am creating, when run through postman it works perfectly but when run this console app it gives me the Response Status code = 0 and Error Specified value has invalid CRLF characters.\r\nParameter name: value
Can someone please look into this and help me ... I have searched almost everything now but could not get any solution.
Here is my code --
var baseUrl = "/gmail/v1/users/" + _accountID + "/messages/";
RestClient client = null;
RestRequest request = null;
StringBuilder sbBody = null;
for (int j = 0; j < _messageId.Count; j++)
{
msgCount++;
if (msgCount == 1)
{
boundary = "testing_batch";
sbBody = new StringBuilder();
client = new RestClient("https://www.googleapis.com/batch/");
request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "multipart/mixed; boundary=\"" + boundary + "\"");
request.AddHeader("Authorization", "Bearer " + accessToken);
}
sbBody.Append(string.Format("--{0}\n", boundary));
sbBody.Append("Content-Type: application/http\n\n");
sbBody.Append(string.Format("GET {0}{1}\n\n", baseUrl, _messageId[j]));
if (msgCount == 1)
sbBody.Append(string.Format("--{0}--", boundary));
if (msgCount == 1)
{
msgCount = 0;
//request.AddBody(sbBody.ToString());
request.AddHeader("RequestBody", sbBody.ToString());
IRestResponse response = client.Execute(request);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
//Do nothing for now
}
else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
{
Console.WriteLine(response.StatusCode);
Console.WriteLine(response.Content);
Console.ReadLine();
break;
}
else
{
Console.WriteLine(response.StatusCode);
Console.WriteLine(response.Content);
Console.ReadLine();
break;
}
}
I am trying to figure out a way of returning messages from a sub folder in outlook office 365 api.
Everything seems to point to this;
HttpResponseMessage response = await client.GetAsync("https://outlook.office365.com/api/v1.0/me/folders/inbox/childfolders/Odata/messages");
But I always get a bad request returned.
Here is my resource.
MSDN
Thanks Scott
The URL syntax is:
https://outlook.office365.com/api/v1.0/me/folders/<FOLDER ID>/Messages
So you need to get the ID for the folder you want to query. For example, if it's a subfolder of the Inbox, you could do a GET to:
https://outlook.office365.com/api/v1.0/me/folders/inbox/childfolders
And you'd get back something like:
{
"#odata.context": "https://outlook.office365.com/api/v1.0/$metadata#Me/Folders('inbox')/ChildFolders",
"value": [
{
"#odata.id": "https://outlook.office365.com/api/v1.0/Users('JasonJ#contoso.com')/Folders('AAMkADNhMjcxM2U5LWY2MmItNDRjYy05YzgwLWQwY2FmMTU1MjViOAAuAAAAAAC_IsPnAGUWR4fYhDeYtiNFAQCDgDrpyW-uTL4a3VuSIF6OAAAeY0W3AAA=')",
"Id": "AAMkADNhMjcxM2U5LWY2MmItNDRjYy05YzgwLWQwY2FmMTU1MjViOAAuAAAAAAC_IsPnAGUWR4fYhDeYtiNFAQCDgDrpyW-uTL4a3VuSIF6OAAAeY0W3AAA=",
"ParentFolderId": "AAMkADNhMjcxM2U5LWY2MmItNDRjYy05YzgwLWQwY2FmMTU1MjViOAAuAAAAAAC_IsPnAGUWR4fYhDeYtiNFAQCDgDrpyW-uTL4a3VuSIF6OAAAAAAEMAAA=",
"DisplayName": "New Subfolder",
"ChildFolderCount": 0
}
]
}
Then take the value of the Id field and plug it into the URL:
https://outlook.office365.com/api/v1.0/me/folders/AAMkADNhMjcxM2U5LWY2MmItNDRjYy05YzgwLWQwY2FmMTU1MjViOAAuAAAAAAC_IsPnAGUWR4fYhDeYtiNFAQCDgDrpyW-uTL4a3VuSIF6OAAAeY0W3AAA=/Messages
public void EnsureConnectionValid()
{
if (AuthenticationContext == null)
{
AuthenticationContext = new AuthenticationContext(authority);
AuthenticationResult = AuthenticationContext.AcquireToken(resource, clientId, new Uri(redirectUri), PromptBehavior.Auto);
}
}
public async Task<string> GetFolderId(string Path)
{
EnsureConnectionValid();
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AuthenticationResult.AccessToken);
var restCommand = "https://outlook.office365.com/api/v1.0/me/folders/Inbox/childfolders?$filter=DisplayName eq " + "'" + Path + "'";
HttpResponseMessage response = await client.GetAsync(restCommand);
response.EnsureSuccessStatusCode();
string jsonMessage;
using (var responseStream = await response.Content.ReadAsStreamAsync())
{
jsonMessage = new StreamReader(responseStream).ReadToEnd();
}
var folderObject = JObject.Parse(jsonMessage)["value"].ToObject<FoldersList[]>();
return folderObject.Select(r => r.Id).SingleOrDefault();
}
IF I remove
.spec(responseSpec)
from my call, the response prints fine at "FOO". If I include the builder, the response prints an empty string (even though the test is passing). Anyone know why, or how to fix this? I would like to use the builder and print the response of the passing test.
public void getCirclesId()
{
String endpoint = "getCirclesId";
String url = baseUrl + resourcePath + "/" + circleId;
RequestSpecification given = given().header("Authorization", RestTest.BEARER_TOKEN);
ResponseSpecBuilder specBuilder = new ResponseSpecBuilder();
specBuilder.expectBody("features.priceMonth", is("5.00"));
specBuilder.expectBody("features.priceYear", is("50.00"));
Response response = JsonTest.executeRequestWithSpec(given, url, resource, endpoint, JsonTest.HttpType.GET, specBuilder);
}
...
public static Response executeRequestWithSpec(RequestSpecification given, String url, String resource, String endpoint, HttpType type, ResponseSpecBuilder builder)
{
Response response = null;
try {
switch (type) {
case GET:
response = executeGetRequestWithSpec(given, url, builder);
break;
case POST:
response = executePostRequestWithSpec(given, url, builder);
break;
case PUT:
response = executePutRequestWithSpec(given, url, builder);
break;
case DELETE:
response = executeDeleteRequestWithSpec(given, url, builder);
break;
}
System.out.println(resource + " - " + endpoint + ": " + response.print());
} catch (AssertionError e) {
RestTest.failCount++;
System.err.println(resource + " - " + endpoint + " Error: " + e.getMessage());
}
return response;
}
private static Response executeGetRequestWithSpec(RequestSpecification given, String url, ResponseSpecBuilder builder)
{
ResponseSpecification responseSpec = builder.build();
Response response = given.when().get(url + ".json").then().assertThat().statusCode(200).spec(responseSpec).extract().response();
System.out.println("FOOOO" + response.print());
return response;
}
Are you using the latest version of REST Assured (currently 2.3.0)? Otherwise I suggest you to upgrade to this version. There was some problems with response specifications in 2.0.