欢迎来到.net学习网

欢迎联系站长一起更新本网站!QQ:879621940

您当前所在位置:首页 » ASP.Net » 正文

热门阅读

WCF中如何正确的获捕服务端抛出的错误

创建时间:2013年09月25日 09:16  阅读次数:(6845)
分享到:
在WCF中,在服务器抛出的任何异常,如果未做特别处理,在客户端都只能被FaultException捕获,比如如下示例:

声明契约
[ServiceContract]
public interface IMyContract
{
    [OperationContract]
    double Division(double x, double y);
}

实现服务
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class MyContract : IMyContract
{
    public double Division(double x, double y)
    {
        throw new DivideByZeroException("除数不能为零啦!");
    }
}

寄宿服务
class Program
{
    static void Main(string[] args)
    {
        ServiceHost host = new ServiceHost(typeof(MyContract));
        host.AddServiceEndpoint(typeof(IMyContract), new WSHttpBinding(), "http://localhost:8010");
        host.Opened += delegate { Console.WriteLine("服务已经开启!"); };
        host.Open();

        Console.ReadLine();
    }
}

客户端
static void Main(string[] args)
{
    ChannelFactory<Host.IMyContract > channel = new ChannelFactory<Host.IMyContract >();
    channel.Endpoint.Binding = new WSHttpBinding();
    channel.Endpoint.Address = new EndpointAddress("http://localhost:8010");
    Host.IMyContract client = channel.CreateChannel();
    try
    {
        client.Division(1, 2);
    }
    catch (DivideByZeroException ex)
    {
        Console.WriteLine("我是DivideByZeroException错误!我的错误信息是:{0}", ex.Message);
    }
    catch (FaultException ex)
    {
        Console.WriteLine("我是FaultException错误!");
    }

    Console.ReadLine();
}

运行效果如下:

图1

从运行效果上我们可以发现,虽然我们在服务端抛出了DivideByZeroException异常,但在端客户却不能被DivideByZeroException捕捉,而是被FaultException捕捉了,这是因为在WCF中,如果直接抛出异常而不定义错误契约的话,客户端是不会知道错误的具体类型的,为了使客户端与服务器解耦,所有直接抛出的错误都以FaultException到达客户端。

那么要怎么才能让客户端明确的知道服务端抛出的异常呢?这就需要用到错误契约了,也就是在定义契约的时候,我们就需要定义在实现该契约的方法中会抛出什么样的异常。定义错误契约很简单,只需要在方法的上面加上FaultContract属性即可,如下代码:
[ServiceContract]
public interface IMyContract
{
    [OperationContract] 
    [FaultContract(typeof(DivideByZeroException))]
    double Division(double x, double y);
}
我们可以为一个方法定义多个错误 ,但如果有定义了错误,就必须在后面的实现中抛出这样的错误。注意,定了IsOneWay=true的方法是不能够定义错误契约的,如果一个方法同时定义了IsOneWay=true与错误契约,就会在运行时提示InvalidOperateionException异常。因为很简单,IsOneWay=true就定义了该方法为单向操作,不需要等待服务端的响应,然后却又定义返回的错误类型,这本就是矛盾的。

然后在服务的Division方法中抛出DivideByZeroException异常,如下:
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class MyContract : IMyContract
{
    public double Division(double x, double y)
    {
        throw new FaultException<DivideByZeroException >(new DivideByZeroException("除数不能为零啦!"));
    }
}

注意,上面我们不是直接抛出DivideByZeroException异常了,而是使用了FaultException<T >。
客户端也稍作修改如下:
……
try
{
    client.Division(1, 2);
}
catch (FaultException<DivideByZeroException > ex)
{
    Console.WriteLine("我是DivideByZeroException错误!我的错误信息是:{0}", ex.Detail.Message);
}
catch (FaultException ex)
{
    Console.WriteLine("我是FaultException错误!");
}
……

运行,效果如下:

图2

从上图的效果可以看到,客户端有正确的捕获到服务端抛出的错误了。
来源:.net学习网
说明:所有来源为 .net学习网的文章均为原创,如有转载,请在转载处标注本页地址,谢谢!
【编辑:Wyf

打赏

取消

感谢您的支持,我会做的更好!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

最新评论

共有评论0条
  • 暂无任何评论,请留下您对本文章的看法,共同参入讨论!
发表评论:
留言人:
内  容:
请输入问题 72+29=? 的结果(结果是:101)
结  果: