I have developed a C# application that calls a REST service existing in some PC in the network.
This is the code to make a request:
public async Task<bool> OpenDoorAsync(string name, int delay)
{
var data = await CallApiAsync("api/door/remoteOpenByName", new Dictionary<string, string> { { "doorName", name }, { "interval", delay.ToString() } });
return data.IsSuccess;
}
private async Task<ResponseData> CallApiAsync(string endPoint, Dictionary<string, string> parameters)
{
try
{
using (HttpClient client = new HttpClient())
{
client.Timeout = TimeSpan.FromSeconds(30);
client.DefaultRequestHeaders.Connection.ParseAdd("keep-alive");
var content = new StringContent(string.Empty, Encoding.UTF8, "application/json");
string fullUri = "http://192.168.0.122:8088/api/door/remoteOpenByName?doorName=10.185.85.237-1&interval=5&access_token=1234";
HttpResponseMessage response = await client.PostAsync(fullUri, content);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<ResponseData>(responseBody);
}
}
catch (Exception ex)
{
OnError("Existió un error al realizar la llamada.", ex);
return new ResponseData()
{
message = "failed"
};
}
}
Entry point is OpenDoorAsync, called this way, from a Winform form:
await _device.OpenDoorAsync(TxtNombrePuerta.Text.Trim(), IntInterval.Value);
Well, after the execution of PostAsync method, a HTTP 500 error is returned:
{StatusCode: 500, ReasonPhrase: 'Internal Server Error', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Connection: close
Date: Thu, 28 Jan 2021 21:06:35 GMT
Set-Cookie: JSESSIONID=4062B932CDB44B4CA3FCCC275937AC15; Path=/; HttpOnly
Server: Apache-Coyote/1.1
Content-Length: 2580
Content-Language: en
Content-Type: text/html; charset=utf-8
}}
However, if I make the same request using Google Chrome RESTED extension, it works perfectly:
Just in case, I analyzed Google Chrome developer tools after the RESTED call and I have not found anything weird. I thought maybe I missed to send something else in the headers.
Does anybody know what is happening with the call from the C# application? Clearly, I am not doing something that RESTED is.
I don't really know why it does not work when using HttpClient class, however, I solved the problem installling an using RestSharp NuGet package.
Finally, the code was reduced to this:
private ResponseData CallApi(string endPoint, Dictionary<string, string> parameters)
{
try
{
string fullUri = $"http://{GetServerIp()}:{((MainWindow)MainWindow).ServerPort}/{endPoint}?{GetQueryParameters(parameters)}";
var client = new RestClient(fullUri);
var request = new RestRequest(Method.POST);
var response = client.Execute(request);
return JsonConvert.DeserializeObject<ResponseData>(response.Content);
}
catch (Exception ex)
{
OnError("Existió un error al realizar la llamada.", ex);
return new ResponseData()
{
message = "failed"
};
}
}
Your working example is passing cookies, which may be required for the API you're calling.
Related
I am trying to consume a POST service to be able to send images, but when I run it through Postman, I get this error.
I am making the call of that service through another api to be able to test it by Postman, it happens that when I do it and paste the image I get that 415 error. What could be happening?
{StatusCode: 415, ReasonPhrase: '', Version: 1.1, Content: System.Net.Http.HttpConnection+HttpConnectionResponseContent, Headers: { X-AREQUESTID: 1196x14887183x1 X-ANODEID: node2 X-XSS-Protection: 1; mode=block X-Content-Type-Options: nosniff X-Frame-Options: SAMEORIGIN Content-Security-Policy: frame-ancestors 'self' X-ASEN: SEN-17699581 Set-Cookie: JSESSIONID=4548966F3B9BAFC283932093C14B6CF7; Path=/; Secure; HttpOnly Set-Cookie: atlassian.xsrf.token=BYCQ-GVBW-0E9H-MNTX_18760f22f63318f1c8b814586ccf9952dcfe353d_lin; Path=/; Secure X-Seraph-LoginReason: OK X-ASESSIONID: 1amnj3o X-AUSERNAME: glgarcia Date: Wed, 09 Nov 2022 23:56:45 GMT Content-Type: text/html; charset=UTF-8 Content-Length: 0 }}
Here's the Web API side:
public async Task<IActionResult> CreateImagenesQuejasOpinionesSugerencia([FromForm] QuejasSugerenciaOpinionesImagenesRequest quejasImagenesRequest,string issueKey)
{
QuejasSugerenciaOpinionesImagenesResponse.Root quejasImagenesResponse = new QuejasSugerenciaOpinionesImagenesResponse.Root();
//return System.Convert.ToBase64String(textAsBytes);
try
{
using (var client = new HttpClient())
{
// Setting Base address.
client.BaseAddress = new Uri($"https://gestiondecasos.humano.local/");
// Initialization.
HttpResponseMessage response = new HttpResponseMessage();
// HTTP POST
var imagenGuardo = quejasImagenesRequest.ConvertToBase64();
response = await client.PostAsJsonAsync($"rest/api/2/issue/{issueKey}/attachments", imagenGuardo).ConfigureAwait(false);
// Verification
if (response.IsSuccessStatusCode)
{
// Reading Response.
var result = await response.Content.ReadAsStringAsync();
quejasImagenesResponse = JsonConvert.DeserializeObject<QuejasSugerenciaOpinionesImagenesResponse.Root>(result);
}
}
return Ok(quejasImagenesResponse);
}
catch (HttpRequestException ex)
{
return Ok(ex.Message);
}
finally
{
}
}
I am making the call of that service through another api to be able to
test it by Postman, it happens that when I do it and paste the image I
get that 415 error. What could be happening?
Well, based on your error message couple of reason there might be of having that error, After my investigation I concluded into following findings:
Content-Type: text/html:
In your error message its clear that you have sent the content as Content-Type: text/html; however, your controller is expecting [FromForm]. From postman you should submit your request as following:
Model:
As you haven't shared your request model details therefore, I made the model as following to simulate the test.
public class QuejasSugerenciaOpinionesImagenesRequest
{
public string name { get; set; }
public IFormFile files { get; set; }
}
Controller:
[HttpPost]
public async Task<IActionResult> CreateImagenesQuejasOpinionesSugerencia([FromForm] QuejasSugerenciaOpinionesImagenesRequest quejasImagenesRequest, string issueKey)
{
string fileInBase64;
try
{
using (var ms = new MemoryStream())
{
quejasImagenesRequest.files.CopyTo(ms);
var fileBytes = ms.ToArray();
fileInBase64 = Convert.ToBase64String(fileBytes);
// act on the Base64 data
}
using (var client = new HttpClient())
{
// Setting Base address.
client.BaseAddress = new Uri($"http://localhost:5094/");
// Initialization.
HttpResponseMessage response = new HttpResponseMessage();
// HTTP POST
response = await client.PostAsJsonAsync($"api/rest/issue/{issueKey}/attachments", fileInBase64).ConfigureAwait(false);
// Verification
if (response.IsSuccessStatusCode)
{
// Reading Response.
var result = await response.Content.ReadAsStringAsync();
//quejasImagenesResponse = JsonConvert.DeserializeObject<QuejasSugerenciaOpinionesImagenesResponse.Root>(result);
}
}
return Ok("");
}
catch (HttpRequestException ex)
{
return Ok(ex.Message);
}
finally
{
}
}
API Test Controller:
[Route("api/[controller]")]
[ApiController]
public class RestController : ControllerBase
{
[HttpPost("issue/{issue}/attachments")]
public IActionResult Rest([FromRoute]string issue, [FromBody]string attachments)
{
return Ok(attachments);
}
}
Output:
Note:
I have simulate the test from postman using from-date format and send request to API CreateImagenesQuejasOpinionesSugerencia which is type of [FromForm] thus I have sent one image file and one addtional parameter as you can see the sreenshot, it hits the controller thereafter, convert it as based64 and finally submit another request to PostAsJsonAsync($"api/rest/issue/{issueKey}/attachments" API endpoint which successfully reach the endpoint. If you still have any confusion please feel free to let me know.
OK. So this is really starting to baffle me now. I can get this to work on one UWP app, but not this one.
I have this piece of code to post:
public async Task<string> SubmitDataWithTokenAsync(string url, string token)
{
var httpClient = new HttpClient();
HttpResponseMessage response;
try
{
var root = new
{
fields = new Dictionary<string, string>
{
//General Parameters...
//Inspection Parameters...
//Startup Parameters...
//Mechanical Parameters...
//Electrical Parameters...
//SCR Parameters...
//Shutdown Parameters...
}
};
var s = new JsonSerializerSettings { DateFormatHandling = DateFormatHandling.MicrosoftDateFormat };
var content = JsonConvert.SerializeObject(root, s);
var request = new HttpRequestMessage(HttpMethod.Post, url);
//Add the token in Authorization header
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
request.Content = new StringContent(content, Encoding.UTF8, "application/json");
response = await httpClient.SendAsync(request);
var responseString = await response.Content.ReadAsStringAsync();
return responseString;
}
catch (Exception ex)
{
return ex.ToString();
}
}
}
the content comes back just fine, so it seems....
"{\"fields\":{\"Date\":\"8/16/2018 2:18:48 PM -04:00\",\"Maximo\":null,\"IBX\":\"DC4\",\"Generator\":\"Generator D\",\"AirQuality\":\"Red / Unhealthy\",\"Engineer\":\"Kassim Ganiyou\",\"MT1Level\":null,\"MT2Level\":null,\"StartDTLevel\":null,\"BC1V\":null,\"BC1A\":null,\"BC2V\":null,\"BC2A\":null,\"StartCoolantTEmp\":null,\"StartHours\":null,\"Reason\":null,\"InspectionNotes\":null,\"StartTime\":null,\"CrankV1\":null,\"CrankV2\":null,\"Emissions\":null,\"SCRStartTime\":null,\"OilPressure\":null,\"CoolantTemp\":null,\"BatteryVolt\":null,\"LeftExhTemp\":null,\"RightExhTemp\":null,\"ABVolts\":null,\"BCVolts\":null,\"CAVolts\":null,\"AAmps\":null,\"BAmps\":null,\"CAmps\":null,\"KW\":null,\"Frequency\":null,\"SCROutletTemp\":null,\"NOx\":null,\"UReaFLow\":null,\"Alarms\":null,\"SCRSTopTime\":null,\"StopTime\":null,\"StopHours\":null}}"
The request comes back:
{Method: POST, RequestUri: 'https://graph.microsoft.com/v1.0/sites/root/lists/A07CEC93-XXXX-XXXX-XXXX-0F756D2EF63A/items', Version: 2.0, Content: System.Net.Http.StringContent, Headers:
{
Authorization: Bearer eyJ0eX...PUQ
Content-Type: application/json; charset=utf-8
Content-Length: 603
}}
But then the response is:
{StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
client-request-id: bb26e6fe-4fae-41ae-921d-aeb39063bd8e
Strict-Transport-Security: max-age=31536000
request-id: bb26e6fe-4fae-41ae-921d-aeb39063bd8e
Transfer-Encoding: chunked
x-ms-ags-diagnostic: {"ServerInfo":{"DataCenter":"East US","Slice":"SliceC","Ring":"5","ScaleUnit":"001","Host":"AGSFE_IN_1","ADSiteName":"EUS"}}
Duration: 319.5961
Cache-Control: private
Date: Thu, 16 Aug 2018 20:03:10 GMT
Content-Type: application/json
}}
I have another UWP app going to the same sharepoint site and I get a Status 201 no problem. I am just not seeing where my issue is in this case.
This is why it is good to take a break from a project and come back to it later.
I found out that I had mistyped ONE letter on the SharePoint list. So today when I reviewed the response code it pointed it our to me.
The code WAS good.
Thanks all.
I am attempting to write a password reset application c# and the graph API. I have set permissions for the application within Azure, receive a valid token, and can request information.
I am receiving a 400 Bad Request response when attempting to perform the reset. I believe I am forming the URL incorrectly. Here is the response I receive followed by my code.
Thanks in advance!
Response: StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Transfer-Encoding: chunked
request-id: omitted
client-request-id: omitted
x-ms-ags-diagnostic: {"ServerInfo":{"DataCenter":"North Central US","Slice":"SliceA","Ring":"3","ScaleUnit":"002","Host":"AGSFE_IN_29","ADSiteName":"CHI"}}
Duration: 43.0949
Strict-Transport-Security: max-age=31536000
Cache-Control: private
Date: Mon, 02 Apr 2018 18:06:06 GMT
Content-Type: application/json
}
private static async Task ResetPasswordAsync(HttpClient client, string UPN)
{
var payload = new
{
accountEnabled = true,
passwordProfile = new
{
forceChangePasswordNextSignIn = true,
password = "Password!"
}
};
var payloadJSON = JsonConvert.SerializeObject(payload);
Console.WriteLine(payloadJSON);
HttpMethod method = new HttpMethod("PATCH");
string requestUrl = $"https://graph.microsoft.com/v1.0/users/{UPN}?api-version=1.6";
var request = new HttpRequestMessage(method, requestUrl)
{
Content = new StringContent($"{payloadJSON}", Encoding.UTF8, "application/json")
};
var response = await client.SendAsync(request);
Console.WriteLine("Response: " + response);
if (!response.IsSuccessStatusCode)
{
throw new InvalidOperationException(response.ReasonPhrase);
}
}
According to 400 Bad Request, we could know that there is something wrong with http request. In your case, you could use Fiddler to catch the htt prequest, we could get Query parameter api-version not allowed. So you could remove the api version from the requesturl.
We could get more information about update use from Graph Update user API
PATCH /users/{id | userPrincipalName}
We also need to add the Authorization in the request header.
string requestUrl = $"https://graph.microsoft.com/v1.0/users/{UPN}";
var token ="Bearer eyJ0eXAiOiJKV1QiLCJub25jZSI6IkFRQUJBQUFBQUFCSGg0...."
...
request.Headers.Add("Authorization", token);
var response = await client.SendAsync(request);
I need to connect to a server we have here at the library so that I can use some internal API features.
This sever uses OWIN to authenticate, and I need to use cookies to help with the authentication. I've looked through a ton of examples on SO on how to use HttpClient with cookies, but I'm obviously still doing something wrong.
I set up this little test app, to try it, but I keep on getting an Interal Server Error:
{StatusCode: 500, ReasonPhrase: 'Internal Server Error', Version: 1.1,
Content: System.Net.Http.StreamContent, Headers:{
Content-Security-Policy: script-src 'unsafe-eval' 'self'
cdnjs.cloudflare.com X-SourceFiles:
=?UTF-8?B?kjsdf83r3748ryefhkr4389r=?= X-UA-Compatible: IE=edge X-Frame-Options: SAMEORIGIN Date: Mon, 15 Aug 2016 14:37:28 GMT
Server: Microsoft-IIS/10.0 Content-Length: 3312 Content-Type:
application/json; charset=utf-8}}
Here is my little test app:
static void Main(string[] args)
{
Console.WriteLine("Connecting to Spock Library System...");
GenerateBookLoan();
}
private static void GenerateBookLoan()
{
DateTime dueDate_Begin = DateTime.Today;
DateTime dueDate_End = DateTime.Today.AddDays(13);
var dueDate_Range = new Dictionary<string, string>
{
{"BeginDueDate", dueDate_Begin.ToString()},
{"EndDueDate", dueDate_End.ToString()}
};
var json = JsonConvert.SerializeObject(dueDate_Range);
var credentials = new NetworkCredential("library_API", "xxxxxxxxxxxxxx");
var handler = new HttpClientHandler { Credentials = credentials, UseCookies = true };
var cookies = new CookieContainer();
handler.CookieContainer = cookies;
using (var http = new HttpClient(handler))
{
try
{
http.BaseAddress = new Uri("http://localhost:63432/");
IEnumerable<Cookie> responseCookies = cookies.GetCookies(http.BaseAddress).Cast<Cookie>();
HttpResponseMessage response = http.PostAsync("api/books/loans/add",
new StringContent(json, Encoding.UTF8, "application/json")).Result;
Console.WriteLine(response);
//do stuff//
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
Console.WriteLine("Done.");
Console.ReadLine();
}
I need some advice on where to go next. I've read through a ton of answers on here, but I can't seem to find one that fits my needs.
Thanks!
I'm trying to download a JSON string in my Windows Store App which should look like this:
{
"status": "okay",
"result": {"id":"1",
"type":"monument",
"description":"The Spire",
"latitude":"53.34978",
"longitude":"-6.260316",
"private": "{\"tag\":\"david\"}"}
}
but I'm getting what looks like info about the server. The output I'm getting is as follows:
Response: StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
MS-Author-Via: DAV
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Date: Thu, 22 Nov 2012 15:13:53 GMT
Server: Apache/2.2.22
Server: (Unix)
Server: DAV/2
Server: PHP/5.3.15
Server: with
Server: Suhosin-Patch
Server: mod_ssl/2.2.22
Server: OpenSSL/0.9.8r
X-Powered-By: PHP/5.3.15
Content-Length: 159
Content-Type: text/json
}
I've been looking around and see that WebClient was used before Windows 8, and is now replaced with HttpClient. So instead of using DownloadString(), I've been using Content.ReadAsString(). Here's the bit of code I have so far:
public async Task<string> GetjsonStream()
{
HttpClient client = new HttpClient();
string url = "http://(urlHere)";
HttpResponseMessage response = await client.GetAsync(url);
Debug.WriteLine("Response: " + response);
return await response.Content.ReadAsStringAsync();
}
Anyone know where I'm going wrong?
Thanks in advance!
You are outputting the server response. The server response contains a StreamContent (see documentation here) but this StreamContent doesn't define a ToString, so the class name is output instead of the content.
ReadAsStringAsync (documentation here) is the right method to get the content sent back by the server. You should print out the return value of this call instead:
public async Task<string> GetjsonStream()
{
HttpClient client = new HttpClient();
string url = "http://(urlHere)";
HttpResponseMessage response = await client.GetAsync(url);
string content = await response.Content.ReadAsStringAsync();
Debug.WriteLine("Content: " + content);
return content;
}
If you are inside await block you might need to get the Result ReadAsStringAsync().Result.
Example:
public async Task<HttpResponseMessage> Listen()
{
await Request.Content.ReadAsMultipartAsync<MultipartMemoryStreamProvider>(
new MultipartMemoryStreamProvider()).ContinueWith(task =>
{
MultipartMemoryStreamProvider multipartMemoryStreamProvider = task.Result;
var imageContent = multipartMemoryStreamProvider.Contents.First();
string name = imageContent.Headers.ContentDisposition.Name;
string fileName = imageContent.Headers.ContentDisposition.FileName;
data = imageContent.ReadAsByteArrayAsync().Result;
string content = multipartMemoryStreamProvider.Contents.Last().ReadAsStringAsync().Result;
model = multipartMemoryStreamProvider.Contents.Last().ReadAsAsync<RecordingModel>().Result;
}
);
}