I am trying to make a POST request in an UWP C# app, based on this example - Method A.
The code for my example is:
string scriptname = "myscript.php";
var content = new FormUrlEncodedContent(values);
//Exception Line (103):
var response = await client.PostAsync("https://myserver.ddns.net/" + scriptname, content);
var responseString = await response.Content.ReadAsStringAsync();
string SJson = responseString.ToString();
messagedialog.Content = SJson;
Exception log:
System.Net.Http.HttpRequestException
HResult=0x80072F0D
Message=An error occurred while sending the request.
Source=System.Net.Http
StackTrace:
at System.Net.Http.HttpClientHandler.d__86.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Net.Http.HttpClient.d__58.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
at Aplikacija_iFE.MainPage.d__10.MoveNext() in D:\Onedrive\myproject\myproject\App\App\MainPage.xaml.cs:line 103
Inner Exception 1:
COMException: The text associated with this error code could not be found.
Overitelj digitalnih potrdil ni veljaven ali pa je napačen
The bold string is in my native language and tells me that the CA is invalid or wrong (Basically it is ,because I signed it myself). Can this error be fixed temporarily with some C# code or must I replace the certificate?
My HTTPS (Apache) server is on a Debian 9 machine.
Edit (10:20 PM): Working code
The following code works for now, but it is ugly, highly insecure, and just a shane for me as a student who's new to programming :|
string scriptname = "MyRestAPI.php";
HttpFormUrlEncodedContent content = new HttpFormUrlEncodedContent(values);
HttpResponseMessage response = new HttpResponseMessage();
try
{
client = new HttpClient();
response = await client.PostAsync(new Uri("https://myserver.ddns.net/" + scriptname), content);
}
catch (Exception e)
{
HttpBaseProtocolFilter filter = new HttpBaseProtocolFilter();
ChainValidationResult[] results = new ChainValidationResult []
{
ChainValidationResult.Untrusted, ChainValidationResult.WrongUsage,
ChainValidationResult.BasicConstraintsError, ChainValidationResult.Expired,
ChainValidationResult.IncompleteChain, ChainValidationResult.InvalidCertificateAuthorityPolicy,
ChainValidationResult.InvalidName, ChainValidationResult.OtherErrors,
ChainValidationResult.RevocationFailure, ChainValidationResult.RevocationInformationMissing,
ChainValidationResult.Revoked, ChainValidationResult.UnknownCriticalExtension
};
for(int i=0;i<results.Length;i++)
{
try
{
filter.IgnorableServerCertificateErrors.Add(results[i]);
client = new HttpClient(filter);
response = await client.PostAsync(new Uri("https://myserver.ddns.net/" + scriptname), content);
}
catch
{
continue;
}
}
client = new HttpClient(filter);
response = await client.PostAsync(new Uri("https://myserver.ddns.net/" + scriptname), content);
}
finally
{
client.Dispose();
}
messagedialog.Content = response.Content.ToString();
You can wither use a config to ignore this error in development environment or make your client to trust the certificate, i.e just add the certificate to your trusted root on your client.
Related
currently im facing a problem when calling the ReadAsStringAsync() Method on HttpResponseMessage. When i call the GetAsync() Method on the HttpClient class i read the Contents from the Content property with ReadAsStringAsync(). Normally i would get a JSON string returned, but i always get System.ObjectDisposedException thrown.
Setting the parameter disposeHandler on the HttpClient constructor to false still does not resolve the problem. The Code in particular:
internal async Task<T> HandleMessage<T>(HttpResponseMessage message)
{
string jsonContent = await message.Content.ReadAsStringAsync(); // Error on this line
return JsonConvert.DeserializeObject<T>(jsonContent);
}
I would pass the type and the the response message of the GetAsync()Method.
internal async Task<T> GetRequest<T>(string route)
{
var response = await _httpClient.GetAsync(new Uri(_baseUrl,route));
return await HandleMessage<T>(response);
}
This is the Method i use to call the HandleMessage Method
EDIT:
I forgot some things to mention. Im currently calling the Nextcloud API. When i get a 401 Unauthorized the Exception gets thrown. This itself is not the Problem. I have the NetworkException() Method which takes the Exception and throws a custom Exception.
On a 200 Response Code everything works.
Additonal Code:
Here is my main method. From here i would call my Method GetAllUsers()
Uri url = new Uri("https://192.168.178.30");
SiliconAuthentication siliconAuthentication = new SiliconAuthentication("cloudadmin", "token");
SiliconCloud.SiliconCloud silicon = new SiliconCloud.SiliconCloud(url,siliconAuthentication);
try
{
silicon.SiliconUserInstruction.GetAllUsers().Wait();
}
catch (SiliconNetworkException sne)
{
Console.WriteLine(sne.Message + Environment.NewLine + "Meta Message: " + sne.MetaMessage + Environment.NewLine+"Meta Statuscode: " + sne.StatusCode);
}
Declaring the route and calling the GetRequest Method:
public async Task<SiliconOCSResponse<SiliconResponseAvailableUser>> GetAllUsers()
{
string apiRoute = "/ocs/v2.php/cloud/users";
return await _siliconNetwork.GetRequest<SiliconOCSResponse<SiliconResponseAvailableUser>>(apiRoute);
}
Calling the GetRequest with the api route
internal async Task<T> GetRequest<T>(string route)
{
var response = await _httpClient.GetAsync(new Uri(_baseUrl, route));
try
{
response.EnsureSuccessStatusCode();
}
catch (HttpRequestException eax) // A HTTP error occurs
{
await NetworkException(route, response, eax);
}
return await HandleMessage<T>(response);
}
Network Exception Method throwing a custom exception
internal async Task NetworkException(string route, HttpResponseMessage message, HttpRequestException innerEx)
{
var ms = await message.Content.ReadAsStringAsync(); // Error here
throw new SiliconNetworkException($"Unknown Network Error occured trying to connect to {route}. See Inner Exception for more information",
innerEx,
JsonConvert.DeserializeObject<SiliconOCSResponse<List<string>>>(ms)
);
}
As requested here is the constructor where the HttpClient is initialized
public SiliconNetwork(Uri url, SiliconAuthentication siliconAuth)
{
// https://github.com/nextcloud/server/issues/7753
_httpClient = new HttpClient(new HttpClientHandler() { UseCookies = false });
_httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(ContentType.TypeJSON));
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes($"{siliconAuth.UserName}:{siliconAuth.Password}")));
this._httpClient.DefaultRequestHeaders.Add("OCS-APIRequest", "true");
this._baseUrl= url;
this._siliconAuthentication = siliconAuth;
}
Additionally the stack trace:
at System.Net.Http.HttpContent.CheckDisposed()
at System.Net.Http.HttpContent.ReadAsStringAsync()
at SiliconCloud.Network.SiliconNetwork.<NetworkException>d__22.MoveNext() in C:\Users\Weasel\source\repos\Silicon\SiliconCloud\Network\SiliconNetwork.cs:line 233
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at SiliconCloud.Network.SiliconNetwork.<GetRequest>d__16`1.MoveNext() in C:\Users\Weasel\source\repos\Silicon\SiliconCloud\Network\SiliconNetwork.cs:line 174
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at SiliconCloud.UserManagement.UserProvisioning.SiliconUserInstruction.<GetAllUsers>d__17.MoveNext() in C:\Users\Weasel\source\repos\Silicon\SiliconCloud\UserManagement\UserProvisioning\SiliconUserInstruction.cs:line 278
As mentioned by Jimi in the comments the problem seems to be with EnsureSucessStatusCode() Method which disposes everything after the Exception gets thrown.
internal async Task<T> GetRequest<T>(string route)
{
var response = await _httpClient.GetAsync(new Uri(_baseUrl, route));
if(!response.IsSuccessStatusCode)
{
await NetworkException(route, response);
}
return await HandleMessage<T>(response);
}
ExceptionSource: mscorlib, ExceptionMesage: An error occurred while
sending the request, ExceptionTrace: at
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
atSystem.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) at d__4.MoveNext().
For most of the times, I could get response from API. Otherwise, occasionally I get the above stated error.
I see some answers (authentication problem, wrong request URL and some others), but I have made sure all those are properly configured at my end.
Hope I can get some help here. Here is the section where the error appears:
HttpResponseMessage response = await client.PostAsync(path, new StringContent(contents, Encoding.UTF8, "application/json")).ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
Task<string> resultdata = response.Content.ReadAsStringAsync();
if (resultdata != null)
{
var resultContent = resultdata.Result;
JsonSerializerSettings settings = new JsonSerializerSettings();
obj reference = JsonConvert.DeserializeObject<Class Name>(resultContent, settings);
}
}
I've been banging my head with this issue since last night. It only happens on the deployed binaries in Windows Server 2012 IIS with no clear error logs. But in Visual Studio, no problem at all.
try
{
using (var client = new HttpClient())
{
var requestUri = "http://[some-vcloud-ipaddress]/api/versions";
var response = await client.GetAsync(requestUri); // <-- This is line 94
if (response.IsSuccessStatusCode)
{
var xml = await response.Content.ReadAsStreamAsync();
var result = Serializer<SupportedVersions>.Deserialize(xml);
return result;
}
return null;
}
}
catch (Exception ex)
{
_logger.ErrorFormat("VcloudApiClient - GetSupportedVersions failed. Error message: {0}", ex.Message);
_logger.ErrorFormat("VcloudApiClient - GetSupportedVersions failed. Error stacktrace: {0}", ex.StackTrace);
throw;
}
Below is the error log.
VcloudApiClient - GetSupportedVersions failed. Error message: An error occurred while sending the request.
VcloudApiClient - GetSupportedVersions failed. Error stacktrace: at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at SomeProject.Tpl.VcloudDirector.VcloudApiClient.<GetSupportedVersions>d__1.MoveNext() in d:\Projects\SomeProject-01\src\Api\SomeProject.Tpl\VcloudDirector\VcloudApiClient.cs:line 94
Please note that there's no problem executing the URL on any other clients (browsers, Postman REST client, etc.).
I have an application which uses WebAPI for pulling out the LDAP data. It runs perfectly on my local machine, but since I publish the app refreshing the data doesn't work. I've done some research and it seems that the asynchronous task is having some sort of deadlock. Since I'm new to that whole threading/tasking stuff I need your advice how to setup and code everything correctly. If I make the exception handling more generic and instead of catching specific Exception-derived classes I end up with Task has been canceled (timeout?) error, currently it displays Response status code does not indicate success: 504 (Gateway Timeout).. I've tried defining HttpClient's timeout, configuring await on GetStringAsync, without any success.
Here's my code:
Models\Partials\Person.cs:
public async Task RefreshLDAP()
{
string URL = UserLib.LDAP_WS + login;
#region other method
//System.Net.WebClient client = new System.Net.WebClient();
//client.Headers[HttpRequestHeader.Accept] = "text/html, image/png, image/jpeg, image/gif, */*;q=0.1";
//client.Headers[HttpRequestHeader.UserAgent] = "Mozilla/5.0 (Windows; U; Windows NT 6.1; de; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12";
//string json_string = client.DownloadString(URL);
#endregion
using (HttpClient client = new HttpClient())
{
client.Timeout = TimeSpan.FromMinutes(30);
string json_string = "";
try
{
json_string =
await client.GetStringAsync(URL).ConfigureAwait(continueOnCapturedContext: false);
}
catch (TaskCanceledException ex)
{
// handle somehow
throw new Exception(string.Format("TaskCanceledException threw an error: {0}",ex.Message));
}
catch (HttpRequestException ex)
{
// handle somehow
throw new Exception(string.Format("HttpRequestException threw an error: {0}", ex.Message));
}
dynamic userInfo = JsonConvert.DeserializeObject<dynamic>(json_string);
first_name = userInfo.FirstName;
last_name = userInfo.LastName;
position = userInfo.Title;
email = userInfo.Mail;
}
}
Controlers\ProfileControler.cs:
public async Task<ActionResult> Refresh()
{
var currentLogin = UserLib.GetLogin();
var currentUser = (from user in ent.People where user.cecid == currentCecid select user).SingleOrDefault();
if (currentUser == null)
throw new Exception();
await currentUser.RefreshLDAP();
ent.SaveChanges();
return View("Manage");
}
Here's the stack trace:
System.Exception: HttpRequestException threw an error: Response status code does not indicate success: 504 (Gateway Timeout).
at MyApp1.Models.Person.<RefreshLDAP>d__9.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at MyApp1.Controllers.ClientsController.<Refresh>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Mvc.Async.TaskAsyncActionDescriptor.EndExecute(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass37.<BeginInvokeAsynchronousActionMethod>b__36(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<>c__DisplayClass48.<InvokeActionMethodFilterAsynchronouslyRecursive>b__41()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass33.<BeginInvokeActionMethodWithFilters>b__32(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass21.<>c__DisplayClass2b.<BeginInvokeAction>b__1c()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass21.<BeginInvokeAction>b__1e(IAsyncResult asyncResult)
I have tried everything and I can not figure out why this error happens.
Background:
I have an IPad application, written in MonoTouch and I have a thread that runs in the background, and every 15 seconds I sync data with the server. This works the first few iterations of the thread, but eventually I get the following stack trace.
An exception occured: System.Net.WebException: Error getting response stream (ReadDone4): ServerProtocolViolation ---> System.FormatException: Input string was not in the correct format
at System.UInt32.Parse (System.String s) [0x00010] in /Developer/MonoTouch/Source/mono/mcs/class/corlib/System/UInt32.cs:405
at System.Net.WebConnection.GetResponse (System.Byte[] buffer, Int32 max) [0x000ba] in /Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/WebConnection.cs:565
at System.Net.WebConnection.ReadDone (IAsyncResult result) [0x00095] in /Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/WebConnection.cs:446
--- End of inner exception stack trace ---
at System.Net.HttpWebRequest.EndGetResponse (IAsyncResult asyncResult) [0x0005e] in /Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/HttpWebRequest.cs:819
at System.Net.HttpWebRequest.GetResponse () [0x0000e] in /Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/HttpWebRequest.cs:827
at SyncService.REST.RestClient.Execute[IEnumerable`1] (SyncService.REST.RestRequest request) [0x00079] in /Users/Chris/Compass/SyncService/REST/RestClient.cs:42
I am talking to an IIS webserver with default configuration.
Here is the method I am calling:
public RestResponse<T> Execute<T>(RestRequest request){
var restResponse = new RestResponse<T>();
var serializer = new JavaScriptSerializer();
var urlPath = _baseUrl + "/" + request.Resource;
var httpRequest = (HttpWebRequest)HttpWebRequest.Create(new Uri(urlPath));
httpRequest.Headers = request.Headers;
Authenticator.Authenticate(httpRequest);
httpRequest.Method = request.Method.ToString();
if (request.Method == Method.POST)
SetPostData(httpRequest, request);
HttpWebResponse httpResponse = null;
try{
httpResponse = (HttpWebResponse) httpRequest.GetResponse();
var reader = new StreamReader(httpResponse.GetResponseStream());
var responseString = reader.ReadToEnd();
reader.Close();
restResponse.StatusCode = httpResponse.StatusCode;
restResponse.Headers = httpResponse.Headers;
restResponse.Data = serializer.Deserialize<T>(responseString);
restResponse.ResponseStatus = ResponseStatus.Completed;
}
catch(WebException e){
restResponse.ResponseStatus = ResponseStatus.Error;
restResponse.ErrorMessage = e.Message;
restResponse.ErrorException = e;
var webResponse = (HttpWebResponse) e.Response;
if (webResponse != null){
restResponse.StatusCode = webResponse.StatusCode;
restResponse.Headers = webResponse.Headers;
}
if (restResponse.StatusCode != HttpStatusCode.NotModified)
Console.WriteLine("An exception occured: " + e + "\r\n");
}catch (Exception ex) {
restResponse.ResponseStatus = ResponseStatus.Error;
restResponse.ErrorMessage = ex.Message;
restResponse.ErrorException = ex;
}
if (httpResponse != null)
httpResponse.Close();
return restResponse;
}
Please help. I don't know what to do. Google shows nothing.
I am able to make 22 successful requests before the error shows up.
EDIT
I have narrowed it down to being a server issue. This is asp.net MVC and the exception only happens when I send a 304 to the client. See Server Code:
private void ServeHttpStatusCode() {
Response.StatusCode = 304;
Response.Status = "304 Not Modified";
Response.StatusDescription = "The resource you are requesting has not been modified";
Response.ContentType = "application/json";
Response.Write("{\"Error\":\"The resource you are requesting has not been modified\"}");
Response.End();
Response.Close();
}
Is there a proxy between the client
and the server?
Does it always fail after 22 requests?
The exception indicates that some UInt32 can't be parsed.
Do you get exceptions on the server side?
In case anyone else is scouring the internet looking for answers on this issue, I had a very similar problem with some functional tests I was writing. They were uploading content to a webserver using http PUT and then using http GET straight after.
The GET failed reliably with the same error in the Uint32 parse. The windows build was fine. In desperation I used Thread.Sleep(20) to insert some delay between http requests, and this has cleared up the error. Not sure why, but it works now, which is good enough for my tests, if not for production stuff.