Connection Failure while calling a REST API in Xamarin PCL - c#

While calling a REST API from PCL, The application gets crashed.
ERRORS
1. Error: ConnectFailure (Connection refused).
2. Skipped 1367 frames! The application may be doing too much work on its main thread.
Here is my code.
using (client = new HttpClient())
{
try
{
var response = await client.GetAsync("http://<my server ip>/Service//DataService.svc/?getVehicleInfo?vehicleId="+ id);
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
JSONModel jsonVehicle = JsonConvert.DeserializeObject<JSONModel>(content);
vehicle = JsonConvert.DeserializeObject<VehicleModel>(jsonVehicle.Result);
}
}
catch (Exception ex)
{
Debug.WriteLine(#"ERROR {0}", ex.Message);
}
return vehicle;
}
I am getting this error at GetAsync().
Internet service is enabled in AndroidManifest.xml.
It has been an obstacle in proceeding further. Need help to resolve it.

Take a look at the double slash here: Service//DataService.svc . It may be the problem. Replace with /

Try updating Xamarin, I had a very similar problem with the 6th version of xamarin but with the 7th the problem disappears

Related

C# / UWP / MVVM - How to handle HttpClient exceptions when the server is unrechable

I am currently working on an UWP app, that will run on a Raspberry PI. Most of my application can be used without an internet connection, but parts of it rely on fetching data from a server ran locally.
My issue is that whenever the server is offline, I can not handle the exceptions raised by the HttpClient.
To avoid using async tasks in the constructor of the ViewModel, I've moved it to the OnLoaded method of the View.
These are the methods that I use:
HomeAssistantView
private async void OnLoaded(object sender, RoutedEventArgs e)
{
await ViewModel.LoadEntities();
}
HomeAssistantViewModel
public async Task LoadEntities()
{
var entityList = await _homeAssistantService.LoadEntities();
Switches = new ObservableCollection<HomeAssistantSwitchEntity>(entityList.OfType<HomeAssistantSwitchEntity>());
Entities = new ObservableCollection<HomeAssistantEntity>(entityList.Where(entity =>!(entity is HomeAssistantSwitchEntity)));
}
HomeAssistantService
public async Task<List<HomeAssistantEntity>> LoadEntities()
{
_client.BaseAddress = new Uri(_homeAssistantURL);
_client.DefaultRequestHeaders.Add("Authorization", $"Bearer {_homeAssistantToken}");
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
try
{
HttpResponseMessage response = await _client.GetAsync("api/states");
if (response.IsSuccessStatusCode)
{
return DeserializeConfigFile(await response.Content.ReadAsStringAsync());
}
}
catch (HttpRequestException e)
{
Debug.WriteLine(e.Message);
}
return new List<HomeAssistantEntity>();
}
Even though I've added a try block, the application raises a System.Exception, with the message "The server name or address could not be resolved". After disabling the generic Exception type in the settings, Visual Studio told me it was a type of HttpRequestException with the message An error occurred while sending the request.
In a different part of my application, where I use a weather API, I got away with using the NetworkInformation.GetInternetConnectionProfile() to check whether there is an internet connection available prior to sending a request, but it's not a viable option here. Also, I've thought of sending a ping to the server prior to trying to fetch the data, but as far as I'm concerned, pinging is not available on the Windows 10 IoT Core.
I understood, that, you don't want the exception to be thrown, is this correct?
If yes just replace
catch (HttpRequestException e)
{
Debug.WriteLine(e.Message);
}
with
catch (Exception e)
{
Debug.WriteLine(e.Message);
}
this will catch all occuring exceptions

Xamarin forms operating camera gives empty exception

