Where to catch exception in WebClient method? - json

I'm developing app which connects to service and consume some JSON data. Consuming works great (JSON.net rocks) but I wonder where I should catch exception error annd show simple MessageBox? Tried in few places but still my app is closing. Or maybe I should do it based on json response which contain error tag? I think that normal error handling could be easier, but have blank spot in my mind now..
Code is below:
private void LoginLoginButton_Click(object sender, System.EventArgs e)
{
((ApplicationBarIconButton)ApplicationBar.Buttons[0]).IsEnabled = false;
ProgressOverlay.Show();
GenerateLoginString();
var w = new SharpGIS.GZipWebClient();
Observable.FromEvent<DownloadStringCompletedEventArgs>(w, "DownloadStringCompleted")
.Subscribe(r =>
{
var settings = IsolatedStorageSettings.ApplicationSettings;
var deserializedRootObject = JsonConvert.DeserializeObject<RootObject>(r.EventArgs.Result);
UserSettings us = new UserSettings()
{
first_name = deserializedRootObject.user.first_name,
last_name = deserializedRootObject.user.last_name,
user_id = deserializedRootObject.user_id,
};
settings.Add("UserSettings", us);
settings.Save();
});
w.DownloadStringAsync(new Uri(UserUri));
w.DownloadStringCompleted += new DownloadStringCompletedEventHandler(w_DownloadStringCompleted);
}
void w_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
NavigationService.Navigate(new Uri("/MainPage.xaml", UriKind.Relative));
}

If you mean you want to catch an exception which occurs in your web client call then it should be in the Error property of DownloadStringCompletedEventArgs.
void w_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if(e.Error != null)
{
MessageBox.Show("An error occurred!");
}
else
{
NavigationService.Navigate(new Uri("/MainPage.xaml", UriKind.Relative));
}
}

Solved!
I used try and catch in this case. Works perfect :)

Related

How to get a Toast Notification when app running in foreground in wp8

