I'm making Xamarin.Forms app which should get JSON from api and then allow to display it. My code so far:
public async void jsonDownload()
{
connect();
await downloadData();
}
public void connect()
{
client = new HttpClient();
client.MaxResponseContentBufferSize = 256000;
}
public async Task<List<Jsonclass>> downloadData()
{
String url = "https://my-json-server.typicode.com/kgbzoma/TestJsonFile/all";
var uri = new Uri(string.Format(url, string.Empty));
try
{
var response = await client.GetAsync(uri).ConfigureAwait(false);
response.EnsureSuccessStatusCode(); //NEVER GET HERE
var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
List = JsonConvert.DeserializeObject<List<Jsonclass>>(content);
}catch (Exception ex)
{
Debug.WriteLine(#" Error {0}", ex.Message);
}
return List;
}
Problem is that code don't even go to response.EnsureSuccessStatusCode(); so my list of objects is empty. On UWP version it's working without any problems.
Here i'm gettin exception: System.Net.Http.HttpRequestException with message An error occurred while sending the request.
SecureChannelFailure (The authentication or decryption has failed.)
or
System.Net.WebException: Error: TrustFailure
or
Mono.Security.Protocol.Tls.TlsException: Invalid certificate received from server.
By default, Xamarin.Android uses the older Mono Managed HttpClient handler that does not support TLS 1.2.
Open your Xamarin.Android project settings, goto Build / Android Build / General and use the AndroidClientHandler.
This will add the following MSBuild properties directly to your .csproj
<AndroidHttpClientHandlerType>Xamarin.Android.Net.AndroidClientHandler</AndroidHttpClientHandlerType>
<AndroidTlsProvider>btls</AndroidTlsProvider>
Note: If doing this manually in the .csproj, you need to add them to the debug AND release PropertyGroup.
Or programmatically set the HttpClient to use it:
client = new HttpClient(new AndroidClientHandler());
Note: You should be looking at the InnerException for these types of errors
catch (Exception ex)
{
Console.WriteLine(#" Error {0}", ex.Message);
Console.WriteLine(#" Error {0}", ex.InnerException?.Message);
}
Related
I have a WebApi that is running on Azure and fully tested via Postman
This API takes 2 headers
Content-Type: application/json
AppToken: {{AppToken}}
I want to call this API from a console application and I thought it is a pretty straight forward process. Here is my Main program
static void Main(string[] args)
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("BASE_ADDRESS/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Add("AppToken", "MY_APP_TOKEN_VALUE");
// Call API to create the registration
CreateRegistration(client).Wait();
}
public static async Task CreateRegistration(HttpClient client)
{
using (client)
{
try
{
Registration reg1 = new Registration { email = "test#ssdafsds.com", clientId = 2342342, registrationId = 23423, ProgramId = 13 };
HttpResponseMessage responseMessage = await client.PostAsJsonAsync("api/auth/register", reg1);
responseMessage.EnsureSuccessStatusCode();
// Handle success
}
catch (Exception ex)
{
// Handle failure
Console.WriteLine(ex.StackTrace);
}
}
}
I am getting an internal server error as the "Reason Phrase" with status code 500. I am not sure why I am getting this error. I should be getting 201 Created like postman
Any idea how to solve this issue?
I made a mistake by passing a program id that I don't actually have in my database which failed the FK_Reference and caused this issue. Thank you all for your help.
I have a Xamarin.Forms App which should communicate with an embedded device via a RESTService.
So in my SharedProject I have a Service which wraps a httpclient.
HttpClient client = new HttpClient() { Timeout = new TimeSpan(0, 0, 31) };
public async Task<MetaData> RequesMetaData()
{
try
{
var response =await client.GetAsync("http://192.168.1.23:9090/api/meta/", HttpCompletionOption.ResponseContentRead);
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadAsStringAsync();
var meta = JsonConvert.DeserializeObject<MetaData>(result);
return meta;
}
catch(OperationCanceledException ocex)
{
ConnectionError?.Invoke(new Message { MessageInfo = ocex.Message, IsError = true });
return new MetaData();
}
catch(Exception ex)
{
ConnectionError?.Invoke(new Message { MessageInfo = ex.Message, IsError = true });
Debug.Print(ex.GetType().Name);
return new MetaData();
}
}
The call should return a Json, which works most times.
The problem is sometimes, the last byte, the curly bracket '}' of the Json is missing.
It is always the last '}', no matter how long the message sent by the server was.
This only occurs on Android. When I test the RESTservice from Firefox,
no such error occurs. Additionally I logged with Wireshark, which reports the full json was delivered over the wire.
Also I tried the same code in a WPF Desktop App, which works flawless. Only on Xamarin Android it is missing the last byte. In the Android Options,
I tried all options (Android,Managed,Default).
Instead of ReadAsStringAsync(), I also tried ReasAsStreamAsync(), but got the same results.
When changing to https, this issue persits but in another form. Instead of the missing last byte, on occassion the Content will just be an empty string "",
maybe because the message could not be decrypted.
For testing I use the x86 Emulator of VisualStudio(Android 9) , as well as a Nexus 5 (Android 6).
I think I found the issue.
The server of the embedded device I was talking to was using http/1.0 and didn't include content-length. Changing it to use http/1.1 and using content-lenght solved the issue for me.
I can only guess that Xamarin.Android HttpClient has problems with http/1.0.
When i call
public static async Task<User> GetUserAsync(string name)
{
try
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(Resource.RestBaseURI);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("APIKey", Resource.APIKey);
var responseMessage = await client.GetAsync($"api/Users/{name}");
if (!responseMessage.IsSuccessStatusCode)
throw new HttpResponseException(responseMessage.StatusCode);
var userDb = responseMessage.Content.ReadAsAsync<UserDb>().Result;
if (userDb == null)
throw new HttpResponseException(HttpStatusCode.NotFound);
var user = DbClientConverter.UserDbToUser(userDb);
user.RefuelEntityList = await RefuelEntityCommunicator.GetRefuelEntitiesAsync(user);
return user;
}
}
catch (HttpResponseException httpResponseException)
{
throw new HttpResponseException(httpResponseException.Response.StatusCode);
}
catch (HttpRequestException httpRequestException)
{
throw new HttpRequestException(httpRequestException.Message, httpRequestException);
}
catch (Exception exception)
{
throw new Exception(exception.Message, exception);
}
}
on Xamarin Android
the await client.GetAsync in line 12 causes a exception:
"The type initializer for 'System.Net.Http.FormattingUtilities' threw an exception"
the same code used in a WPF Application is no problem.
Any ideas how to fix this?
Solution 1: It seems that some dependencies are broken. Have you tried to reinstall NuGet package?
From the package manager, run Update-Package Microsoft.AspNet.WebApi -reinstall.
Solution 2: use NuGet to install the Web API 2.1 WebHost.
Solution 3: Install-Package Microsoft.AspNet.WebApi -Version 5.x.x
https://forums.xamarin.com/discussion/85204/problem-is-could-not-load-type-system-net-http-formattingutilities
Instead of
client.DefaultRequestHeaders.Add("APIKey", Resource.APIKey);
Use
client.DefaultRequestHeaders.TryAddWithoutValidation("APIKey", Resource.APIKey);
This is becuase "APIKey" here is a non-standard custom header
I guess it's a problem with ReadAsAsync extension method.
See here for a custom solution.
The view 'Search' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/Home/Search.aspx
~/Views/Home/Search.ascx
~/Views/Shared/Search.aspx
~/Views/Shared/Search.ascx
~/Views/Home/Search.cshtml
~/Views/Home/Search.vbhtml
~/Views/Shared/Search.cshtml
~/Views/Shared/Search.vbhtml
I am working on a basic web application that reads data from an api. When I run the solution and try to access the view referenced by this controller from the code below, I get this error. I have narrowed it down to being the GetAsync line of code. This works on windows however does not work on my Mac.
From what I can find, the cross platform .net framework Mono, used by visual studio on OSX, does not support GetAsync. What are my options if I want to develop/test this on my Mac but also deploy on a azure server?
public async Task<ActionResult> Search(string ticker)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(demoapiurl);
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
try
{
HttpResponseMessage res = await client.GetAsync(string.Format("{0}&symbol={1}&apikey={2}", apiurl, ticker, apikey));
if (res.IsSuccessStatusCode)
{
var accResponse = res.Content.ReadAsStringAsync().Result;
var quotes = GettingStarted.FromJson(accResponse);
GettingStarted allquotes = JsonConvert.DeserializeObject<GettingStarted>(accResponse);
return View(allquotes);
}
}
catch (Exception ex)
{
Console.WriteLine("Exception Message: " + ex.Message);
}
}
return View();
}
I started to learn Xamarin to develop application for iOS, Android and Windows Phone.
Seems a simple question but I don't know how to proceed with Xamarin.
I have the following lines of code:
public async Task<List<MyData>> GetItemsAsync()
{
HttpClient client = new HttpClient();
try {
string result = await client.GetStringAsync( "https://jsonplaceholder.typicode.com/posts/1" );
if(!string.IsNullOrWhiteSpace(result)) {
}
} catch( Exception ex ) {
return await Task.FromResult(new List<MyData>(0));
} finally {
client.Dispose(); //of course, I can use `using`
}
return await Task.FromResult(new List<MyData>(0));
}
When debug in Visual Studio Android Emulator(VisualStudio_android-23_x86_phone (Android 6.0 - API 23)), the line where starts with string result is stuck, nothing happens, no exception is thrown. I cannot use F10 in Visual Studio to inspect.
Also, I cannot use WebClient because System.Net doesn't include it.
Edit: If I remove await then I receive a general exception:
Where is my mistake ?
For those who meet the error:
Error: SecureChannelFailure (The authentication or decryption has failed.)
Please use specific handler for Android:
using (HttpClient myClient = new HttpClient(new AndroidClientHandler())) { }
or for iOS:
using(HttpClient myClient = new HttpClient(new CFNetworkHandler())) {}
References:
https://developer.xamarin.com/guides/cross-platform/macios/http-stack/
https://developer.xamarin.com/guides/android/application_fundamentals/http-stack/