使用包含 System.Exception 的自定义 FaultContract 对象会导致“添加服务引用”失败

发布于 2024-10-11 20:26:58 字数 454 浏览 2 评论 0原文

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

最近我们注意到我们无法在其他项目中成功添加对此服务的服务引用。它生成的只是我们通过故障契约包含的第一个自定义异常(实际上,只有一种类型)。如果我添加一个简单的网络参考,它也能正常工作。此外,WcfClient.exe 在加载服务时也没有问题。仅仅 VS.NET 添加服务引用是行不通的。

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

无论如何,这让我很困惑。如果我删除此自定义异常的FaultContract,一切都会正常。我可以添加服务参考,没问题。但有什么方法我仍然可以拥有自定义例外吗?这是一个已知问题吗?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

乖不如嘢 2024-10-18 20:26:58

我今天自己也遇到了这个问题。解决方案是在FaultContract 中使用不继承自Exception 的对象。如果您查看 MSDN 文档中的 FaultExceptionFaultContract 您将看到官方示例使用普通类(具有 DataContact 属性),而不是扩展 Exception for FaultException.Detail 的类。我不确定为什么异常会导致添加服务引用失败,但我怀疑它与序列化或检索自定义异常的类型信息有关。我提供了实施前后的示例来演示工作方法。

之前(不起作用):

[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 感谢使用他的代码并帮助找到此问题的解决方案。

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.

若无相欠,怎会相见 2024-10-18 20:26:58

我找到了以下关于如何使用从 System.Exception 继承的对象创建故障契约的文章: http://blog.clauskonrad.net/2008/06/wcf-and-custom-exceptions.html

但是,它对我不起作用。我怀疑它对我不起作用的原因是我使用的是 BasicHttp 绑定而不是 .NET-.NET 绑定。

I found the following article on how to create a fault contract using objected inherited from System.Exception: http://blog.clauskonrad.net/2008/06/wcf-and-custom-exceptions.html

However, it didn't work for me. I suspect the reason it didn't work for me is that I'm using a BasicHttp binding and not a .NET-.NET binding.

少钕鈤記 2024-10-18 20:26:58

我也遇到过这个问题。我最终使用 svcutil.exe 生成代理,但它似乎没有遇到同样的问题。

I've also hit this issue. I ended up using the svcutil.exe to generate the proxy which doesn't appear to suffer the same issue.

养猫人 2024-10-18 20:26:58

我遇到了同样的问题,并通过使用 SVCUTIL.exe 生成代理来解决它。我完全按照 MSDN 推荐的方式进行了自定义故障设置,但“添加服务引用”并未在代理中包含故障契约。然后我使用了 SVCUTIL,它就像魔术一样工作:)

I had the same problem and solved it by generating the proxy using SVCUTIL.exe. I had the custom fault setup exactly the way MSDN recommends but "add service reference" was not including the fault contract in the proxy. Then I used the SVCUTIL and it worked like magic :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文