在WCF服务返回带有枚举成员且具有无效值(Enum类型中不存在的int)的DataContract的情况下,客户端的抛出异常为The underlying connection was closed: The connection was closed unexpectedly.
奇怪的是,触发了此异常,因为DataContractSerializer无法在连接的服务器端进行序列化。
我宁愿在服务器端运行时向我抛出更有用的东西,更重要的是,但可能是编译器警告......
WCF服务合同
[ServiceContract]
public interface IDtoService
{
[OperationContract]
MyDto GetData(int value);
}
public enum Rating
{
None = 0,
NotSet = 1,
Somevalue = 34
}
[DataContract]
public class MyDto
{
Rating _rate;
[DataMember]
public Rating Rating
{
get { return _rate; }
set
{
_rate = value;
}
}
}
服务实施
public class DtoService : IDtoService
{
public MyDto GetData(int value)
{
var dto = new MyDto { Rating = (Rating) 42 }; // not in ENUM!
return dto;
}
}
客户端
var cl = new DtoServiceClient.DtoServiceClient();
var tada = cl.GetData(1); // connection closed exception
要抛出实际的异常,我必须在调试选项VS2010和“异常”对话框中禁用“仅启用我的代码”,并为“公共语言运行时异常”启用“
”使用该设置,有价值的例外是:
SerializationException
枚举值'42'对于类型无效 'WcfService1.Rating'并且无法序列化。确保 必要的枚举值存在并标有 如果类型具有DataContractAttribute,则为EnumMemberAttribute属性 属性
这是因为调试器对所有其他类型的抛出异常非常嘈杂,AFAIK可以被忽略。
我可以尝试在没有噪音的情况下抛出此异常吗?
我可以调整或添加WCF管道吗?
在返工成本的早期失败的一个可能的解决方案是在枚举成员的setter中添加额外的Assert:
Debug.Assert(Enum.IsDefined(typeof(Rating), value),"value is not valid for this enum");
我尝试的另一种方法是添加合同,希望可以产生警告。我找不到比基本上是Debug.Assert的副本更好的东西。
System.Diagnostics.Contracts.Contract.Assert(Enum.IsDefined(typeof(Rating), value));
是否有选项让编译器为我发出此检查,或者是否有其他我不知道的选项?
(我也尝试在启用check for arithmetic overflow/underflow
的情况下进行编译而不期望它成功)
CodeContracts会发出警告,(你必须使用Implicit Enum写入义务)虽然这并没有真正帮助
实际值可能不在此枚举值
定义的范围内
此行为位于VS2010 / .Net 4.0上下文中。
答案 0 :(得分:3)
你可以做一些事情。
在WCF方面,使用IncludeExceptionDetailInFaults
(使用ServiceBehavior属性或app.config)。这将使WCF向客户端发送详细的例外。请注意,这被视为“不安全”设置,因为它将服务器堆栈跟踪暴露给客户端,因此您只应在开发期间使用它。对于生产,您应该使用WCF错误处理程序来记录所有服务错误(或打开WCF跟踪)。
如果您想在编译时期间使用代码约定来捕获此错误,您可以使用对象不变量:
public class MyDto
{
public Rating Rating { get; set; }
[ContractInvariantMethod]
void Invariant()
{
Contract.Invariant(Enum.IsDefined(typeof(Rating), Rating));
}
}
如果启用静态分析,您将收到此行的警告:
new MyDto { Rating = (Rating) 42 };