有异常发生时,有没有办法在WCF中处理HTTP响应?

时间:2012-11-29 04:43:38

标签: .net wcf web-services

我有一个看起来像这样的网络服务:

[ServiceContract]
public class MyService
{
   [OperationContract]
   public void BreakStuff()
   {
      throw new MyException();
   }
}

现在它不是一个非常强大的网络服务,但你看 - 它会很棒!

如果我调用BreakStuff(),WCF会捕获异常,返回HTTP 500并可选择在IncludeExceptionDetailsInFaults设置为true时吐出序列化堆栈跟踪。我想重写此行为并吐出我自己的自定义错误消息对象,并返回HTTP 200.我想这样做是因为我认为在某些情况下抛出异常是 cleaner 而不是乱丢代码 try / catch 块并让所有Web方法返回某种 Result 对象。

我所做的是实现我自己的IDispatchMessageFormatter,其中包含合同:

public interface IDispatchMessageFormatter
{
   void DeserializeRequest(Message message, object[] parameters);
   Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result);
}

SerializeReply被调用正常的HTTP 200响应,但是如果web方法抛出异常,WCF从不调用SerializeReply,所以我没有机会控制响应输出。

WCF是否提供自定义错误响应的功能?

1 个答案:

答案 0 :(得分:2)

您可以通过实现IErrorHandler接口来实现自定义错误处理程序。我过去使用过这种方法来返回JSON格式的自定义错误信息。在ProvideFault方法中,您还可以更改响应代码。以下是我使用过的一种方法的示例。

public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{   
    fault = GetJsonResponseFromException(version, error);
    ConfigureMessageFormat(ref fault);
    ConfigureHttpReponse(ref fault, error);
}

protected virtual void ConfigureMessageFormat(ref Message fault)
{
    var formatting =
      new WebBodyFormatMessageProperty(WebContentFormat.Json);
    fault.Properties.Add(WebBodyFormatMessageProperty.Name, formatting);
}

protected virtual void ConfigureHttpReponse(ref Message fault, Exception error)
{
    var exception = error as WebFaultException<ServiceFault>;
    var statusCode = HttpStatusCode.InternalServerError;
    var description = HttpWorkerRequest
        .GetStatusDescription(Convert.ToInt32(statusCode));

    if (exception != null)
    {
        statusCode = exception.StatusCode;
        description = exception.Reason.Translations[0].Text;
    }

    var httpResponse = new HttpResponseMessageProperty()
    {
        StatusCode = statusCode,
        StatusDescription = description
    };

    httpResponse.Headers[HttpResponseHeader.ContentType] = "application/json";
    fault.Properties.Add(HttpResponseMessageProperty.Name, httpResponse);
}