使用包含System.Exception的自定义FaultContract对象会导致“添加服务引用"失败 [英] Using custom FaultContract object containing System.Exception causes 'Add Service Reference' to fail
问题描述
我刚刚发现一些特别的事情.我有一个通过stockHttpBinding发布的内部库存服务,以及一个启用了元数据的customBinding(http + binary).我还为http提供了一个mex端点.我们使用Visual Studio 2008& VB.NET
最近,我们注意到我们无法在其他项目中成功添加对此服务的服务引用.它生成的所有内容都是我们通过FaultContract包含的第一个自定义异常(实际上,只有一种类型).如果我要添加一个简单的网络参考,它也会正常运行.同样,WcfClient.exe在加载服务方面也没有问题.只是VS.NET添加服务引用不起作用.
在服务中,此异常继承自Exception,并标记为可序列化.那就是你应该做的,不是吗?
无论如何,这让我感到困惑.如果我删除此自定义异常的FaultContract,一切正常.我可以添加服务参考,没问题.但是,有什么方法可以让我自定义异常吗?这是一个已知问题吗?
我今天遇到了这个问题.解决方案是在FaultContract中使用不继承自Exception的对象.如果您查看
之前(无效):
[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屋!