使用包含System.Exception的自定义FaultContract对象会导致“添加服务引用"失败 [英] Using custom FaultContract object containing System.Exception causes 'Add Service Reference' to fail

查看:111
本文介绍了使用包含System.Exception的自定义FaultContract对象会导致“添加服务引用"失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚发现一些特别的事情.我有一个通过stockHttpBinding发布的内部库存服务,以及一个启用了元数据的customBinding(http + binary).我还为http提供了一个mex端点.我们使用Visual Studio 2008& VB.NET

最近,我们注意到我们无法在其他项目中成功添加对此服务的服务引用.它生成的所有内容都是我们通过FaultContract包含的第一个自定义异常(实际上,只有一种类型).如果我要添加一个简单的网络参考,它也会正常运行.同样,WcfClient.exe在加载服务方面也没有问题.只是VS.NET添加服务引用不起作用.

在服务中,此异常继承自Exception,并标记为可序列化.那就是你应该做的,不是吗?

无论如何,这让我感到困惑.如果我删除此自定义异常的FaultContract,一切正常.我可以添加服务参考,没问题.但是,有什么方法可以让我自定义异常吗?这是一个已知问题吗?

解决方案

我今天遇到了这个问题.解决方案是在FaultContract中使用不继承自Exception的对象.如果您查看 FaultException 和 FaultContract 您将看到官方示例使用普通类(具有DataContact属性),而不是为FaultException.Detail扩展Exception的类.我不确定Exception为什么导致Add Service Reference失败,但是我怀疑它与序列化或检索自定义异常的类型信息有关.我在示例实现之前和之后都包含了此示例,以演示该工作方法.

之前(无效):

[ServiceContract]
public interface IMyService
{
    [OperationContract]
    [FaultContract(typeof(MyException))]
    MyResults MyServiceOperation(string myParameter);
}

[Serializable]
public class MyException : Exception
{
    public string CustomData { get; set; }
}

[ErrorHandlerBehavior(typeof(MyErrorHandler))]
public class MyService : IMyService
{
    public MyResults MyServiceOperation(string myParameter)
    {
        ...
        throw new MyModelException { CustomData = "42" };
        ...
    }
}

public class MyErrorHandler : IErrorHandler
{
    public bool HandleError(Exception error) { return false; }

    public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
    {
        try { throw error; }
        catch (MyModelException ex)
        {
            var faultEx = new FaultException<MyException>(new MyException { CustomData = ex.CustomData });
            fault = Message.CreateMessage(version, faultEx.CreateMessageFault(), faultEx.Action);
        }
        catch { /* Supress all others */ }
    }
}

(工作后):

[ServiceContract]
public interface IMyService
{
    [OperationContract]
    [FaultContract(typeof(MyFault))]
    MyResults MyServiceOperation(string myParameter);
}

[DataContract]
public class MyFault
{
    [DataMember]
    public string CustomData { get; set; }
}

[ErrorHandlerBehavior(typeof(MyErrorHandler))]
public class MyService : IMyService
{
    public MyResults MyServiceOperation(string myParameter)
    {
        ...
        throw new MyModelException { CustomData = "42" };
        ...
    }
}

public class MyErrorHandler : IErrorHandler
{
    public bool HandleError(Exception error) { return false; }

    public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
    {
        try { throw error; }
        catch (MyModelException ex)
        {
            var faultEx = new FaultException<MyFault>(new MyFault { CustomData = ex.CustomData });
            fault = Message.CreateMessage(version, faultEx.CreateMessageFault(), faultEx.Action);
        }
        catch { /* Supress all others */ }
    }
}

资料来源: Max Strini ,以介绍他的代码并帮助找到解决该问题的方法. /p>

I just noticed something particular. I have an internal stock service which is published through basicHttpBinding, and a customBinding (http+binary) for which metadata is enabled. I also included a mex endpoint for http. We use Visual Studio 2008 & VB.NET

Just recently we noticed that we were unable to succesfully add a service reference to this service in our other projects. All that it would generate was the first custom exception we included through a FaultContract (actually, there was only 1 type). if I'd add a simple web reference it would work correctly as well. Also, the WcfClient.exe had no problems either in loading the services. Just VS.NET add service reference wouldn't work.

In the service this exception inherits from Exception and is marked as serializable. That's all you're supposed to do, no?

Anyway, this had me baffled. If I remove the FaultContract for this custom exception everything works fine. I can add a service reference, no problem. But is there a way I can still have my custom exceptions? Is this a known problem?

解决方案

I ran into this myself today. The solution was to use an object not inheriting from Exception in the FaultContract. If you look at the MSDN docs for FaultException and FaultContract you will see that the official examples use plain classes (with DataContact attributes) rather than classes extending Exception for FaultException.Detail. I'm not sure why Exception causes the Add Service Reference to fail, but I suspect it has to do with the serializing or retrieving the type information for custom exceptions. I have included before and after example implementations to demonstrate the working approach.

Before (didn't work):

[ServiceContract]
public interface IMyService
{
    [OperationContract]
    [FaultContract(typeof(MyException))]
    MyResults MyServiceOperation(string myParameter);
}

[Serializable]
public class MyException : Exception
{
    public string CustomData { get; set; }
}

[ErrorHandlerBehavior(typeof(MyErrorHandler))]
public class MyService : IMyService
{
    public MyResults MyServiceOperation(string myParameter)
    {
        ...
        throw new MyModelException { CustomData = "42" };
        ...
    }
}

public class MyErrorHandler : IErrorHandler
{
    public bool HandleError(Exception error) { return false; }

    public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
    {
        try { throw error; }
        catch (MyModelException ex)
        {
            var faultEx = new FaultException<MyException>(new MyException { CustomData = ex.CustomData });
            fault = Message.CreateMessage(version, faultEx.CreateMessageFault(), faultEx.Action);
        }
        catch { /* Supress all others */ }
    }
}

After (worked):

[ServiceContract]
public interface IMyService
{
    [OperationContract]
    [FaultContract(typeof(MyFault))]
    MyResults MyServiceOperation(string myParameter);
}

[DataContract]
public class MyFault
{
    [DataMember]
    public string CustomData { get; set; }
}

[ErrorHandlerBehavior(typeof(MyErrorHandler))]
public class MyService : IMyService
{
    public MyResults MyServiceOperation(string myParameter)
    {
        ...
        throw new MyModelException { CustomData = "42" };
        ...
    }
}

public class MyErrorHandler : IErrorHandler
{
    public bool HandleError(Exception error) { return false; }

    public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
    {
        try { throw error; }
        catch (MyModelException ex)
        {
            var faultEx = new FaultException<MyFault>(new MyFault { CustomData = ex.CustomData });
            fault = Message.CreateMessage(version, faultEx.CreateMessageFault(), faultEx.Action);
        }
        catch { /* Supress all others */ }
    }
}

Source: Max Strini for the use of his code and help in finding the solution to this issue.

这篇关于使用包含System.Exception的自定义FaultContract对象会导致“添加服务引用"失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