Wcf服务异常良好做法

mar*_*raz 31 .net c# wcf web-services

我正在开发分布式应用程序.在其中,我必须验证角色和权限集.在例如未经授权的访问中
抛出异常是一个很好的实践吗? 或者我应该向客户发送一些消息?

小智 55

在您的服务操作中,您可以指定一个FaultContract,它将同时满足这两个目的:

[OperationContract]
[FaultContract(typeof(MyServiceFault))]
void MyServiceOperation();
Run Code Online (Sandbox Code Playgroud)

请注意,MyServiceFault必须使用与复杂类型相同的方式标记DataContract和DataMember属性:

[DataContract]
public class MyServiceFault
{
    private string _message;

    public MyServiceFault(string message)
    {
        _message = message;
    }

    [DataMember]
    public string Message { get { return _message; } set { _message = value; } }
}
Run Code Online (Sandbox Code Playgroud)

在服务方面,您可以:

throw new FaultException<MyServiceFault>(new MyServiceFault("Unauthorized Access"));
Run Code Online (Sandbox Code Playgroud)

在客户端:

try
{
    ...
}
catch (FaultException<MyServiceFault> fault)
{
    // fault.Detail.Message contains "Unauthorized Access"
}
Run Code Online (Sandbox Code Playgroud)

  • 对于OP:你不想"抛出异常".你想"回归故障".这就是这个答案告诉你如何做的. (7认同)

Dan*_*son 12

好吧,您可以捕获WCF服务实现方法中的所有异常,并将它们重新抛出为FaultExceptions.通过这种方式,将在客户端上重新抛出异常,并显示您选择的消息:

[OperationContract]
public List<Customer> GetAllCustomers()
{
    try
    {
        ... code to retrieve customers from datastore
    }
    catch (Exception ex)
    {
        // Log the exception including stacktrace
        _log.Error(ex.ToString());

        // No stacktrace to client, just message...
        throw new FaultException(ex.Message);
    }
}
Run Code Online (Sandbox Code Playgroud)

为了避免将意外错误转发回客户端,从不在服务器端的代码中抛出异常实例也是一种好习惯.而是创建一个或多个自己的异常类型并抛出它们.通过这样做,您可以区分意外的服务器处理错误和由于无效请求而引发的错误等:

public List<Customer> GetAllCustomers()
{
    try
    {
        ... code to retrieve customers from datastore
    }
    catch (MyBaseException ex)
    {
         // This is an error thrown in code, don't bother logging it but relay
         // the message to the client.
         throw new FaultException(ex.Message);
    }
    catch (Exception ex)
    {
        // This is an unexpected error, we need log details for debugging
        _log.Error(ex.ToString());

        // and we don't want to reveal any details to the client
        throw new FaultException("Server processing error!");
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 有人可以评论为什么这个答案没有被更多地投票,为什么接受的答案在某种程度上更好?它更复杂,实现了同样的目的吗? (2认同)
  • @Esko:据我所知,这些答案使用了相同的功能:SOAP-Fault通过抛出FaultException.唯一的区别是,这个答案只会抛出一个基本的FaultExeption,而接受的答案显示如何自定义FaultExeption.通过自定义,您可以在客户端处理更具体的不同类型的服务器端异常,并传递更多信息.您可以将抛出FaultExeption与抛出FaultException <MyServiceFault>与抛出异常与抛出非WCF上下文中的MyCustomException进行比较. (2认同)