从WCF项目中返回有意义的异常

时间:2010-03-30 15:31:20

标签: web-services exception-handling wcf

我对WCF很新。我所拥有的一点点经验来自于在ASP.NET Web应用程序中使用相当简单的.SVC服务。

我尝试过第一次尝试使用WCF项目,并遇到了一个重要的节目制作者。

我确信大多数人都知道,出于一些奇怪的原因,在一个将customErrors模式设置为On的Web应用程序中

<customErrors mode = “On” />

服务(.ASMX和.SVC)不会向客户端返回异常详细信息。相反,异常和堆栈跟踪被清空,并且消息始终显示为“处理请求时出错”,这一点都没有用。

当服务直接托管在Web应用程序本身内部时,可以通过将服务放在专用文件夹中,并将customErrors设置为“Off”来轻松解决此限制。

但是,我遇到了同样的问题,例外情况不是从单独的WCF项目中的服务返回。事情是,我不知道如何解决这个问题。

简而言之:我需要让我的WCF项目服务向客户端发送REAL异常 - 或者至少是原始异常消息,而不是“处理请求时出错”。

编辑:我应该在这里指出,我想返回异常的原因是我经常通过Ajax(jQuery)从客户端调用这些服务,并希望如果返回消息是“正常”返回(例如,使用绿色文本),则以不同方式格式化返回消息,如果是错误则使用红色文本。我在$ .ajax对象的错误处理程序中处理消息格式,显然只会在服务失败时运行。

我还应该指出,一切正常,自定义错误关闭:

<customErrors mode = “Off” />

所以,我想也许可以设置一些配置属性来阻止ASP.NET运行时在使用customErrors时杀死我的异常。

Here是我在此发现的一些相关信息。

3 个答案:

答案 0 :(得分:3)

您还有另一种方法可以捕获您想要冒泡到客户端的异常,并返回服务错误。

还有一些设计工作需要继续进行,因为你必须自己设计故障合同,但它可以让你灵活地将任何你想要的东西返回给客户。因此,您可以设计一个详细说明错误的合同,如果您认为有必要,可以进行堆栈跟踪。

示例:

[DataContract(Namespace = "urn:// or http://....")]
public class ClientNeedsToKnowFault
{
    [DataMember]
    public List<Error> Errors
    {
        get { return _errors; }
        set { _errors = value; }
    }

     ....
    public ClientNeedsToKnowFault() { }

    public ClientNeedsToKnowFault(string message)
    {
        Message = message;
        Errors = new List<Error>() { new Error(message) };
    }



    ...
    //Helper method to throw
     public static void ThrowFault(string message, List<Error> errorList)
    {
        throw new FaultException<ClientNeedsToKnowFault>(new ClientNeedsToKnowFault(message, errorList));
    }

设计故障后,您需要为服务方法添加其他属性。

[FaultContract(typeof(ClientNeedsToKnowFault))]
 void MyServiceMethod();

最后一步是扔掉它。正如你在上面看到的那样,我只是放了一个帮助方法来抛出它,因为我觉得FaultException过程有点乱。

我会说这种方法的主要方法是必须在客户端捕获故障。但是,如果信息足够重要,可以返回错误,那么您可能会想要这种复杂性。

答案 1 :(得分:1)

这里真正的答案是你应该总是避免向调用者冒泡实际异常。这里的“ServiceResponse”模式很有用。我们的想法是,您将返回一个“ServiceResponse”类,其中包含您的服务所需的任何响应值,但除了允许您返回Exception对象的属性外,还有一些“IsError”标志。

然后,该服务可以简单地处理所有错误并返回该信息:

public ServiceResponse MyService()
{
  try { 
    // ... do work here
    return new ServiceResponse { WhateverReturnValue = true };
  } catch(Exception e) {
    return new ServiceResponse { IsError = true, Error = e };
  }
}

答案 2 :(得分:1)

您可以查看实施IErrorHandler界面以捕获任何异常并返回合同指定的FaultException