I want to implement the "toast" notification inside my windows phone application. I'm implementing push message's, but I want them to show always. No matter if the application is running or not. The push notification will handle it when the application is closed, but not when it is running. Also if I create a shelltoast manually it won't show. To make it more difficult I can't use any external dll's. I only want to use code. What would be the best way to do this? I already know about the ToastNotificationRecieved event. I want to know how to implement it so that it will show a "toast" like message without using a framework
My code is below
PushPlugin.cs(c# code)
public void showToastNotification(string options)
{
ShellToast toast;
if (!TryDeserializeOptions(options, out toast))
{
this.DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
return;
}
Deployment.Current.Dispatcher.BeginInvoke(toast.Show);
}
public void PushChannel_ShellToastNotificationReceived(object sender, NotificationEventArgs e)
{
var toast = new PushNotification
{
Type = "toast"
};
foreach (var item in e.Collection)
{
toast.JsonContent.Add(item.Key, item.Value);
}
this.ExecuteCallback(this.pushOptions.NotificationCallback, JsonConvert.SerializeObject(toast));
}
In javascript
function onNotificationWP8(data) {
var pushNotification;
pushNotification = window.plugins.pushNotification;
pushNotification.showToastNotification(successHandler, errorHandler,
{
"Title": data.jsonContent["wp:Text1"], "Content": data.jsonContent["wp:Text2"], "NavigationUri": data.jsonContent["wp:Param"]
});
}
On devices without Windows Phone 8 Update 3, toast notifications are not displayed when the target app is running in the foreground. On devices with Windows Phone 8 Update 3, toast notifications are displayed when the target app is running in the foreground, but is obscured by other activity such as a phone call or the lock screen.
The following C# code example shows the properties used to create a toast notification using local code.
// Create a toast notification.
// The toast notification will not be shown if the foreground app is running.
ShellToast toast = new ShellToast();
toast.Title = "[title]";
toast.Content = "[content]";
toast.Show();
This thread has it all you looking for
public static class Notification
{
public static string ChannelURI = string.Empty;
public static void MainNotificationCallFunction()
{
try
{
NotificationMessage("Test Notification");
}
catch (Exception e)
{ }
}
public static void NotificationMessage(string Message)
{
try
{
ToastTemplateType toastType = ToastTemplateType.ToastText02;
XmlDocument toastXmlJob = ToastNotificationManager.GetTemplateContent(toastType);
XmlNodeList toastTextElementJob = toastXmlJob.GetElementsByTagName("text");
toastTextElementJob[0].AppendChild(toastXmlJob.CreateTextNode(Message));
IXmlNode toastNodeJob = toastXmlJob.SelectSingleNode("/toast");
((XmlElement)toastNodeJob).SetAttribute("duration", "long");
ToastNotification toastJob = new ToastNotification(toastXmlJob);
ToastNotificationManager.CreateToastNotifier().Show(toastJob);
}
catch (Exception e)
{ }
}
public static void PushNotification()
{
try
{
/// Holds the push channel that is created or found.
HttpNotificationChannel pushChannel;
string channelName = "Usman's Channel";
// Try to find the push channel.
pushChannel = HttpNotificationChannel.Find(channelName);
// If the channel was not found, then create a new connection to the push service.
if (pushChannel == null)
{
pushChannel = new HttpNotificationChannel(channelName);
//// Register for all the events before attempting to open the channel.
pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(PushChannel_ChannelUriUpdated);
pushChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(PushChannel_ErrorOccurred);
pushChannel.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(PushChannel_HttpNotificationReceived);
pushChannel.Open();
pushChannel.BindToShellTile();
pushChannel.BindToShellToast();
}
else
{
//// The channel was already open, so just register for all the events.
pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(PushChannel_ChannelUriUpdated);
pushChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(PushChannel_ErrorOccurred);
pushChannel.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(PushChannel_HttpNotificationReceived);
}
}
catch (Exception ex)
{ }
}
private static void PushChannel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)
{
try
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
// Display the new URI for testing purposes. Normally, the URI would be passed back to your web service at this point.
System.Diagnostics.Debug.WriteLine(e.ChannelUri.ToString());
MessageBox.Show(String.Format("Channel Uri is {0}", e.ChannelUri.ToString()));
});
}
catch (Exception ex)
{ }
}
private static void PushChannel_ErrorOccurred(object sender, NotificationChannelErrorEventArgs e)
{
try
{
// Error handling logic for your particular application would be here.
Deployment.Current.Dispatcher.BeginInvoke(() =>
MessageBox.Show(String.Format("A push notification {0} error occurred. {1} ({2}) {3}", e.ErrorType, e.Message, e.ErrorCode, e.ErrorAdditionalData)));
}
catch (Exception ex)
{ }
}
private static void PushChannel_HttpNotificationReceived(object sender, HttpNotificationEventArgs e)
{
try
{
string message;
using (System.IO.StreamReader reader = new System.IO.StreamReader(e.Notification.Body))
{
message = reader.ReadToEnd();
}
Deployment.Current.Dispatcher.BeginInvoke(() => MessageBox.Show(String.Format("Received Notification {0}:\n{1}", DateTime.Now.ToShortTimeString(), message)));
}
catch (Exception ex)
{ }
}
private static void channel_ErrorOccurred(object sender, NotificationChannelErrorEventArgs e)
{
try
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(e.Message, "Error", MessageBoxButton.OK);
});
}
catch (Exception ex)
{ }
}
private static void channel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)
{
try
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
//ProgressBarPushNotifications.Visibility = System.Windows.Visibility.Collapsed;
MessageBox.Show(e.ChannelUri.ToString(), "Uri Recieved", MessageBoxButton.OK);
});
}
catch (Exception ex)
{ }
}
private static void channel_ShellToastNotificationReceived(object sender, HttpNotificationEventArgs e)
{
try
{
StringBuilder message = new StringBuilder();
string relativeUri = string.Empty;
message.AppendFormat("Received Toast {0}:\n", DateTime.Now.ToShortTimeString());
using (System.IO.StreamReader reader = new System.IO.StreamReader(e.Notification.Body))
{
message.AppendFormat(reader.ReadToEnd());
}
// Display a dialog of all the fields in the toast.
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(message.ToString());
});
}
catch (Exception ex)
{ }
}
}