I'm working on a mobile Android app using Xamarin Forms and Visual Studio.
I'm using the CrossMedia Plugin to be able to take or select photo's in my mobile app. At first I had problems with the initialize and that issue appeared to be caused by the wrong Android SDK I was targeting. After I updated the SDK and updated all the packages I was able to get the 'select a photo' option working, but using the camera still doesn't work, and I can't figure out what is causing this.
I've got the following method;
private async void TakeAPhoto(object sender, EventArgs e)
{
try
{
await CrossMedia.Current.Initialize();
}
catch (Exception exception)
{
await DisplayAlert("ERROR", "Error initializing camera!", "Ok");
}
var cameraStatus = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Camera);
var storageStatus = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Storage);
if (cameraStatus != PermissionStatus.Granted || storageStatus != PermissionStatus.Granted)
{
var results = await CrossPermissions.Current.RequestPermissionsAsync(new[] { Permission.Camera, Permission.Storage });
cameraStatus = results[Permission.Camera];
storageStatus = results[Permission.Storage];
}
if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
{
await DisplayAlert("No camera", "No camera available", "Ok");
return;
}
if (cameraStatus == PermissionStatus.Granted && storageStatus == PermissionStatus.Granted)
{
MediaFile file;
try
{
//Exception occurs in this code.
file = await CrossMedia.Current.TakePhotoAsync(new StoreCameraMediaOptions
{
//Specify Store to Album OR Directory, not both
Directory = "App_Images",
Name = "Test.jpg"
});
}
catch (Exception exception)
{
//I've got a break point here which is being hit, but the exception is (null)
throw;
}
if (file == null)
return;
//TODO: Store image to azure.
}
else
{
await DisplayAlert("Permissions Denied", "Unable to take photos.", "OK");
//On iOS you may want to send your user to the settings screen.
//CrossPermissions.Current.OpenAppSettings();
}
}
However, when I'm running the code I'm getting an empty exception, it just says '(null)';
The debug window of Visual Studio gives me a lot of information, but the only real exception I see here is an 'InvocationException';
InspectorDebugSession(0): HandleTargetEvent: TargetHitBreakpoint
InspectorDebugSession(0): StateChange: EntryPointBreakpointRegistered -> EntryPointBreakpointHit
InspectorDebugSession(0): AgentBridge.InjectAssembly: /mnt/shell/emulated/0/Android/data/MyFirstAppPackage.MyFirstAppPackage/files/.__override__/inspector-temp/Xamarin.Interactive.dll
InspectorDebugSession(0): AgentBridge.InjectAssembly: Mono.Debugger.Soft.InvocationException: Exception of type 'Mono.Debugger.Soft.InvocationException' was thrown.
at Mono.Debugger.Soft.InvocationsAPI.EndInvokeMethodInternalWithResultImpl(IAsyncResult asyncResult)
at Xamarin.Interactive.IdeSupport.AgentBridge.InjectAssembly(String agentAssemblyPath) in C:\d\lanes\4699\fec6f88f\source\xamarinvs\External\inspector-ide-integration\Xamarin.Interactive.IdeSupport\AgentBridge.cs:line 55
at Xamarin.Interactive.IdeSupport.InspectorDebuggerSession.<HandleTargetEvent>b__26_0(Object <p0>) in C:\d\lanes\4699\fec6f88f\source\xamarinvs\External\inspector-ide-integration\Xamarin.Interactive.IdeSupport\InspectorDebuggerSession.cs:line 242
InspectorDebugSession(0): StateChange: EntryPointBreakpointHit -> Error
InspectorDebugSession(0): Disposed
I've been busy for quite some time to try and figure this out, but I'm completely stuck on this at the moment. I've also tried remote debugging by attaching a Samsung Galaxy S4 Mini to my computer, but it gives me the same error. What am I doing wrong here?
I got this issue resolved by simply selecting the proper Android version to compile on. The plugin documentation says the compile version of android needs to be set to Android 6.0, I had it set to 7.0 because I thought this was possible. But it's not.
Also the target android version was set to a higher version. Setting these both to Android 6.0 fixed the issue.
For more information see the documentation here.

TLSharp Data center (dc) Exception

