App crashes on iOS with no internet connection - c#

I am using async method to retrieve JSON data , the data comes successfully but when I turn off the internet in my device, the App stops unfortunately. How can I handle this exception, or how can I handle internet Connectivity in Xamarin.Forms.
public partial class MainActivity : ContentPage
{
public ObservableCollection<Adverts> Zoos { get; set; }
public int Count = 0;
public short Counter = 0;
public int SlidePosition = 0;
string heightList;
int heightRowsList = 90;
private const string Url = "http://eamobiledirectory.com/cooperp/Mobile/Mobileapi.aspx?Action=Featured&Country=Uganda";
private const string BaseImageUrl = "http://eamobiledirectory.com/cooperp/Images/app_images/";
private HttpClient _client = new HttpClient();
public ObservableCollection<Adverts> adverts;
public MainActivity()
{
InitializeComponent();
TrendingShows();
if (CrossConnectivity.Current.IsConnected)
{
OnAppearing();
}
else
{
App.Current.MainPage.DisplayAlert("Alert ", "No internet Connection Please", "OK");
}
}
protected override async void OnAppearing()
{
var content = await _client.GetStringAsync(Url);
var adv = JsonConvert.DeserializeObject<List<Adverts>>(content);
adverts = new ObservableCollection<Adverts>(adv);
AdvertsCarousel.ItemsSource = adverts;
// attaching auto sliding on to carouselView
Device.StartTimer(TimeSpan.FromSeconds(18), () =>
{
SlidePosition++;
if (SlidePosition == adverts.Count)
SlidePosition = 0;
AdvertsCarousel.Position = SlidePosition;
return true;
});
}
i tried this but it seems not working , How can i handle this.

Either use a simple try/catch construction, this also helps for any other errors that might occur. Or look into the Connectivity Plugin. This has some methods, properties and events to determine what the state of your connection is and you can handle your content accordingly.
Edit
As a follow up to your edited question; you do not need to call OnAppearing yourself. Either abstract your code to some kind of method that refreshes the data if you need to, or find another method that is better suitable.
You should also move your check closer to the point where you are fetching your data. For instance, do it more like this:
protected override async void OnAppearing()
{
adverts = new List<Adverts>();
if (CrossConnectivity.Current.IsConnected)
{
var content = await _client.GetStringAsync(Url);
var adv = JsonConvert.DeserializeObject<List<Adverts>>(content);
adverts = new ObservableCollection<Adverts>(adv);
}
else
{
// TODO: Either show cached adverts here, or hide your carrousel or whatever you want to do when there is no connection
}
AdvertsCarousel.ItemsSource = adverts;
// attaching auto sliding on to carouselView
Device.StartTimer(TimeSpan.FromSeconds(18), () =>
{
SlidePosition++;
if (SlidePosition == adverts.Count)
SlidePosition = 0;
AdvertsCarousel.Position = SlidePosition;
return true;
});
}

Related

selenium C# wait for background requests(not initiated by c# code)

Im using selenium chrome driver combined with cefsharp, the page im working on sends some kind of ping request(fetch/xhr) everytime an element is clicked the problem is that those request aren't initiated by selenium chrome driver so there is no wayy for me to track them and wait for the finish. Is there any way for selenium or js to track those requests?
With Selenium 4 you actually can intercept requests
Call Enable to start requests tracking
Call WaitForRequestResponse to wait for the specific request
If you can same requests you can clean already catch requests with Clear
public class WebDriverNetworkController
{
private const string RequestWillBeSent = "requestWillBeSent";
private const string ResponseReceived = "responseReceived";
private readonly IDriverProvider _driverProvider;
private readonly ILogger _log;
private readonly ConcurrentDictionary<DevToolsSession, List<HttpRequestModel>> _sentRequests = new();
public WebDriverNetworkController(IDriverProvider driverProvider, ILogger log)
{
_driverProvider = driverProvider;
_log = log;
}
private void HandleDevToolsEvent(object sender, DevToolsEventReceivedEventArgs e)
{
var session = sender as DevToolsSession;
switch (e.EventName)
{
case RequestWillBeSent:
{
OnRequestWillBeSent(session, e.EventData);
break;
}
case ResponseReceived:
{
OnResponseReceived(session, e.EventData);
break;
}
}
}
public void Enable()
{
_log.Information("Enabling network tracing");
var session = GetDevToolsSession();
session.DevToolsEventReceived += HandleDevToolsEvent;
var enableTask = session.Domains.Network.EnableNetwork();
enableTask.Wait();
}
public void Disable()
{
_log.Information("Disabling network tracing");
var session = GetDevToolsSession();
session.DevToolsEventReceived -= HandleDevToolsEvent;
var disableTask = session.Domains.Network.DisableNetwork();
disableTask.Wait();
}
public void Clear()
{
_log.Information("Clearing captured network tracing requests");
var sentRequests = GetRequests();
sentRequests.Clear();
}
public HttpRequestModel[] GetAllRequests() => GetRequests().ToArray();
public HttpRequestModel WaitForRequestResponse(HttpMethod method, string uri)
{
_log.Debug($"Waiting for {method.Method} request to {uri}");
var session = GetDevToolsSession();
HttpRequestModel request = null;
var waiter = new ConditionWaiter
{
Message = $"{method.Method} request to {uri}"
};
waiter.Until(() =>
{
request = GetLastSentRequest(method, uri, session);
return request?.Response != null;
});
return request;
}
private HttpRequestModel GetLastSentRequest(HttpMethod method, string uri, DevToolsSession session) =>
GetRequests(session).LastOrDefault(request => request.Method == method && request.Uri.EndsWith(uri));
private DevToolsSession GetDevToolsSession()
{
var driver = _driverProvider.GetDriver();
if (driver is IDevTools devTools)
{
return devTools.GetDevToolsSession();
}
throw new WebDriverException($"Could not cast {driver.GetType().Name} to {nameof(IDevTools)}");
}
private List<HttpRequestModel> GetRequests(DevToolsSession session = null) =>
_sentRequests.GetOrAdd(session ?? GetDevToolsSession(), _ => new());
private void OnRequestWillBeSent(DevToolsSession session, JToken eventData)
{
var requestModel = new HttpRequestModel
{
Id = eventData.SelectToken("requestId", true)!.Value<string>(),
Method = new(eventData.SelectToken("request.method", true)!.Value<string>()!),
Uri = eventData.SelectToken("request.url", true)!.Value<string>(),
Body = eventData.SelectToken("request")!.Value<string>("postData")
};
var sentRequests = _sentRequests.GetOrAdd(session, _ => new());
sentRequests.Add(requestModel);
}
private void OnResponseReceived(DevToolsSession session, JToken eventData)
{
var requestId = eventData.SelectToken("requestId", true)!.Value<string>();
var responseModel = new HttpResponseModel
{
Uri = eventData.SelectToken("response.url", true)!.Value<string>(),
StatusCode = (HttpStatusCode)eventData.SelectToken("response.status", true)!.Value<long>()
};
var sentRequests = _sentRequests[session];
var request = sentRequests.Last(request => request.Id == requestId);
request.Response = responseModel;
}
}
The code above is not ready to be used right away but should give a general understanding of the approach.

Can I do any action just after return my response with an API GraphQL

I am trying to perform an action right after returning my response to a GraphQL API request.
Let me explain: I would like to develop a GraphQL server that receives a certain request from another server and sends a request to this other server just after answering the first request
In comparison, it looks like the OnActionExecuted function with ActionFilterAttribute but I can't implement it for GraphQl, maybe it works only for Rest APIs
I also found the function :
public async override Task AfterExecutionAsync(IExecutionContext context) from class GraphQL.Execution.DocumentExecutionListenerBase but I can't figure out how to implement it so that it triggers after returning my answer
this is the idea but of course it is not what i have tried haha
public async Task<sendLinkRequest> sendLinkStatusUpdate(newLinkStatusInput input)
{
return _sendLinkRequestService.sendLinkStatusUpdate(input);
//Doing this after my function return the result
var graphQLClient = new GraphQLHttpClient("https://exemple.com", new NewtonsoftJsonSerializer());
var sendLinkStatusUpdate = new GraphQLRequest
{
Query = "mutation{sendLinkStatusUpdate(input : {newLinkStatus: \"active\"}) {errors {scope message}}}",
Variables = new
{
newLinkStatus = "active"
}
};
var graphQLResponse = await graphQLClient.SendQueryAsync<sendLinkRequest>(sendLinkStatusUpdate);
}
Anyway, if someone has an idea or a lead I'm interested
Thanks for your comment ! I managed to do it like that :)
public sendLinkRequest sendLinkStatusUpdate(newLinkStatusInput input)
{
TrackingActionFilter ta = new TrackingActionFilter();
ta.ProcessCompleted += ta_nextAction; // register with an event
sendLinkRequest test = ta.StartProcess(input, _sendLinkRequestService);
return test;
}
public async static void ta_nextAction(object sender, EventArgs e)
{
var graphQLClient = new GraphQLHttpClient("https://talentusnewdemo.eu-west-1.beepleapp.eu/b/multi-tenant-api", new NewtonsoftJsonSerializer());
var sendLinkStatusUpdate = new GraphQLRequest
{
Query = "mutation{sendLinkStatusUpdate(input : {newLinkStatus: \"active\"}) {errors {scope message}}}",
Variables = new
{
newLinkStatus = "active"
}
};
var graphQLResponse = await graphQLClient.SendQueryAsync<sendLinkRequest>(sendLinkStatusUpdate);
Console.WriteLine("Process Completed!");
}
public class TrackingActionFilter
{
public event EventHandler ProcessCompleted;
public sendLinkRequest StartProcess(newLinkStatusInput input, IsendLinkRequestService _sendLinkRequestService)
{
Console.WriteLine("Process Started!");
OnProcessCompleted(EventArgs.Empty); //No event data
return _sendLinkRequestService.sendLinkStatusUpdate(input);
}
protected virtual void OnProcessCompleted(EventArgs e)
{
ProcessCompleted?.Invoke(this, e);
}
}

