.NET RIA Services Exception handling
Note: This post is based on the July preview of the .NET RIA Services, so changes may happen in a future release of the framework
At the moment I’m updating a code example for my Silverlight 3.0 course and have added some exception handling to the code. I also got a question about how to handle exception while calling the Load operation of the DomainService class. So I decided to write a blog post about it, maybe someone more have the same question.
By default if you make a call to a DomainService query
method, you will not get an exception on the client-side, if
you don’t adding some extra code. Lets pretend that the
following code is your DomainService and Query method:
public class MyDomainService : DomainService { public IEnumerable<Customer> GetCustomers() { //Code that can throw an exception; } }
The method above will throw an exception. If you on the
client-side want to “call/use” the GetCustomers method, you
will use the generated DomainContext class’s Load method:
var d = new MyDomainContext(); var loadOperation = d.Load<Customer>(d.GetCustomersQuery(), MyCallBack, null); LayoutRoot.DataContext = d.Customers;
When this code is executed, you will not get any
exception, so the user or you may think that no exception
have occurred. But that isn’t the case. So what I’m going to
write about now, is different way you can check if an
exception occurred (Wouldn’t it be nice if we only could get
an exception instead of adding extra code to check if an
exception is thrown ;)).
The LoadOperation class has two properties we can use, HasError and Error. To check if we got an exception we can use the HasError property, if we want to get information about an exception, we can use the Error property. The first example I’m going to use, will only display an exception for the client.
On the client-side I have a StackPanel called myErrorPanel, it also have a TextBlock where the Text property is bound to a property path “Error.Message”.
<StackPanel x:Name="myErrorPanel"> <TextBlock Text="{Binding Path=Error.Message}"></TextBlock> </StackPanel>
In the code-behind we can now write the following code
which will bound the LoadOperation to the myErrorPanel:
var d = new MyDomainContext(); var loadOperation = d.Load<Customer>(d.GetCustomersQuery()); LayoutRoot.DataContext = d.Customers; myErrorPanel.DataContext = loadOperation;
If the Load method of our DominContext has an error,
the Error Message will be displayed for the User. By using
this solution, we will not have any idea if an error has
occurred during the Load operation, if it does it will only
be shown for the User. The StackPanel will also take up some
space on the user interface, so to solve it we can for
example add a Converter, and bound the HasError to the
StackPanel’s Visibility property. The following two other
solution will instead show us, how we can use a callback
method and the LoadOperation’s Complteted event to have a
better control if an exception is thrown during the Load
operation.
The DomainContext’s Load method can take a callback as an
parameter, by using a callback, we will get a notification
when the Load operation is completed, and we can also see if
there was any error during the Load operation. The following
code will use a callback and check if an error has occurred:
var d = new MyDomainContext(); var loadOperation = d.Load<Customer>(d.GetCustomersQuery(), MyCallBack, null); ... void MyCallBack(LoadOperation<Customer> loadOperation) { if (loadOperation.HasError) //Handle the error }
The following solution will use the LoadOptions’s
Completed event to check if an error has occurred:
var d = new MyDomainContext(); var loadOperation = d.Load<Customer>(d.GetCustomersQuery()); loadOption.Completed += new EventHandler(loadOption_Completed); ... void loadOption_Completed(object sender, EventArgs e) { if (((LoadOperation)sender).HasError) //handle the error }
If you wonder what solution I prefer, it would be the
one that uses a callback. I do want to see some changes to
the .NET RIA Services Load operations, like specifying a
callback just for handling exceptions, and a default
generated callback added to the DominaContext, which will be
called if no callback is used, by doing so, we could get an
exception when the Load fails without adding some extra
code.