One pattern for how to handle errors/exceptions during async calls in MvvmCross is available in the BestSellers example: MvvmCross BestSellers Sample
BestSellers uses 2 techniques that I find I've used quite a lot in MvvmCross applications:
- the use of BaseViewModel classes for shared ViewModel code like error handling
- the use of an app level "error router" to get errors from the ViewModels to UI notifications like UIAlertViews, Toasts and/or MessageBoxes.
At a more detailed level, what BestSellers does is:
Each ViewModel uses a direct call to a webservice for book information. For example the Category List is constructed as:
public CategoryListViewModel()
{
AsyncLoad();
}
private void AsyncLoad()
{
GeneralAsyncLoad(URL_CATEGORIES, ProcessResult);
}
where GeneralAsyncLoad is defined in a shared BaseViewModel:
protected void GeneralAsyncLoad(string url, Action responseStreamHandler)
{
try
{
IsLoading = true;
var request = WebRequest.Create(url);
request.BeginGetResponse((result) => GeneralProcessResponse(request, result, responseStreamHandler), null);
}
catch (ThreadAbortException)
{
throw;
}
// obviously we could do better than catching all `Exception` here!
catch (Exception exception)
{
IsLoading = false;
ReportError("Sorry - problem seen " + exception.Message);
}
}
The ReportError method within the above exception handler uses an injected object - an
IErrorReporter
.
This injected object is initialised as a singleton during App construction - see
ErrorApplicationObject
in App.cs
During their construction and setup, the UI projects all subscribe to events from that same singleton - but using an
IErrorSource
interface instead or IErrorReporter
.
This then allows each platform to display it's own error display - e.g.:
- iOS shows an UIAlertView in its ErrorDisplayer.cs
- Android shows a Toast in its ErrorDisplayer.cs
- WP7 shows a MessageBox from code within App.xaml.cs
Obviously, if you need error handling as well as error displaying - e.g. if you want to retry the asynchronous operation or if you want to load an offline copy of data instead - then you can add this to your error handling within the ViewModel and the BaseViewModel.
Stuart,
ReplyDeleteHow does this process work in v3? I've tried adding this concept into my v3 app but I think the framework has changed to the point where this approach doesn't work any more.
I will implement my own error reporting using a messagenger approach but would like to use this "common" approach if it is still available.
Cheers,
Steve
Afaik this approach should still work... However, I too now generally use the MvxMessenger plugin for distributing the error messages now instead of using the IErrorSource interface. (The MvxMessenger has a SubscribeOnMainThread method which helps for the UI code)
DeleteCool, I'll continue on down this road then :)
DeleteIn case you're wondering... any comment on a post older than 3 months gets moderated... sorry, it just helps to keep the spam down... :)
DeleteYes, I noticed that :) No worries.....
ReplyDeleteOk, so where in the View do I subscribe to messages, I tried this code which doesn't get executed:
ReplyDeletepublic HomeView(IMvxMessenger messenger)
{
_messenger = messenger;
// Subscribe to inter-app message "ApplicationError_Message"
_messageToken =
messenger.SubscribeOnMainThread(Display_Error);
}
Steve
Please take this to StackOverflow - easier to write and format better questions and answers there.
Deletehttp://stackoverflow.com/questions/16696357/subscribing-to-mvxmessage-from-android-client
Delete