WCF не может десериализоваться при использовании IDataContractSurrogate
Я использую сервис WCF с WebHttpBinding. Я написал собственную реализацию IDataContractSurrogate для сериализации enum в виде строк.
Перечисления являются сериализационными работами, но десериализация не выполняется.
когда запрос содержит enum, тогда я получаю:
Удаленный сервер возвратил неожиданный ответ: (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
}
1 ответ
Ваш подход хорошо работает при сериализации, но не будет работать при десериализации. Это не удастся, потому что примитивные значения не могут быть заменены при десериализации.