我们有一个公开“客户”类型的WCF服务,即:
[DataContract(Name = "CustomerData", Namespace = "http://www.testing.com")] public partial class Customer { [DataMember] public CustomerLevel Level { get; set; } }
您可以看到上面的类型具有枚举类型的属性。这个枚举的定义是:
[IgnoreCoverage] [DataContract(Namespace = "http://www.testing.com"")] public enum CustomerLevel : int { [EnumMember(Value = "Platinum")] Platinum = 1, [EnumMember(Value = "Gold")] Gold = 2, [EnumMember(Value = "Silver")] Silver = 3, [EnumMember(Value = "Bronze")] Bronze = 4, }
只要服务器为其返回的每个客户发送有效枚举,服务就可以正常工作。但是,如果服务返回未在枚举中定义的CustomerLevel,则服务调用超时。
错误的CustomerLevel值的示例可能是:
customer.Level = (CustomerLevel)0;
如果客户端尝试发送未定义的值,服务也会超时。
有没有办法允许非定义的值流到客户端和服务器,并让每个值自己处理坏值?
答案 0 :(得分:3)
我认为你不会得到虚假的工作。他们将反序列化为什么?如果你的意思是客户端发送整数,那么将类型更改为int,并将其自己转换为枚举(使用自己的错误处理)。
关于客户是否应该超时,请告诉我们您使用的是哪种客户。此外,我建议您查看网络流量,看看服务如何响应,如果有的话。还要查看Windows事件日志以查看服务是否完全被抱怨。最后,您可能希望打开WCF跟踪以查看服务如何对此做出反应。
答案 1 :(得分:2)
您可以使用自定义IDataContractSurrogate将枚举映射到int然后再返回枚举。
创建此类代理的文档位于:http://msdn.microsoft.com/en-us/library/ms733064.aspx
这是我开发的可以处理枚举类型列表的通用版本。您可以在DataContractSerializer的构造函数中指定它。有关详细信息,请参阅我的博客文章:http://www.shulerent.com/2012/08/13/handling-invalid-enum-values-in-a-datacontractserializer/
/// <summary>
/// IDataContractSurrogate to map Enum to int for handling invalid values
/// </summary>
public class InvalidEnumContractSurrogate : IDataContractSurrogate
{
private HashSet<Type> typelist;
/// <summary>
/// Create new Data Contract Surrogate to handle the specified Enum type
/// </summary>
/// <param name="type">Enum Type</param>
public InvalidEnumContractSurrogate(Type type)
{
typelist = new HashSet<Type>();
if (!type.IsEnum) throw new ArgumentException(type.Name + " is not an enum","type");
typelist.Add(type);
}
/// <summary>
/// Create new Data Contract Surrogate to handle the specified Enum types
/// </summary>
/// <param name="types">IEnumerable of Enum Types</param>
public InvalidEnumContractSurrogate(IEnumerable<Type> types)
{
typelist = new HashSet<Type>();
foreach (var type in types)
{
if (!type.IsEnum) throw new ArgumentException(type.Name + " is not an enum", "type");
typelist.Add(type);
}
}
#region Interface Implementation
public Type GetDataContractType(Type type)
{
//If the provided type is in the list, tell the serializer it is an int
if (typelist.Contains(type)) return typeof(int);
return type;
}
public object GetObjectToSerialize(object obj, Type targetType)
{
//If the type of the object being serialized is in the list, case it to an int
if (typelist.Contains(obj.GetType())) return (int)obj;
return obj;
}
public object GetDeserializedObject(object obj, Type targetType)
{
//If the target type is in the list, convert the value (we are assuming it to be int) to the enum
if (typelist.Contains(targetType)) return Enum.ToObject(targetType, obj);
return obj;
}
public void GetKnownCustomDataTypes(System.Collections.ObjectModel.Collection<Type> customDataTypes)
{
//not used
return;
}
public object GetCustomDataToExport(Type clrType, Type dataContractType)
{
//Not used
return null;
}
public object GetCustomDataToExport(System.Reflection.MemberInfo memberInfo, Type dataContractType)
{
//not used
return null;
}
public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData)
{
//not used
return null;
}
public System.CodeDom.CodeTypeDeclaration ProcessImportedType(System.CodeDom.CodeTypeDeclaration typeDeclaration, System.CodeDom.CodeCompileUnit compileUnit)
{
//not used
return typeDeclaration;
}
#endregion
}
答案 2 :(得分:2)
对我来说问题的答案至少是设置IsRequired = false。像这样:
[DataMember(IsRequired = false)]
Nullable<MyEnum> Prop {get;set;}
这增加了nillble =&#34; true&#34;正确地对待wsdl ...
答案 3 :(得分:1)
我认为没有办法使用DataContract公开未定义的枚举。
对于传播异常,您可以尝试启用“IncludeExceptionDetailsInFaults” - 有关详细信息,请参阅MSDN documentation。
我通常做的是实现一个IErrorHandler服务器端,它记录异常并提升故障的异常 - IDesign's web site上有一些好东西。
答案 4 :(得分:0)
尝试从枚举值中删除EnumMember
属性。 德尔>
此外,您无需将枚举标记为DataContract
,因为DataContractSerializer
会自动序列化您在现有DataContracts
中使用的任何枚举。
我上面发布的内容不起作用。我认为不可能使用DataContractSerializer
来序列化无效的枚举值。