Gestione degli errori sul client

In questo argomento viene descritto come gestire generalmente gli errori e come eseguire alcuni passaggi in risposta agli errori rilevati quando si recuperano o modificano i dati da un client. Con WCF RIA Services gli errori vengono gestiti fornendo un metodo di callback per le operazioni sui dati e controllando la presenza degli errori nel metodo di callback. L'utilizzo dei metodi di callback è necessario poiché le chiamate alle operazioni sui dati sono asincrone e pertanto qualsiasi eccezione viene generata in modo asincrono. Per impostazione predefinita, un'eccezione viene generata per qualsiasi errore nelle operazioni di dominio. Servizi RIA consente di gestire gli errori e di specificare che il framework non genera un'eccezione.

Gestione degli errori durante il caricamento di dati

Durante il caricamento dei dati da un metodo di query è possibile gestire l'errore o scegliere di ignorarlo. In particolare, è possibile scegliere tra le opzioni seguenti:

  • Utilizzare un metodo Load che dispone di un parametro per un metodo di callback. Nel metodo di callback gestire l'errore e chiamare il metodo MarkErrorAsHandled per indicare che l'eccezione non viene generata.

  • Utilizzare un metodo Load che dispone di un parametro boolean denominato throwOnError. Impostare throwOnError su false quando si chiama il metodo Load per indicare che non si desidera che venga generata un'eccezione per gli errori di query.

  • Utilizzare il metodo Load che non dispone di un parametro per un metodo di callback o di un parametro boolean. Qualsiasi errore rilevato durante l'esecuzione della query comporterà un'eccezione non gestita.

Nell'esempio seguente viene illustrato come caricare i dati da una query e specificare un metodo di callback che verifica la presenza di errori nell'operazione di caricamento.

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

Gestione degli errori durante l'invio di dati

Durante l'invio di dati, non è possibile scegliere di disattivare le eccezioni come accade per il metodo Load. Qualsiasi errore rilevato durante l'invio di dati comporterà un'eccezione. In particolare, è possibile scegliere tra le opzioni seguenti:

  • Utilizzare il metodo SubmitChanges e fornire un metodo di callback come parametro. Nel metodo di callback gestire l'errore e chiamare il metodo MarkErrorAsHandled per indicare che l'eccezione non viene generata.

  • Utilizzare il metodo SubmitChanges. Qualsiasi errore rilevato durante l'invio dei dati comporterà un'eccezione non gestita.

Nell'esempio seguente viene illustrato come chiamare il metodo SubmitChanges con un metodo di callback per la gestione degli errori.

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

Gestione degli errori con le operazioni invoke

Durante l'esecuzione di un'operazione invoke, sono disponibili le stesse opzioni di quelle presenti durante l'invio di dati. In particolare, è possibile scegliere tra le opzioni seguenti:

  • Includere un metodo di callback quando si chiama l'operazione invoke. Nel metodo di callback gestire l'errore e chiamare il metodo MarkErrorAsHandled per indicare che l'eccezione non viene generata.

  • Chiamare l'operazione invoke senza includere un metodo di callback. Qualsiasi errore rilevato durante il richiamo del metodo comporterà un'eccezione non gestita.

Nell'esempio seguente viene illustrata un'operazione invoke con un metodo di callback.

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

Gestione degli errori con il servizio di autenticazione

La classe AuthenticationService consente di fornire un metodo di callback quando si chiamano i metodi seguenti:

Nel metodo di callback è possibile fornire il codice per gestire gli errori dal servizio di autenticazione. Nell'esempio seguente viene illustrato come chiamare il metodo Login da un gestore eventi per un pulsante di accesso. Viene incluso un metodo di callback per rispondere ai risultati dell'operazione di accesso.

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