I can not handle these classes c# uwp

until now I only have small applications, but now I can not handle these classes c# uwp
I want to break the code into several classes, each class will deal with a few parameters. classes will send parameter values to the main page. but when I try to display those parameters, they are always zero, even though the text file appears modified.
i have main page
namespace airflow
{
public sealed partial class MainPage : Page
{
}
public MainPage()
{
}
private async void main_page_Loaded(object sender, RoutedEventArgs e)
{
param_perimetrala read = new param_perimetrala();
ora_start_perimetrala = read.start_perimetrala;
var mesaj = new MessageDialog(ora_start_perimetrala.ToString());
var res = await mesaj.ShowAsync();
}
}
and a class
namespace airflow
{
public class param_perimetrala
{
public static int ora_start_perimetrala;
public int minut_start_perimetrala;
public int ora_stop_perimetrala;
public int minut_stop_perimetrala;
public int ore_ciclu_perimetrala;
public int minut_ciclu_perimetrala;
public int contor_ore_perimetrala = 0;
public int contor_minute_perimetrala = 0;
public int contor_sec_perimetrala = 0;
public async void readfile_perimetrala()
{
StorageFolder folder = ApplicationData.Current.LocalFolder;
StorageFile perimetrala_file = await folder.CreateFileAsync("parametrii_perimetrala.txt", CreationCollisionOption.OpenIfExists);
var readFile_perimetrala = await FileIO.ReadLinesAsync(perimetrala_file);
int count = 0;
foreach (var line in readFile_perimetrala)
{
string[] split_perimetrala = line.Split(new string[] { "=" }, StringSplitOptions.RemoveEmptyEntries);
var temp = split_perimetrala[1];
if (count == 0)
{
ora_start_perimetrala = Int32.Parse(temp);
}
if (count == 1)
{
minut_start_perimetrala = Int32.Parse(temp);
}
if (count == 2)
{
ora_stop_perimetrala = Int32.Parse(temp);
}
count = count + 1;
}
}
public int start_perimetrala
{
get { return ora_start_perimetrala; }
set { ora_start_perimetrala = value; }
}
}
}
how to send ora_start_perimetrala value in mainpage?
enter image description here
In your main_page_Loaded event handler method you are calling read_file_perimetrala but read_file_perimetrala is async void. This means as soon as you get to an await statement, and the await is actually awaitable (not returned immediately) then the method will put the rest of the work aside until the awaited portion is complete. Then it picks back up and runs the rest. During that time of placing it aside the calling thread then continues to run wherever it's needed.
You need to make this a Task and await the call to is also so that you can insure the parameters are filled before continuing work.
Change your readFile_perimetrala to be like so:
public async Task readfile_perimetralaAsync()
Change the entire main_page_Loaded event handler to read like so...
private async void main_page_Loaded(object sender)
{
param_perimetrala read = new param_perimetrala();
await read.readfile_perimetralaAsync();
var mesaj = new MessageDialog(read.start_perimetrala.ToString());
var res = await mesaj.ShowAsync();
}
In your code you're assigning the value to a method but I can tell that you want the int value.
Just some light weight examples to help get started understanding Task and async await. Don't use this as a resource but just enough to get you curious to dig deeper because it's a simple but rather deep subject.
public class TaskExamples
{
public async void DoAsyncVoid()
{
await Task.Delay(200);
}
public async Task DoAsyncTask()
{
await Task.Delay(200);
}
public async Task<int> DoReturnValueTask()
{
await Task.Delay(200);
return 50;
}
public async void CallingTasks()
{
DoAsyncVoid(); //This can't use await because it is 'void' so the next line is ran as soon as this command reaches the first 'true awaitable' await.
await DoAsyncTask(); //This runs before DoAsyncVoid is complete.
var value = await DoReturnValueTask(); //This waits until 'DoAsyncTask' is complete because it is a Task and awaited.
await new MessageDialog(value.ToString()).ShowAsync(); //This waits until 'DoReturnValueTask' is complete and value will be 50 in this case.
//All code here waits until the Dialog is closed because it is also awaited.
}
}