WebClient TimeOut Windows Phone 8

I would like to run a task during the waiting of a web request. If the task finishes before the request can return a response, then I would display a message "The server is taking too long". I'm using a WebClient object, how can I manage the time out?
public Class Result
{
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (NavigationContext.QueryString.TryGetValue("critere", out sCritere))
{
try
{
_datamanager = new DataManager();
_datamanager.m_evt_Client_DownloadStringCompleted += OnDownloadStringCompleted;
_datamanager.DownloadXmlData(DataManager.URL_RECHERCHE, sCritere);
//HERE I NEED TO RUN A TIMER If the response is too long i would display a message
}
catch(Exception ex)
{
MessageBox.Show(ex.Message, "Erreur", MessageBoxButton.OK);
NavigationService.GoBack();
NavigationService.RemoveBackEntry();
}
}
}
}
public Class DataManager
{
public void DownloadXmlData(string uri, string critere = "")
{
try
{
WebClient client = new WebClient();
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
client.Credentials = new NetworkCredential(UserSaved, PasswordSaved, domain);
client.DownloadStringAsync(new Uri(uri + critere));
}
catch(WebException )
{
throw new WebException(MyExceptionsMessages.Webexception) ;
}
catch (Exception )
{
throw new UnknowException(MyExceptionsMessages.UnknownError);
}
}
public void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
//raise Downloadstringcompleted event if error==null
}
}
You can use BackgroundWorker..
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += (s, e) =>
{
// your task to do while webclient is downloading
};
bw.RunWorkerCompleted += (s, e) =>
{
// check whether DownloadStringCompleted is fired or not
// if not, cancel the WebClient's asynchronous call and show your message.
client.CancelAsync();
MessageBox.Show("message");
}
client.DownloadStringAsync(uri);
bw.RunWorkerAsync();

Deregister the EventHandler in Windows Phone 8 application

I am using this piece of code to register the event and want to de-register Event after completing it's task but don't know how to do problem is that I am using local object for registering event..
code..
public void loadData()
{
//Here client is loacal object..
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(AccessTokenDownloadCompleted);
}
void AccessTokenDownloadCompleted(object sender, DownloadStringCompletedEventArgs e)
{
}
If I understood you correctly, you want to remove your event handler after the download is completed. To remove an event handler, all you need to do is:
client.DownloadStringCompleted -= new DownloadStringCompletedEventHandler(AccessTokenDownloadCompleted);
Note the -= instead of +=.
Place this code where the download completes and you should be fine.
Maybe you can try this:
public void loadData()
{
//Here client is loacal object..
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(AccessTokenDownloadCompleted);
}
void AccessTokenDownloadCompleted(object sender, DownloadStringCompletedEventArgs e)
{
Client client = sender as Client;
if(client != null)
client.DownloadStringCompleted -= new DownloadStringCompletedEventHandler(AccessTokenDownloadCompleted);
}

ASync JSON REST call problem with MVVM

