Как вернуть стандартное сообщение об исключении / ошибке в WCF

В нашем приложении все данные контракта имеют одного родителя - OperationResponse и это OperationResponse содержит enum (тип enum OperationState в собственности Result) который представляет результат вызова (Ok, InvalidParams, Error).

Как я могу переписать поведение WCF после исключения - не возвращать состояние ошибки, а возвращать классическое сообщение, в моем случае OperationResponse, но со свойством Result = OperationState.Error?

Изменить: Я думаю, я на правильном пути, мне нужно реализовать IErrorHandler, но теперь я потерян, потому что я не знаю, как установить сообщение об ошибке в исходящее сообщение об ошибке...

public bool HandleError(Exception error)
{
    // log error
    return true; // we catch error and provide our custom message.
}

public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
    // create result message
    var message = new OperationResponse
    {
        Result = OperationState.Error
    };

    // ok how to return message into ref fault?
}

Edit2: кажется, что это неразрешимая проблема без решения... Я нашел только те же вопросы без решения, как эта тема...:(

1 ответ

Решение

Я не уверен, что это именно то, что вы ищете, но это довольно управляемый способ обработки ошибок из WCF (и, возможно, других систем / контекстов).

Здесь мы создаем общий ServiceResponse<T>, который может содержать любой тип ответа в свойстве Dataи информация о состоянии в Succeeded а также StatusMessage,

Использовать CreateServiceResponse() чтобы обернуть, какой метод вы хотите вызвать внутри этого объекта. Таким образом, вы можете вернуть ServiceResponse с Data установить на результат от этого метода. Ниже приведен пример использования.

Возможно, вы можете настроить это, чтобы вернуть экземпляр вашего OperationResponse с OperationState вместо Succeeded собственность используется здесь?

public class ServiceResponse<T>
{
    public ServiceResponse()
    {
        // Initial default values:
        Data = default(T);
        Succeeded = true;
        StatusMessage = string.Empty;
    }

    // Indicates whether the attempted operation was completed successfully. 
    [DataMember]
    public bool Succeeded { get; set; }

    // Error messages if an operation fails.
    [DataMember]
    public string StatusMessage { get; set; }

    // The main results from any service-call.        
    [DataMember]
    public T Data { get; set; }

    [DataMember]
    public String InnerExceptionMessage { get; set; }

    public static ServiceResponse<T> CreateServiceResponse(Func<T> responseFunc)
    {
        var response = new ServiceResponse<T>();

        try
        {
            response.Data = responseFunc.Invoke();
        }
        catch (Exception ex)
        {
            response = HandleException(responseFunc, ex);
        }

        return response;
    }

    private static ServiceResponse<T> HandleException(Func<T> responseFunc, Exception ex)
    {
        // Handle any exceptions here, and return a ServiceResponse with 
        // Succeeded = false, and the appropriate messages, etc.
    }
}

Пример использования (при условии, что GetClients() вернет IEnumerable):

var response = ServiceResponse<IEnumerable<Client>>
                   .CreateServiceResponse(() => GetClients(clientGroupId));
Другие вопросы по тегам