Поделиться через


Контракт сбоя

В примере "Ошибки" показано, как передавать сведения об ошибках из службы клиенту. Пример основан на Руководстве для начинающих, с добавлением дополнительного кода в службу для преобразования внутреннего исключения в сбой. Клиент пытается выполнить деление на ноль, чтобы вызвать ошибку в службе.

Замечание

Процедура установки и инструкции по сборке для этого примера находятся в конце этого раздела.

Контракт калькулятора был изменен, чтобы включить FaultContractAttribute, как показано в следующем примере кода.

[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples")]
public interface ICalculator
{
    [OperationContract]
    int Add(int n1, int n2);
    [OperationContract]
    int Subtract(int n1, int n2);
    [OperationContract]
    int Multiply(int n1, int n2);
    [OperationContract]
    [FaultContract(typeof(MathFault))]
    int Divide(int n1, int n2);
}

Атрибут FaultContractAttribute указывает, что Divide операция может возвращать ошибку типа MathFault. Ошибка может быть любого типа, который можно сериализовать. В этом случае MathFault это контракт данных, как показано ниже.

[DataContract(Namespace="http://Microsoft.ServiceModel.Samples")]
public class MathFault
{
    private string operation;
    private string problemType;

    [DataMember]
    public string Operation
    {
        get { return operation; }
        set { operation = value; }
    }

    [DataMember]
    public string ProblemType
    {
        get { return problemType; }
        set { problemType = value; }
    }
}

Метод Divide выбрасывает FaultException<TDetail> исключение при делении на ноль, как показано в следующем примере кода. Это исключение приводит к тому, что ошибка отправляется клиенту.

public int Divide(int n1, int n2)
{
    try
    {
        return n1 / n2;
    }
    catch (DivideByZeroException)
    {
        MathFault mf = new MathFault();
        mf.operation = "division";
        mf.problemType = "divide by zero";
        throw new FaultException<MathFault>(mf);
    }
}

Код клиента вызывает ошибку, производя деление на ноль. При запуске примера запросы и ответы операции отображаются в окне консоли клиента. Вы видите, что деление на ноль сообщается как сбой. Нажмите клавишу ВВОД в окне клиента, чтобы завершить работу клиента.

Add(15,3) = 18
Subtract(145,76) = 69
Multiply(9,81) = 729
FaultException<MathFault>: Math fault while doing division. Problem: divide by zero

Press <ENTER> to terminate client.

Клиент выполняет это, перехватив соответствующее FaultException<MathFault> исключение:

catch (FaultException<MathFault> e)
{
    Console.WriteLine("FaultException<MathFault>: Math fault while doing " + e.Detail.operation + ". Problem: " + e.Detail.problemType);
    client.Abort();
}

По умолчанию сведения о непредвиденных исключениях не отправляются клиенту, чтобы предотвратить утечку деталей реализации службы за пределы её безопасных границ. FaultContract предоставляет способ описания ошибок в контракте и помечать определенные типы исключений соответствующим образом для передачи клиенту. FaultException<T> предоставляет механизм исполнения для передачи сообщений об ошибках потребителям.

Однако при отладке полезно просмотреть внутренние сведения о сбое службы. Чтобы отключить ранее описанное безопасное поведение, можно указать, что сведения о каждом необработанных исключениях на сервере должны быть включены в ошибку, отправляемую клиенту. Это достигается путем установки IncludeExceptionDetailInFaults на true. Его можно задать в коде или в конфигурации, как показано в следующем примере.

<behaviors>
  <serviceBehaviors>
    <behavior name="CalculatorServiceBehavior">
      <serviceMetadata httpGetEnabled="True"/>
      <serviceDebug includeExceptionDetailInFaults="True" />
    </behavior>
  </serviceBehaviors>
</behaviors>

Кроме того, поведение должно быть связано со службой путем указания атрибута behaviorConfiguration службы в файле конфигурации как "CalculatorServiceBehavior".

Чтобы поймать такие ошибки на клиенте, необходимо поймать FaultException, который не является универсальным.

Это поведение должно использоваться только для отладки и никогда не должно быть включено в рабочей среде.

Настройка, сборка и запуск примера

  1. Убедитесь, что вы выполнили процедуру настройки One-Time для образцов Windows Communication Foundation.

  2. Чтобы создать версию решения на C# или Visual Basic .NET, следуйте инструкциям по сборке примеров Windows Communication Foundation .

  3. Чтобы запустить пример в конфигурации с одним или несколькими компьютерами, следуйте инструкциям в запуска примеров Windows Communication Foundation.