0

我正在使用带有WebHttpBinding的 WCF 服务。我已经编写了自定义IDataContractSurrogate实现来将枚举序列化为字符串。

枚举是序列化工作,但反序列化失败。

当请求包含枚举时,我得到:

远程服务器返回意外响应:(400) 错误请求。

或者当响应包含枚举时,我得到:

InvalidCastException: Specified cast is not valid
Server stack trace: 
   at ReadMyResponseFromJson(XmlReaderDelegator , XmlObjectSerializerReadContextComplexJson , XmlDictionaryString , XmlDictionaryString[] )
   at System.Runtime.Serialization.Json.JsonClassDataContract.ReadJsonValueCore(XmlReaderDelegator jsonReader, XmlObjectSerializerReadContextComplexJson context)
   at System.Runtime.Serialization.Json.XmlObjectSerializerReadContextComplexJson.ReadDataContractValue(DataContract dataContract, XmlReaderDelegator reader)
   at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, Type declaredType, DataContract& dataContract)
   at System.Runtime.Serialization.XmlObjectSerializerReadContextComplex.InternalDeserializeWithSurrogate(XmlReaderDelegator xmlReader, Type declaredType, DataContract surrogateDataContract, String name, String ns)
   at System.Runtime.Serialization.XmlObjectSerializerReadContextComplex.InternalDeserialize(XmlReaderDelegator xmlReader, Type declaredType, DataContract dataContract, String name, String ns)
   at System.Runtime.Serialization.Json.DataContractJsonSerializer.InternalReadObject(XmlReaderDelegator xmlReader, Boolean verifyObjectName)
   at System.Runtime.Serialization.XmlObjectSerializer.InternalReadObject(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
   at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
   at System.Runtime.Serialization.Json.DataContractJsonSerializer.ReadObject(XmlDictionaryReader reader, Boolean verifyObjectName)
   at ...

服务器代码:

string baseAddress = "http://localhost:8733/Design_Time_Addresses/FingerprintService/";
_serviceHost = new WebServiceHost(myServiceInstance, new Uri(baseAddress));
_serviceHost.AddServiceEndpoint(typeof (IMyService), new WebHttpBinding(WebHttpSecurityMode.None), baseAddress);
EndpointExtension.Setup(_serviceHost.Description.Endpoints[0]);
_serviceHost.Open();

客户端代码:

IMyService FingerprintService()
{
    var channelFaftory = new WebChannelFactory<IMyService>(new Uri(TbxUri.Text));
    EndpointExtension.Setup(channelFaftory.Endpoint);
    return channelFaftory.CreateChannel();
}

端点设置(主机和客户端通用):

    public static void Setup(ServiceEndpoint endpoint)
    {
        var webHttpBehavior = endpoint.Behaviors.Find<WebHttpBehavior>();
        if (webHttpBehavior == null)
        {
            webHttpBehavior = new WebHttpBehavior();
            endpoint.Behaviors.Add(webHttpBehavior);
        }


        foreach (OperationDescription opertion in endpoint.Contract.Operations)
        {
            var dataContractBehavior = opertion.Behaviors.Find<DataContractSerializerOperationBehavior>();
            dataContractBehavior.DataContractSurrogate = new EnumSurrogate();
        }
    }
}

最后,代理人:

public class EnumSurrogate : IDataContractSurrogate
{
    public Type GetDataContractType(Type type)
    {
        if (type.IsEnum)
        {
            return typeof(string);
        }
        return type;
    }

    public object GetObjectToSerialize(object obj, Type targetType)
    {
        if (obj is Enum)
        {
            return obj.ToString();
        }
        return obj;
    }

    public object GetDeserializedObject(object obj, Type targetType)
    {
        if (obj is string && targetType.IsEnum)
        {
            return Enum.Parse(targetType, (string)obj);
        }
        return obj;
    }

    //other methods throws NotImplementedException
}
4

1 回答 1

2

您的方法在序列化时效果很好,但在反序列化时不起作用。这将失败,因为在反序列化时无法替代原始值。

https://canbilgin.wordpress.com/2012/06/07/how-to-serialize-an-enum-as-string-with-idatacontractsurrogate/

于 2016-10-19T20:48:36.113 回答