I am using TLSharp library for implementing a custom Telegram client. when I run the code below:
public async Task<string> SendCodeRequest(string phoneNumber)
{
var completed = false;
TL.AuthSendCodeRequest request = null;
while (!completed)
{
request = new TL.AuthSendCodeRequest(phoneNumber, 5, _apiId, _apiHash, "en");
await _sender.Send(request);
await _sender.Receive(request);
completed = true;
}
// TODO handle other types (such as SMS)
if (request.Result is TL.AuthSentCodeType)
{
var result = (TL.AuthSentCodeType)request.Result;
return result.PhoneCodeHash;
}
else
{
var result = (TL.AuthSentAppCodeType)request.Result;
return result.PhoneCodeHash;
}
}
I gives me the following exception :
Your phone number registered to {dcIdx} dc. Please update settings.
See https://github.com/sochix/TLSharp#i-get-an-error-migrate_x for
details.
The mentioned github page says that TLSharp Handles these exceptions by itself. So I guess something is wrong with the library core because the code should resolve data center IPs by itself not generating an exception.
Any help would be appreciated.
TlSharp Currently doesn't handle this exception you have to catch the exception and get the data center number then Try to reconnect to the Data Center using the ReconnectToDc() Function.
In the MtProtoSender.cs file you can find the following line of code that generates the exception:
throw new InvalidOperationException($"Your phone number registered to {dcIdx} dc. Please update settings. See https://github.com/sochix/TLSharp#i-get-an-error-migrate_x for details.");
Replace it with the following code so that the Exception that is generated has the required Data Center number for connecting to it.
InvalidOperationException exception = new InvalidOperationException($"Your phone number registered to {dcIdx} dc. Please update settings. See https://github.com/sochix/TLSharp#i-get-an-error-migrate_x for details.");
exception.Data.Add("dcId", dcIdx);
throw exception;
Change your code like this:
while (!completed)
{
request = new TL.AuthSendCodeRequest(phoneNumber, 5, _apiId, _apiHash, "en");
try
{
await _sender.Send(request);
await _sender.Receive(request);
completed = true;
}
catch (InvalidOperationException ex)
{
if (ex.Message.StartsWith("Your phone number registered to") && ex.Data["dcId"] != null)
{
await ReconnectToDc((int)ex.Data["dcId"]);
}
else
{
throw;
}
}
}
In the Code above the Data Center number that was attached to the Exception is used for reconnecting to the Data center.
Probably your phone number is not in the format accepted by Telegram.
Phone number must start with plus sign, use country code and phone number without gap, for example: +989333333333

Checking HTTP Status of Many Pages on IIS Express: Crashes IIS Express

I am writing a simple C# console application, whose main job is, when given a set of URLs, to ping those URLs and report whether or not an HTTP 200 OK result was returned. The real life data set is in the area of 20,000 URLs to test (to verify that an en-masse edit did not ruin any of the pages).
Currently, the code that checks the response looks like this:
public UrlTestResult TestUrl(string url)
{
if (string.IsNullOrWhiteSpace(url))
{
throw new ArgumentNullException("url");
}
using (var client = new HttpClient())
{
try
{
Task<HttpResponseMessage> message = client.GetAsync(url);
if (message == null || message.Result == null)
{
return new FailedUrlTestResult(url, "No response was returned.");
}
if (message.Result.StatusCode == HttpStatusCode.OK)
{
return new SuccessfulUrlTestResult(url);
}
return new FailedUrlTestResult(url, "{0}: {1}".Format((int)message.Result.StatusCode, message.Result.ReasonPhrase));
}
catch (Exception ex)
{
return new FailedUrlTestResult(url, "An exception occurred: " + ex);
}
}
}
This code does work for smaller sets of data. Even if I iterate over the collection of URLs using Parallel.ForEach instead of a normal foreach, it behaves fine. After running for a few minutes or so, however, when parsing the 20,000 dataset, IIS Express (hosting localhost) will crash.
I'm guessing that my options are:
Run out of IIS and see if that works
Throttle the number of requests to give IIS Express a chance to breathe (trick here is how much to throttle)
Test the URLs in smaller chunks (similar to the second option)
What I am wondering is:
Is there a "cheaper" way to ping a URL and get its HTTP response back than HttpClient?
Are there any configuration options for IIS or IIS Express that I should be taking into consideration?
EDIT: I'm finding that IIS Express seems to simply be running out of memory. Pictured is the instance where the crash occurs:
Which means that IIS Express is holding on to memory that it obviously doesn't need to be (because once the request is over, I don't care about it anymore). Don't know if this'll help solve my problem any, though.
I simply changed to running localhost out of IIS instead of IIS Express. The memory usage was about the same, but it never crashed at any point for the ten minutes that the application was running. I also took Gabi's comment/suggestion and made HttpClient only be instantiated one time instead of once per test. The final code looks like this:
public sealed class UrlTester : IUrlTester
{
private readonly HttpClient httpClient = new HttpClient();
public UrlTestResult TestUrl(string url)
{
if (string.IsNullOrWhiteSpace(url))
{
throw new ArgumentNullException("url");
}
try
{
Task<HttpResponseMessage> message = httpClient.GetAsync(url);
if (message == null || message.Result == null)
{
return new FailedUrlTestResult(url, "No response was returned.");
}
if (message.Result.StatusCode == HttpStatusCode.OK)
{
return new SuccessfulUrlTestResult(url);
}
return new FailedUrlTestResult(url, "{0}: {1}".FormatCurrentCulture((int)message.Result.StatusCode, message.Result.ReasonPhrase));
}
catch (Exception ex)
{
return new FailedUrlTestResult(url, "An exception occurred: " + ex);
}
}
public void Dispose()
{
if (httpClient != null)
{
httpClient.Dispose();
}
}
}
And the caller to this class utilizes C#'s using statement to ensure that the HttpClient instance is properly disposed of.

