Fehlerbehandlung auf dem Client

In diesem Thema wird beschrieben, wie Fehler normalerweise behandelt und bestimmte Schritte als Reaktion auf die Fehler beim Abrufen oder Ändern von Daten von einem Client ausgeführt werden. In WCF RIA Services werden Fehler behandelt, indem eine Rückrufmethode für Datenvorgänge bereitgestellt und in dieser Rückrufmethode überprüft wird, ob Fehler vorliegen. Die Verwendung von Rückrufmethoden ist erforderlich, weil Aufrufe von Datenvorgängen asynchron sind und Ausnahmen daher asynchron ausgelöst werden. Standardmäßig wird für alle Fehler in Domänenvorgängen eine Ausnahme ausgelöst. In RIA Services haben Sie die Möglichkeit, die Fehler zu behandeln und anzugeben, dass keine Ausnahme vom Framework ausgelöst wird.

Fehlerbehandlung beim Laden von Daten

Beim Laden von Daten aus einer Abfragemethode können Sie den Fehler behandeln oder ignorieren. Die folgenden Möglichkeiten stehen Ihnen zur Auswahl:

  • Verwenden Sie eine Load-Methode mit einem Parameter für eine Rückrufmethode. Behandeln Sie den Fehler in der Rückrufmethode, und rufen Sie die MarkErrorAsHandled-Methode auf, um anzugeben, dass die Ausnahme nicht ausgelöst wird.

  • Verwenden Sie eine Load-Methode mit einem boolean-Parameter mit dem Namen throwOnError. Legen Sie throwOnError auf false fest, wenn Sie die Load-Methode aufrufen, um anzugeben, dass keine Ausnahme für Abfragefehler ausgelöst werden soll.

  • Verwenden Sie die Load-Methode ohne einen Parameter für eine Rückrufmethode oder einen boolean-Parameter. Alle Fehler beim Ausführen der Abfrage führen zu einer nicht behandelten Ausnahme.

Das folgende Beispiel zeigt, wie Daten aus einer Abfrage geladen werden und eine Rückrufmethode angegeben wird, die überprüft, ob beim Ladevorgang Fehler aufgetreten sind.

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();
    }
}

Fehlerbehandlung beim Senden von Daten

Beim Senden von Daten können die Ausnahmen nicht wie bei der Load-Methode deaktiviert werden. Alle Fehler beim Senden von Daten führen zu einer Ausnahme. Die folgenden Möglichkeiten stehen Ihnen zur Auswahl:

  • Verwenden Sie die SubmitChanges-Methode, und stellen Sie eine Rückrufmethode als Parameter bereit. Behandeln Sie den Fehler in der Rückrufmethode, und rufen Sie die MarkErrorAsHandled-Methode auf, um anzugeben, dass die Ausnahme nicht ausgelöst wird.

  • Verwenden Sie die SubmitChanges-Methode. Alle Fehler beim Senden von Daten führen zu einer nicht behandelten Ausnahme.

Das folgende Beispiel zeigt, wie die SubmitChanges-Methode mit einer Rückrufmethode zum Behandeln von Fehlern aufgerufen wird.

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();
}

Fehlerbehandlung bei Startvorgängen

Beim Starten eines Vorgangs sind die gleichen Optionen verfügbar wie beim Senden von Daten. Die folgenden Möglichkeiten stehen Ihnen zur Auswahl:

  • Schließen Sie eine Rückrufmethode ein, wenn Sie den Startvorgang aufrufen. Behandeln Sie den Fehler in der Rückrufmethode, und rufen Sie die MarkErrorAsHandled-Methode auf, um anzugeben, dass die Ausnahme nicht ausgelöst wird.

  • Rufen Sie den Startvorgang auf, ohne eine Rückrufmethode einzuschließen. Alle Fehler beim Aufrufen der Methode führen zu einer nicht behandelten Ausnahme.

Das folgende Beispiel zeigt einen Startvorgang mit einer Rückrufmethode.

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;
  }
}

Fehlerbehandlung für den Authentifizierungsdienst

Die AuthenticationService-Klasse ermöglicht es Ihnen, beim Aufrufen der folgenden Methoden eine Rückrufmethode bereitzustellen:

In der Rückrufmethode können Sie Code bereitstellen, um Fehler vom Authentifizierungsdienst zu behandeln. Das folgende Beispiel zeigt, wie die Login-Methode von einem Ereignishandler für eine Anmeldeschaltfläche aufgerufen wird. Um auf die Ergebnisse des Anmeldevorgangs zu reagieren, wird eine Rückrufmethode hinzugefügt.

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;
}