在 WCF 服务返回具有无效值(枚举类型中不存在 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;
}
}
Client
var cl = new DtoServiceClient.DtoServiceClient();
var tada = cl.GetData(1); // connection closed exception
为了抛出实际的异常,我必须在 VS2010 的调试选项中禁用“仅启用我的代码”,并在“异常”对话框中启用“公共语言运行时异常”的抛出
通过该设置,有价值的例外是:
序列化异常
枚举值“42”对于类型无效
'WcfService1.Rating' 并且无法序列化。确保
存在必要的枚举值并标记为
如果类型具有 DataContractAttribute,则为 EnumMemberAttribute 属性
属性
这是以调试器对所有其他类型的抛出异常(据我所知可以忽略)变得非常嘈杂为代价的。
我可以尝试如何在没有噪音的情况下抛出此异常?
我可以在 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
启用但不期望它成功)
代码合约确实发出警告(您必须启用隐式枚举写入义务),但这并没有真正帮助
实际值可能不在为此枚举值定义的范围内
此行为发生在 VS2010/.Net 4.0 上下文中。