My application is an "Offline System"
We can download appointments in that application and can use those application in offline mode, and that data can be upload when we have internet available.
But my Issue is: On client system our application crash with or without internet and i do not understand the reason. Below is the image or error message. That message is from Login screen when user try to login in offline mode
Any Suggestions please.
Thanks in advance.
This indicates some kind of network connectivity issue. The best way to find out why, is to check the inner exception as mentioned in your stacktrace:
See inner exception, if present, for more details
Assuing you have this kind of code:
var httpClient = new HttpClient();
var message = httpClient.GetAsync(url).Result;
Re-write doing something like this:
try {
var httpClient = new HttpClient();
var message = httpClient.GetAsync(url).Result;
} catch (Exception ex) {
ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
}
Since it is expected to have these exceptions while offline, when you get it, you should wait and retry later on.
Alternatively, you can use the network availability change to spin up your upload function
NetworkChange.NetworkAvailabilityChanged
+= new NetworkAvailabilityChangedEventHandler(NetworkChange_NetworkAvailabilityChanged);
Related
I am developing an application which is to run as a WinForms thick-client, accessing both an API to be running in the cloud (Azure), and a local SQL Server DB for data.
To allow users to log in, the login screen is triggered as a Modal prompt when the application starts up with the following code in the HomeScreen form which is the 'main' page of the application:
using (Form loginScreen = new LoginForm())
{
loginScreen.ShowDialog(this);
}
Once the login screen has been passed, the user can see the home screen, if they cancel it, the application closes. Once they get to the home screen, another API call is run to retrieve data about the user from the API for display on the home screen.
All API calls execute the same code, which is below (this is very early code for a 'working prototype' and I am aware there are probably issues with it that require a refactor, at this point I'm really only interested in understanding what is causing my call to PostAsJsonAsync to fail:
public async Task<ApiResponse> sendApiRequest(RequestDetail reqDet)
{
//create a variable to track if the action was done or we need to retry after a timeout and login
bool actionDone = false;
//instantiate a variable for the ApiResponse so it can be used later outside of the scope of the actionDone loop
ApiResponse res = null;
while (actionDone == false)
{
//populate the main SessionKey of the packet from the GlobalData var (for initial dev, to be refactored out)
reqDet.SessionKey = GlobalData.SessionKey;
//populate the SessionKey in the array underneath the main object (for future use)
reqDet.strParameters["SessionKey"] = GlobalData.SessionKey;
//instantiate a new ApiRequest object to hold the main request body
ApiRequest req = new ApiRequest("ClientRequest", reqDet);
//Create HttpClient class for communication with the server
HttpClient client = new HttpClient();
//Set URL and Headers (URL will be in a config file in future
client.BaseAddress = new Uri("https://removed.the.url.for.se/api/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
//actually call the service, wait for the response, and read it out into the response object
HttpResponseMessage response = await client.PostAsJsonAsync((string)req.requestBody.ApiLocation, req);
res = await response.Content.ReadAsAsync<ApiResponse>();
//check if the response was successful or we need to show an error
if (res.responseType == "Success")
{
//set action done to TRUE so we exit the loop
actionDone = true;
}
else
{
//Use the MessageService to dispaly the error
Error err = res.responseError;
MessagesService ms = new MessagesService();
await ms.displayErrorPrompt(err);
//trigger a login screen and restart the service call if the user's session has expired
if (err.ErrorText.Equals("Session has expired, please log in again"))
{
using (Form login = new LoginForm())
{
login.ShowDialog();
} // Dispose form
}
else
{
// set ActionDone to True if it's not a login error so we don't endlessly call the service
actionDone = true;
}
}
}
//return the final result
return res;
}
When running the entire stack locally, this all works perfectly, I can login and traverse the rest of my application as normal. When running the client locally in VS and the API in Azure, the first call to the Login API succeeds (I can call it multiple times e.g. with a wrong password and it behaves as normal), however the second call to get the user's data to paint on the home screen fails.If I put a breakpoint on the PostAsJsonAsync line, I can see that the line executes once and continues as normal, but immediately after stepping over the line the second time for the user details call, the entire application exits without executing the subsequent code.
What is strange about this is that it exits with a 0x0 return code, does not throw an exception, or in any way behave abnormally other than shutting down after just that line.
I have tried manually calling the APIs on the Azure service in Postman and they all return exactly the same (correct) results I get when running it locally, so I know it is not the deployment to the App Service that is the issue.
Things I have tried to fix it after Googling, reading other SE posts and looking at comments on this question
I have tried enabling first-chance exceptions in Visual Studio for all CLR exceptions. Nothing is caught or thrown that I can see.
Here is a screenshot of my settings in case I've done something wrong
I have tried wrapping just that line in a try-catch block that catches all exceptions. It still immediately stops executing after the PostAsJsonAsync and never reaches the Catch block
Adding the following code to my Program.cs file to catch unhandled exceptions (is never run when I put a breakpoint on it and nothing is written to the console that I can see):
static void Main()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new HomeScreen());
}
static void MyHandler(object sender, UnhandledExceptionEventArgs args)
{
Exception e = (Exception)args.ExceptionObject;
Console.WriteLine("MyHandler caught : " + e.Message);
}
Setting a DumpFolder that is writable by all users, and a DumpType of 2 in a key named after my executable at Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\ - I've tried both keys named MyApplication and MyApplication.exe and neither results in a file being produced when the app crashes.
The Windows Event Viewer after the 'crash' (nothing from my application)
Reviewing the request/response in Fiddler - the first 'login' request and response is shown correctly, but the second is not shown at all, so it looks like it's crashing before even sending the request
I'd be extremely grateful for any suggestions you can provide, even if it is only a workaround or 'patch' to resolve the issue. It's extremely strange to me both that it exits the program with no exception and without running the subsequent code, that it only does this when the API piece is running in Azure, not when running locally, and finally that it's only when it gets to the subsequent request after the login.
Update
I have tried commenting out the line that runs the RefreshScreen() function to call the web service again and the application still exits in the same way after the login, but just without hitting my breakpoint a second time. However again only when the application is running against the Azure API and not locally. If I break at the last line of the HomeScreen constructor and keep stepping, it goes back to my Main() method and ends the application. Is there something I'm doing wrong here?
I think the PostAsJsonAsync may have been a red herring so have taken it out of the title.
public HomeScreen()
{
InitializeComponent();
if(GlobalData.SessionKey == null)
{
using (Form loginScreen = new LoginForm())
{
loginScreen.ShowDialog(this);
}
// Dispose form
}
refreshScreen();
}
public async Task refreshScreen()
{
ApiService srv = new ApiService();
ApiResponse res = await srv.sendApiRequest(new Sessions_GetUserDetailsRequest());
if (res.responseType == "Success")
{
foreach (dynamic usrItem in JsonConvert.DeserializeObject(res.responseContent))
{
lblUserName.Text = usrItem.UserGivenName + " " + usrItem.UserSurname;
lblSiteName.Text = usrItem.TenantName;
}
}
}
So after doing some research to answer the helpful comments on this question, I stumbled across the answer.
I have an event in the application that is designed to close the entire application if the user exits the login page without logging in, since otherwise it would return to the 'home screen' form in an invalid state. It contained the following code, designed to close the application if the user didn't have a token (i.e. had cancelled the page):
Because my login process is asynchronous (code above) when I was stepping through the process in VS, I was getting to the "PostAsJsonAsync" step, and it was closing the application without showing me it was running the 'on close' event. However, unknown to me when testing locally, the code had a race condition where it would jump ahead to the 'close form' bit while still awaiting the web service call, and therefore execute the following code:
private void DoOnFormClosing(object sender, FormClosingEventArgs e)
{
if(GlobalData.SessionKey == null || GlobalData.SessionExpiry <= DateTime.Now)
{
Application.Exit();
}
}
The solution was to remove this event as part of the login process, after the login had been validated, meaning this code would never be called if the user had successfully logged in.
I have gRPC service define like below
service ConsumerService
{
stream Message Consume(SubscriptionRequest);
}
Client looks like this:
var consumer = new ConsumerService.ConsumerServiceClient(<channel>);
AsyncServerStreamingCall<Message> proxy = consumer.ConsumeAsync(subRequest));
while (!gracefulShutdown)
await proxy.ResponseStream.MoveNext(cts.Token);
// todo: tell the server that client is not going to read responses anymore..
await proxy.ResponseStream.CompleteAsync(); // I would like to have method like this
I need client to gracefully stop reading responses when gracefulShutdown is set to true.
How do I do this?
If i just stop reading and close channel, server considers it is as abort.
As much as i checked on internet i didnt found any way to do it gracefully. I expected to use CancellationTokenSource. Just use try, catch. Looks like this is intended behaviour. Comment from grpc team
Cancellations are to be used for forcing termination
of outstanding calls due to unexpected circumstances, you shouldn't rely on
them for handling the basic workflow in your application
Use catch block like here to check exception
catch (RpcException e) when (e.Status.StatusCode == StatusCode.Cancelled)
{
Console.WriteLine("Streaming was cancelled from the client!");
}
More info on github C# Clean Cancellation
Using Visual studio 2012, C#.net 4.5 , SQL Server 2008, Feefo, Nopcommerce
Hey guys I have Recently implemented a new review service into a current site we have.
When the change went live the first day all worked fine.
Since then though the sending of sales to Feefo hasnt been working, There are no logs either of anything going wrong.
In the OrderProcessingService.cs in Nop Commerce's Service, i call a HttpWebrequest when an order has been confirmed as completed. Here is the code.
var email = HttpUtility.UrlEncode(order.Customer.Email.ToString());
var name = HttpUtility.UrlEncode(order.Customer.GetFullName().ToString());
var description = HttpUtility.UrlEncode(productVariant.ProductVariant.Product.MetaDescription != null ? productVariant.ProductVariant.Product.MetaDescription.ToString() : "product");
var orderRef = HttpUtility.UrlEncode(order.Id.ToString());
var productLink = HttpUtility.UrlEncode(string.Format("myurl/p/{0}/{1}", productVariant.ProductVariant.ProductId, productVariant.ProductVariant.Name.Replace(" ", "-")));
string itemRef = "";
try
{
itemRef = HttpUtility.UrlEncode(productVariant.ProductVariant.ProductId.ToString());
}
catch
{
itemRef = "0";
}
var url = string.Format("feefo Url",
login, password,email,name,description,orderRef,productLink,itemRef);
var request = (HttpWebRequest)WebRequest.Create(url);
request.KeepAlive = false;
request.Timeout = 5000;
request.Proxy = null;
using (var response = (HttpWebResponse)request.GetResponse())
{
if (response.StatusDescription == "OK")
{
var stream = response.GetResponseStream();
if(stream != null)
{
using (var reader = new StreamReader(stream))
{
var content = reader.ReadToEnd();
}
}
}
}
So as you can see its a simple webrequest that is processed on an order, and all product variants are sent to feefo.
Now:
this hasnt been happening all week since the 15th (day of the
implementation)
the site has been grinding to a halt recently.
The stream and reader in the the var content is there for debugging.
Im wondering does the code redflag anything to you that could relate to the process of website?
Also note i have run some SQL statements to see if there is any deadlocks or large escalations, so far seems fine, Logs have also been fine just the usual logging of Bots.
Any help would be much appreciated!
EDIT: also note that this code is in a method that is called and wrapped in A try catch
UPDATE: well forget about the "not sending", thats because i was just told my code was rolled back last week
A call to another web site while processing the order can degrade performance, as you are calling to a site that you do not control. You don't know how much time it is going to take. Furthermore, the GetResponse method can throw an exception, if you don't log anything in your outer try/catch block then you won't be able to know what's happening.
The best way to perform such a task is to implement something like the "Send Emails" scheduled task, and send data when you can afford to wait for the remote service. It is easy if you try. It is more resilient and easier to maintain if you upgrade the nopCommerce code base.
This is how I do similar things:
Avoid modifying the OrderProcessingService: Create a custom service or plugin that consumes the OrderPlacedEvent or the OrderPaidEvent (just implement the IConsumer<OrderPaidEvent> or IConsumer<OrderPlacedEvent> interface).
Do not call to a third party service directly while processing the request if you don't need the response at that moment. It will only delay your process. At the service created in step 1, store data and send it to Feefo later. You can store data to database or use an static collection if you don't mind losing pending data when restarting the site (that could be ok for statistical data for instance).
Best way to implement point #2 is to add a new scheduled task implementing ITask (remember to add a record to the ScheduleTask table). Just recover the stored data do your processing.
Add some logging. It is easy, just get an ILogger instance and call Insert.
As far as I can see, you are making a blocking synchronous call to other websites, which will definitely slow down your site in between the request-response process. What Marco has suggested is valid, try to do it in an ITask. Or you can use an asynchronous web request to potentially remove the block, if you need things done immediately instead of scheduled. :)
I'm using 2 WebClients in my app, for 2 different weather API's.
When my internet connection is slow I get an exception from one of the API's.. It returns a 404 Notfound error.
I have tested this by disabling my WiFi, and put the data connection to '2G'. The first API returns the data with no problem, the second API however crashes my app with a WebException.
When I turn on the WiFi again it works flawlessly. Looks like the second API has a very little patience with slow connections.
Is there a way to fix this? I have also tried to change the WebClient into a HttpWebRequest but the problem still occurs.
Kind regards,
Niels
EDIT
My code:
private void GettingTheData()
{
WebClient Client = new WebClient();
Client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(Client _DownloadStringCompleted);
Client.DownloadStringAsync(new Uri("http://theURI.com"));
}
void Client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
string result = e.Result.ToString();
// Let's do the cool stuff overhere
}
There exist HTTP Client library for WP which contains support for timeout. Article about it.
Some sample code for Windows Phone 8:
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
var httpClient = new HttpClient {Timeout = TimeSpan.FromSeconds(30)};
var responseBodyAsText = await httpClient.GetStringAsync("www.contoso.com");
}
Maybe the problem isn't the network latency. Perhaps your second API has a requirement that callers send a user-agent string, or some other HTTP header that you aren't sending. The fact that it works over WiFi and not 2G could have something to do with the fact that any device connecting from your WiFi network would appear to be the same to the server hosting the API (from an IP Address standpoint) and may allow access based on some cached identity (maybe you browsed the service to test it from your development PC). I would be interested to see what would happen if you connected to a different WiFi network if the response would be similar.
My immediate suggestion would be to catch the WebException and give the user a chance to retry.
I would have added this as a comment but I guess I don't have enough reputation for that.
Try increasing the ServicePointManager.DefaultConnectionLimit though the default is 2.
I need to create an C# application that will monitor whether a set of web services are up and running. User will select a service name from a dropdown. The program need to test with the corresponding service URL and show whether the service is running. What is the best way to do it? One way I am thinking of is to test whether we are able to download the wsdl. IS there a better way?
Note: The purpose of this application is that the user need to know only the service name. He need not remember/store the corresponding URL of the service.
I need a website version and a desktop application version of this C# application.
Note: Existing services are using WCF. But in future a non-WCF service may get added.
Note: My program will not be aware of (or not interested in ) operations in the service. So I cannot call a service operation.
REFERENCE
How to check if a web service is up and running without using ping?
C program-How do I check if a web service is running
this would not guarantee functionality, but at least you could check connectivity to a URL:
var url = "http://url.to.che.ck/serviceEndpoint.svc";
try
{
var myRequest = (HttpWebRequest)WebRequest.Create(url);
var response = (HttpWebResponse)myRequest.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
// it's at least in some way responsive
// but may be internally broken
// as you could find out if you called one of the methods for real
Debug.Write(string.Format("{0} Available", url));
}
else
{
// well, at least it returned...
Debug.Write(string.Format("{0} Returned, but with status: {1}",
url, response.StatusDescription));
}
}
catch (Exception ex)
{
// not available at all, for some reason
Debug.Write(string.Format("{0} unavailable: {1}", url, ex.Message));
}
This approach works for me.
I used Socket to check if the process can connect.
HttpWebRequest works if you try to check the connection 1-3 times but if you have a process which will run 24hours and from time to time needs to check the webserver availability that will not work anymore because will throw TimeOut Exception.
Socket socket
= new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
var result = socket.BeginConnect("xxx.com", 80, null, null);
// test the connection for 3 seconds
bool success = result.AsyncWaitHandle.WaitOne(3000,false);
var resturnVal = socket.Connected;
if (socket.Connected)
socket.Disconnect(true);
socket.Dispose();
return resturnVal;