I am trying to implement the MVVM patter for my WP7 Silverlight app and I am running into a problem with the async JSON Rest call. I moved into my ViewModel class the following two methods that were on my WP7 app Page.
public void FetchGames()
{
ObservableCollection<Game> G = new ObservableCollection<Game>();
//REST call in here
var webClient = new WebClient();
Uri uri = new Uri("http://www.somewebsite.com/get/games/league/" + league);
webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(OpenReadCompletedGames);
webClient.OpenReadAsync(uri);
}
private void OpenReadCompletedGames(object sender, OpenReadCompletedEventArgs e)
{
DataContractJsonSerializer ser = null;
ser = new DataContractJsonSerializer(typeof(ObservableCollection<Game>));
Games = ser.ReadObject(e.Result) as ObservableCollection<Game>;
this.IsDataLoaded = true;
}
Now the problem is that because it is an async call the following code does not work. The following code is on my app Page.
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (NavigationContext.QueryString.TryGetValue("league", out league))
{
try
{
App.gViewModel.league = league;
App.gViewModel.FetchGames();
if(App.gViewModel.IsDataLoaded)
{
lbTeams.ItemsSource = App.gViewModel.Games;
}
}
catch ()
{
//error logging in here
}
}
}
Stepping thru the code shows that FetchGames is called then hits the next line ( if(App.gViewModel.IsDataLoaded)
) before the async call is finished. So IsDataLoaded is always false and I cant bind the listbox on the page.
Doing a lot of googleing I have some possible solutions but I am unable convert them to my particular problem. One is like this and it has to do with continuation passing style'. I couldn't get it to work tho and would greatly appreciate some help.
Thanks!
void DoSomethingAsync( Action<string> callback ) {
HttpWebRequest req; // TODO: build your request
req.BeginGetResponse( result => {
// This anonymous function is a closure and has access
// to the containing (or enclosing) function.
var response = req.EndGetResponse( result );
// Get the result string and call the callback
string resultString = null; // TODO: read from the stream
callback(resultString);
}, null );
}
This can be resolved by moving
lbTeams.ItemsSource = App.gViewModel.Games;
to the end of the OpenReadCompletedGames method. You'll need to use the Dispatcher to update the UI from here.
Dispatcher.BeginInvoke( () => { lbTeams.ItemsSource = App.gViewModel.Games; } );

json ihttpmodule compression

I wrote an IHttpModule that compress my respone using gzip (I return a lot of data) in order to reduce response size.
It is working great as long as the web service doesn't throws an exception.
In case exception is thrown, the exception gzipped but the Content-encoding header is disappear and the client doesn't know to read the exception.
How can I solve this? Why the header is missing? I need to get the exception in the client.
Here is the module:
public class JsonCompressionModule : IHttpModule
{
public JsonCompressionModule()
{
}
public void Dispose()
{
}
public void Init(HttpApplication app)
{
app.BeginRequest += new EventHandler(Compress);
}
private void Compress(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
HttpRequest request = app.Request;
HttpResponse response = app.Response;
try
{
//Ajax Web Service request is always starts with application/json
if (request.ContentType.ToLower(CultureInfo.InvariantCulture).StartsWith("application/json"))
{
//User may be using an older version of IE which does not support compression, so skip those
if (!((request.Browser.IsBrowser("IE")) && (request.Browser.MajorVersion <= 6)))
{
string acceptEncoding = request.Headers["Accept-Encoding"];
if (!string.IsNullOrEmpty(acceptEncoding))
{
acceptEncoding = acceptEncoding.ToLower(CultureInfo.InvariantCulture);
if (acceptEncoding.Contains("gzip"))
{
response.AddHeader("Content-encoding", "gzip");
response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);
}
else if (acceptEncoding.Contains("deflate"))
{
response.AddHeader("Content-encoding", "deflate");
response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress);
}
}
}
}
}
catch (Exception ex)
{
int i = 4;
}
}
}
Here is the web service:
[WebMethod]
public void DoSomething()
{
throw new Exception("This message get currupted on the client because the client doesn't know it gzipped.");
}
I appriciate any help.
Thanks!
Even though it's been a while since you posted this question, I just had the same issue and here's how I fixed it:
In the Init() method, add a handler for the Error event
app.Error += new EventHandler(app_Error);
In the handler, remove Content-Type from the Response headers and set the Response.Filter property to null.
void app_Error(object sender, EventArgs e)
{
HttpApplication httpApp = (HttpApplication)sender;
HttpContext ctx = HttpContext.Current;
string encodingValue = httpApp.Response.Headers["Content-Encoding"];
if (encodingValue == "gzip" || encodingValue == "deflate")
{
httpApp.Response.Headers.Remove("Content-Encoding");
httpApp.Response.Filter = null;
}
}
Maybe there's a more elegant way to do this but did the trick for me.