私はWCFが初めてで、誰かが助けてくれることを望んでいました。[knowntype]
派生クラスが適用された非抽象基本クラスがあり、これは配列内のサービスへの要求の本文で使用されます。派生クラスを含む XML を使用してサービスを呼び出すと、逆シリアル化後にコードで得られるのは、派生クラスではなく基本クラスだけです。
入力 XML には、完全に無視されているように見える xml インスタンス タイプ ( xsi:type
) 属性があります。どのように設定しても、システムはエラーなしで基本クラスを提供します。
私がこれを取得している実際のコード/etcは巨大です。そこで、代表的なテストをノックアップしましたが、これは適切に機能し、興味深いことに、 をxsi:type
無効な型に変更すると、動作さDataContractSerializer
せたいコードとは異なり、から例外が発生します。
例外を強制するために要素の名前を変更すると、次の言及が表示されますDataContractSerializer
。
`Start element 'itemz' does not match end element 'item'. Line 110, position 23.
at System.Xml.XmlExceptionHelper.ThrowXmlException(XmlDictionaryReader reader, String res, String arg1, String arg2, String arg3)
at System.Xml.XmlUTF8TextReader.ReadEndElement()
at System.Xml.XmlUTF8TextReader.Read()
at System.Xml.XmlBaseReader.Skip()
at System.Runtime.Serialization.XmlReaderDelegator.Skip()
at ReadArrayOfitemFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString , XmlDictionaryString , CollectionDataContract )
at System.Runtime.Serialization.CollectionDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDe legator reader, String name, String ns, Type declaredType, DataContract& dataContract)
at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDe legator xmlReader, Int32 id, RuntimeTypeHandle declaredTypeHandle, String name, String ns)
at ReadinteropSectionFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString[] , XmlDictionaryString[] )
...
at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator xmlReader, Type declaredType, DataContract dataContract, String name, String ns)
at System.Runtime.Serialization.DataContractSerializer.InternalReadObject(XmlReaderDelegator xmlReader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)`
例外から判断すると、どちらの場合も DataContractSerializer を使用しているように見えますが、実際のコードでは、派生型を使用しようとさえしていません。以前の ASMX スタイルのサービスとは異なり、シリアライザーのコードに飛び込んで、それが一体何をしているのかを確認する方法をまだ見つけていません。シリアライザーをデバッグするにはどうすればよいですか?
少しでもお役に立てれば、より多くのコード/xml を提供できるように努めます。私が持っている「デモ」コードは以下のとおりです。実際のコードと同じように[MessageContract]
、サービスに を使用しますが、エンティティはすべて徹底的に DataContract されています (実際のコードでは、SVCUTIL が同様の属性を持つプロキシ コードを生成しました)。
[DataContract] public class Security
{
[DataMember] public string Username { get; set; }
}
[DataContract] public class Wrapper
{
[DataMember] public BaseEntity[] MyEntities { get; set; }
}
[DataContract, KnownType(typeof(AdvancedEntity))] public class BaseEntity
{
[DataMember] public string Name { get; set; }
}
[DataContract] public class AdvancedEntity : BaseEntity
{
[DataMember] public int Age { get; set; }
}
[ServiceContract] interface ITrivialService
{
[OperationContract] Response DoStuff(Request request);
}
[MessageContract] public class Request
{
[MessageHeader] public Security AuthenticationDetails { get; set; }
[MessageBodyMember] public Wrapper MyWrapper { get; set; }
}
[MessageContract] public class Response
{
[MessageBodyMember] public BaseEntity Entity { get; set; }
}
public class TrivialService : ITrivialService
{
public Response DoStuff(Request request)
{
string newName = string.Empty;
BaseEntity entity = request.MyWrapper.MyEntities[0];
//do something different depending on which entity we got
AdvancedEntity advancedEntity = entity as AdvancedEntity;
if (advancedEntity != null)
{
advancedEntity.Name = request.AuthenticationDetails.Username;
advancedEntity.Age++;
}
else
{
entity.Name = entity.Name + " and " + request.AuthenticationDetails.Username;
}
Response response = new Response();
response.Entity = entity;
return response;
}
}