DotVVM - GridViewDataSet not loading any data

I am stuck on problem where my facade method is never called so my returned items are always zero. I dont exactly know why this happens since it should at least load items on initial page load. Also I got almost identical ViewModel where it works fine.
Here is my viewmodel where I want to load FavouriteCommodities into GridViewDataSet
//initialized via constructor
private readonly FavouriteCommodityFacade _favouriteCommodityFacade;
public GridViewDataSet<FavouriteCommodityDTO> GridViewDataSetItems { get; set; }
public int PageSize { get; set; } = 10;
private ISortingOptions DefaultSortOptions => new SortingOptions();
public override Task Init()
{
GridViewDataSetItems = new GridViewDataSet<FavouriteCommodityDTO>()
{
PagingOptions = { PageSize = PageSize },
SortingOptions = DefaultSortOptions
};
return base.Init();
}
public override Task PreRender()
{
if (!Context.IsPostBack || GridViewDataSetItems.IsRefreshRequired)
{
LoadData();
}
return base.PreRender();
}
public void LoadData()
{
FavouriteCommodityGroups = _userAccountFavouriteProductsFacade.GetAllFavouriteProductsToUser();
//this never fires my facade method below
GridViewDataSetItems.OnLoadingData = option => _favouriteCommodityFacade.GetAssignedFavouriteProductsToGroup(option);
}
Here is my method in my facade which is never fired.
public GridViewDataSetLoadedData<FavouriteCommodityDTO>
GetAssignedFavouriteProductsToGroup (IGridViewDataSetLoadOptions gridViewDataSetLoadOption)
{
using (unitOfWorkProvider.Create())
{
var query = _favouriteCommodityByChosenGroupQuery();
FavouriteProductByGroupFilter.FavouriteGroupId = 16;
query.Filter = FavouriteProductByGroupFilter;
var x = GetGridViewDataSetLoadedData(gridViewDataSetLoadOption, query);
return x.Result;
}
}
I am also wondering if there is possibility to load those items on user click event. When I looked into namespace DotVVM.Framework.Controls I didnt find anything useful for that.
So I figure out after a while that Repeater component not triggering method. I had to use only GridView component in view.