The connection was closed unexpectedly C# after a long running time

Hi I was making a crawler for a site. After about 3 hours of crawling, my app stopped on a WebException. below are my code in c#. client is predefined WebClient object that will be disposed every time gameDoc has already been processed. gameDoc is a HtmlDocument object (from HtmlAgilityPack)
while (retrygamedoc)
{
try
{
gameDoc.LoadHtml(client.DownloadString(url)); // this line caused the exception
retrygamedoc = false;
}
catch
{
client.Dispose();
client = new WebClient();
retrygamedoc = true;
Thread.Sleep(500);
}
}
I tried to use code below (to keep the webclient fresh) from this answer
while (retrygamedoc)
{
try
{
using (WebClient client2 = new WebClient())
{
gameDoc.LoadHtml(client2.DownloadString(url)); // this line cause the exception
retrygamedoc = false;
}
}
catch
{
retrygamedoc = true;
Thread.Sleep(500);
}
}
but the result is still the same. Then I use StreamReader and the result stays the same! below are my code using StreamReader.
while (retrygamedoc)
{
try
{
// using native to check the result
HttpWebRequest webreq = (HttpWebRequest)WebRequest.Create(url);
string responsestring = string.Empty;
HttpWebResponse response = (HttpWebResponse)webreq.GetResponse(); // this cause the exception
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
responsestring = reader.ReadToEnd();
}
gameDoc.LoadHtml(client.DownloadString(url));
retrygamedoc = false;
}
catch
{
retrygamedoc = true;
Thread.Sleep(500);
}
}
What should I do and check? I am so confused because I got am able to crawl on some pages, on the same site, then in about 1000 reasults, it cause the exception. the message from exception is only The request was aborted: The connection was closed unexpectedly. and the status is ConnectionClosed
PS. the app is a desktop form app.
update :
Now I am skipping the values and turned them to null so that the crawling can goes on. But if the data is really needed, I still have to update the crawling result manually, which is tiring because the result contains thousands of record. Please help me.
example :
it was like you have downloaded like about 1300 data from the website, then the application stopped saying The request was aborted: The connection was closed unexpectedly. while all your internet connection still on and on a good speed.
ConnectionClosed may indicate (and probably does) that the server you're downloading from is closing the connection. Perhaps it is noticing a large amount of requests from your client and is denying you additional service.
Since you can't control server-side shenanigans, I'd recommend you have some sort of logic to retry the download a bit later.
Got this error because it was returned as 404 from the server.

Categories