通过Web服务正确捕获特定异常

时间:2021-09-03 21:53:51

I am currently using a C# .NET Service in our client program. As part of the server design, several custom made exceptions are thrown to indicate specific errors (as in any normal desktop program).

我目前在客户端程序中使用C#.NET服务。作为服务器设计的一部分,抛出了几个自定义异常以指示特定错误(如在任何普通桌面程序中)。

The problem is that the Web Service catches these errors and serializes them into a FaultException, with the actual exception (like NoRoomsAvailableException) written in the Message field.

问题是Web Service捕获这些错误并将它们序列化为FaultException,并在Message字段中写入实际异常(如NoRoomsAvailableException)。

My question is whether there is a best practice for handling these errors. We have just begun working on this, and we would probably do some text pattern matching to pull out the exception type and error message, but it seems like a hacky way to do it, so any "clean" way of doing it would be much appreciated.

我的问题是,是否有处理这些错误的最佳做法。我们刚刚开始研究这个问题,我们可能会做一些文本模式匹配来提取异常类型和错误消息,但这似乎是一种hacky方式,所以任何“干净”的做法都会很多赞赏。

2 个解决方案

#1


The proper way would be to define fault contracts. For example in your web service you could do the following:

正确的方法是定义故障合同。例如,在您的Web服务中,您可以执行以下操作:

[DataContract]
public class NoRoomsAvailableFaultContract
{
    [DataMember]
    public string Message { get; set; }
}

Next you declare this contract for a given service operation

接下来,您为给定的服务操作声明此合同

[ServiceContract]
public interface IMyServiceContract
{
    [OperationContract]
    [FaultContract(typeof(NoRoomsAvailableFaultContract))]
    void MyOperation();
}

And you implement it like so:

你这样实现它:

public class MyService : IMyServiceContract 
{
    public void MyOperation()
    {
        if (somethingWentWrong)
        {
            var faultContract = new NoRoomsAvailableFaultContract()
            {
                Message = "ERROR MESSAGE"
            };
            throw new FaultException<NoRoomsAvailableFaultContract>(faultContract);
        }
    }
}

In this case the NoRoomsAvailableFaultContract will be exposed in the WSDL and svcutil.exe could generate a proxy class. Then you could catch this exception:

在这种情况下,NoRoomsAvailableFaultContract将在WSDL中公开,svcutil.exe可以生成代理类。然后你可以捕获这个异常:

try
{
    myServiceProxy.MyOperation();
}
catch (FaultException<NoRoomsAvailableFaultContract> ex)
{
    Console.WriteLine(ex.Message);
}

#2


darin has the correct answer. I'll only say explicitly what he implies: web services do not pass exceptions. They return SOAP Faults. If you define your faults properly, as he does, then you get to throw FaultException<fault>. This will become a SOAP Fault with fault in the detail element. In the case of a .NET client, this will then be turned into a FaultException<fault>, which you can catch.

达林有正确的答案。我只会明确说明他的含义:Web服务不会传递异常。它们返回SOAP Faults。如果你正确地定义了你的错误,那么就可以抛出FaultException 。这将成为详细信息元素中出现故障的SOAP Fault。对于.NET客户端,这将转换为FaultException ,您可以捕获它。

Other platforms may handle this somewhat differently. I've seen IBM's Rational Web Developer generate Java proxy code that creates a separate exception for each declared fault. That was a version before Java generics, so maybe by now it does the same thing as .NET does.

其他平台可能会有所不同。我见过IBM的Rational Web Developer生成Java代理代码,为每个声明的错误创建一个单独的异常。这是Java泛型之前的一个版本,所以也许到现在它和.NET一样。

#1


The proper way would be to define fault contracts. For example in your web service you could do the following:

正确的方法是定义故障合同。例如,在您的Web服务中,您可以执行以下操作:

[DataContract]
public class NoRoomsAvailableFaultContract
{
    [DataMember]
    public string Message { get; set; }
}

Next you declare this contract for a given service operation

接下来,您为给定的服务操作声明此合同

[ServiceContract]
public interface IMyServiceContract
{
    [OperationContract]
    [FaultContract(typeof(NoRoomsAvailableFaultContract))]
    void MyOperation();
}

And you implement it like so:

你这样实现它:

public class MyService : IMyServiceContract 
{
    public void MyOperation()
    {
        if (somethingWentWrong)
        {
            var faultContract = new NoRoomsAvailableFaultContract()
            {
                Message = "ERROR MESSAGE"
            };
            throw new FaultException<NoRoomsAvailableFaultContract>(faultContract);
        }
    }
}

In this case the NoRoomsAvailableFaultContract will be exposed in the WSDL and svcutil.exe could generate a proxy class. Then you could catch this exception:

在这种情况下,NoRoomsAvailableFaultContract将在WSDL中公开,svcutil.exe可以生成代理类。然后你可以捕获这个异常:

try
{
    myServiceProxy.MyOperation();
}
catch (FaultException<NoRoomsAvailableFaultContract> ex)
{
    Console.WriteLine(ex.Message);
}

#2


darin has the correct answer. I'll only say explicitly what he implies: web services do not pass exceptions. They return SOAP Faults. If you define your faults properly, as he does, then you get to throw FaultException<fault>. This will become a SOAP Fault with fault in the detail element. In the case of a .NET client, this will then be turned into a FaultException<fault>, which you can catch.

达林有正确的答案。我只会明确说明他的含义:Web服务不会传递异常。它们返回SOAP Faults。如果你正确地定义了你的错误,那么就可以抛出FaultException 。这将成为详细信息元素中出现故障的SOAP Fault。对于.NET客户端,这将转换为FaultException ,您可以捕获它。

Other platforms may handle this somewhat differently. I've seen IBM's Rational Web Developer generate Java proxy code that creates a separate exception for each declared fault. That was a version before Java generics, so maybe by now it does the same thing as .NET does.

其他平台可能会有所不同。我见过IBM的Rational Web Developer生成Java代理代码,为每个声明的错误创建一个单独的异常。这是Java泛型之前的一个版本,所以也许到现在它和.NET一样。