Proper way to rise an event from one class and handle it in other class

I am building api for one application. what i want is when I get a new order, i have to insert it in DB and I want to rise an event (without blocking my api call may be async). so that latter in other class i can handle that event and do the other work like send the new order notification to account and send order update to user using pubnub.
public class OrderService : IOrderService
{
public delegate void OrderEventHandler(Order order,bool isNewOrder);
public static event OrderEventHandler OrderEvents = delegate { };
public OrderService()
{
OrderEventListener listener = new OrderEventListener();
OrderEvents += new OrderEventHandler(listener.HandleOrderEvents);
}
#region Methods
public void Test()
{
INPRODataFacade facade = new NPRODataFacade();
var unitOfWork = facade.GetUnitOfWork();
var order = unitOfWork.OrderRepository.Find(o => o.OrderID == 1).FirstOrDefault();
unitOfWork.Commit();
facade.ReturnUnitOfWork();
RiseEvent(order,true);
}
private async System.Threading.Tasks.Task RiseEvent(Order order,bool isNewOrder)
{
if (order == null)
{
return;
}
OrderEvents(order,isNewOrder);
}
}
public class OrderEventListener
{
PubNub.PubNub pubNub = null;
const string ChanelPrifix = "fasttract";
public OrderEventListener()
{
pubNub = new PubNub.PubNub(ConfigurationSettings.PubNub_SubscribeKey, ConfigurationSettings.PubNub_PublishKey, ConfigurationSettings.PubNub_SecretKey, ConfigurationSettings.PubNub_SSlOn);
}
public void HandleOrderEvents(Order order, bool isNewOrder)
{
string chanelName = isNewOrder ? string.Format("{0}_{1}", ChanelPrifix, order.AccountID)
: string.Format("{0}_{1}_{2}", ChanelPrifix, order.AccountID, order.OrderID);
var channel = pubNub.Channel(chanelName);
channel.Publish(new PubNubMessageModel { Message = GetMessage( order, isNewOrder) });
}
public string GetMessage(Order order,bool isNewOrder)
{
string message = string.Empty;
if(isNewOrder)
{
message = "You have recieved a new order #" + order.OrderID;
return message;
}
message = order.Status.ToString();
return message;
}
}
Here have noticed that it is blocking my api call. means I am not getting api response back until event handler finished its execution. is this the right way to handle events ? I think there should be a way that i just add events while getting new order and then in listener i process that events anytime without blocking api call.

Categories

Resources