Error Handling on the Client
[WCF RIA Services Version 1 Service Pack 2 is compatible with either .NET framework 4 or .NET Framework 4.5, and with either Silverlight 4 or Silverlight 5.]
This topic describes how you typically want to handle errors and take certain steps in response to the errors that you retrieve or modify data from a client. With WCF RIA Services, you handle errors by providing a callback method for data operations and checking for errors in that callback method. Using callback methods is necessary because calls to data operations are asynchronous and therefore any exceptions are thrown asynchronously. By default, an exception is thrown for any errors in domain operations. RIA Services provides ways for you to handle the errors and specify that the framework not throw an exception.
Error Handling When Loading Data
When loading data from a query method, you can either handle the error or choose to ignore the error. Specifically, you choose from the following options:
Use a Load method that has a parameter for a callback method. In the callback method, handle the error and call the MarkErrorAsHandled method to indicate that the exception is not thrown.
Use a Load method that has a boolean parameter named throwOnError. Set throwOnError to false when you call the Load method to indicate that you do not want an exception thrown for query errors.
Use the Load method which does not have a parameter for a callback method or a boolean parameter. Any errors when running the query will result in an unhandled exception.
The following example shows how to load data from a query and specify a callback method that checks for errors from the load operation.
Private _customerContext As New CustomerDomainContext
Public Sub New()
InitializeComponent()
Dim loadOp = Me._customerContext.Load(Me._customerContext.GetCustomersQuery(), AddressOf OnLoadCompleted, Nothing)
CustomerGrid.ItemsSource = loadOp.Entities
End Sub
Private Sub OnLoadCompleted(ByVal lo As LoadOperation(Of Customer))
If (lo.HasError) Then
MessageBox.Show(String.Format("Retrieving data failed: {0}", lo.Error.Message))
lo.MarkErrorAsHandled()
End If
End Sub
private CustomerDomainContext _customerContext = new CustomerDomainContext();
public MainPage()
{
InitializeComponent();
LoadOperation<Customer> loadOp = this._customerContext.Load(this._customerContext.GetCustomersQuery(), OnLoadCompleted, null);
CustomerGrid.ItemsSource = loadOp.Entities;
}
private void OnLoadCompleted(LoadOperation<Customer> lo)
{
if (lo.HasError)
{
MessageBox.Show(string.Format("Retrieving data failed: {0}", lo.Error.Message));
lo.MarkErrorAsHandled();
}
}
Error Handling When Submitting Data
When submitting data, you cannot choose to turn off the exceptions as you can with the Load method. Any errors when submitting data will result in an exception. Specifically, you choose from the following options:
Use the SubmitChanges method and provide a callback method as a parameter. In the callback method, handle the error and call the MarkErrorAsHandled method to indicate that the exception is not thrown.
Use the SubmitChanges method. Any errors when submitting the data will result in an unhandled exception.
The following example shows how to call the SubmitChanges method with a callback method for handling errors.
Private Sub SaveButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
_customerContext.SubmitChanges(AddressOf OnSubmitCompleted, Nothing)
End Sub
Private Sub RejectButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
_customerContext.RejectChanges()
CheckChanges()
End Sub
Private Sub CustomerGrid_RowEditEnded(ByVal sender As System.Object, ByVal e As System.Windows.Controls.DataGridRowEditEndedEventArgs)
CheckChanges()
End Sub
Private Sub CheckChanges()
Dim changeSet = _customerContext.EntityContainer.GetChanges()
ChangeText.Text = changeSet.ToString()
Dim hasChanges = _customerContext.HasChanges
SaveButton.IsEnabled = hasChanges
RejectButton.IsEnabled = hasChanges
End Sub
Private Sub OnSubmitCompleted(ByVal so As SubmitOperation)
If (so.HasError) Then
MessageBox.Show(String.Format("Submit Failed: {0}", so.Error.Message))
so.MarkErrorAsHandled()
End If
CheckChanges()
End Sub
private void SaveButton_Click(object sender, RoutedEventArgs e)
{
_customerContext.SubmitChanges(OnSubmitCompleted, null);
}
private void RejectButton_Click(object sender, RoutedEventArgs e)
{
_customerContext.RejectChanges();
CheckChanges();
}
private void CustomerGrid_RowEditEnded(object sender, DataGridRowEditEndedEventArgs e)
{
CheckChanges();
}
private void CheckChanges()
{
EntityChangeSet changeSet = _customerContext.EntityContainer.GetChanges();
ChangeText.Text = changeSet.ToString();
bool hasChanges = _customerContext.HasChanges;
SaveButton.IsEnabled = hasChanges;
RejectButton.IsEnabled = hasChanges;
}
private void OnSubmitCompleted(SubmitOperation so)
{
if (so.HasError)
{
MessageBox.Show(string.Format("Submit Failed: {0}", so.Error.Message));
so.MarkErrorAsHandled();
}
CheckChanges();
}
Error Handling With Invoke Operations
When invoking an operation, you have the same options available as when you submit data. Specifically, you choose from the following options:
Include a callback method when you call the invoke operation. In the callback method, handle the error and call the MarkErrorAsHandled method to indicate that the exception is not thrown.
Call the invoke operation without including a callback method. Any errors when invoking the method will result in an unhandled exception.
The following example shows an invoke operation with a callback method.
Dim invokeOp As InvokeOperation(Of Integer)
invokeOp = customerContext.GetLocalTemperature(selectedPostalCode, AddressOf OnInvokeCompleted, Nothing)
Private Sub OnInvokeCompleted(ByVal invOp As InvokeOperation(Of Integer))
If (invOp.HasError) Then
MessageBox.Show(String.Format("Method Failed: {0}", invOp.Error.Message))
invOp.MarkErrorAsHandled()
Else
result = invOp.Value
End If
End Sub
InvokeOperation<int> invokeOp = customerContext.GetLocalTemperature(selectedPostalCode, OnInvokeCompleted, null);
private void OnInvokeCompleted(InvokeOperation<int> invOp)
{
if (invOp.HasError)
{
MessageBox.Show(string.Format("Method Failed: {0}", invOp.Error.Message));
invOp.MarkErrorAsHandled();
}
else
{
result = invokeOp.Value;
}
}
Error Handling with Authentication Service
The AuthenticationService class enables you to provide a callback method when you call the following methods:
In the callback method, you can provide code to handle errors from the authentication service. The following example shows how to call the Login method from an event handler for a login button. A callback method is included to respond to the results of the login operation.
Private Sub LoginButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
Dim lp As LoginParameters = New LoginParameters(UserName.Text, Password.Password)
WebContext.Current.Authentication.Login(lp, AddressOf Me.LoginOperation_Completed, Nothing)
LoginButton.IsEnabled = False
LoginResult.Text = ""
End Sub
Private Sub LoginOperation_Completed(ByVal lo As LoginOperation)
If (lo.HasError) Then
LoginResult.Text = lo.Error.Message
LoginResult.Visibility = System.Windows.Visibility.Visible
lo.MarkErrorAsHandled()
ElseIf (lo.LoginSuccess = False) Then
LoginResult.Text = "Login failed. Please check user name and password."
LoginResult.Visibility = System.Windows.Visibility.Visible
ElseIf (lo.LoginSuccess = True) Then
SetControlVisibility(True)
End If
LoginButton.IsEnabled = True
End Sub
private void LoginButton_Click(object sender, RoutedEventArgs e)
{
LoginParameters lp = new LoginParameters(UserName.Text, Password.Password);
WebContext.Current.Authentication.Login(lp, this.LoginOperation_Completed, null);
LoginButton.IsEnabled = false;
LoginResult.Text = "";
}
private void LoginOperation_Completed(LoginOperation lo)
{
if (lo.HasError)
{
LoginResult.Text = lo.Error.Message;
LoginResult.Visibility = System.Windows.Visibility.Visible;
lo.MarkErrorAsHandled();
}
else if (lo.LoginSuccess == false)
{
LoginResult.Text = "Login failed. Please check user name and password.";
LoginResult.Visibility = System.Windows.Visibility.Visible;
}
else if (lo.LoginSuccess == true)
{
SetControlVisibility(true);
}
LoginButton.IsEnabled = true;
}