0

IClientMessageInspectorとそのメソッドBeforeSendRequestを使用して、要求メッセージを検査します。重要なのは、一部の要求メッセージにはメンバーがあり、そのメンバーはオブジェクト型です(実際のシナリオでは、KnownType属性で指定された文字列またはその他の値の例があります)。

[DataContract(Namespace = "")]
    [KnownType(typeof(SomeValueDTO))]
    public class CenDTO
    {
        [DataMember]
        public string Uri { get; set; }

        [DataMember]
        public object Value { get; set; }
    }

このプロジェクトでは、名前空間がどこにも定義されていないことに注意してください。そのため、「BeforeSendRequest」で例外が発生しました。そして、このインターフェースは実際のサービスと同じDataContractSerializerを使用していないように見えます。これには、そのようなシリアル化エラーやそのようなsmthはありません。エラー:

    The empty string '' is not a valid name.
   at System.Xml.XmlTextWriter.LookupPrefix(String ns)
   at System.Xml.XmlDictionaryWriter.XmlWrappedWriter.LookupPrefix(String namespaceUri)
   at System.Xml.XmlDictionaryWriter.XmlWrappedWriter.WriteXmlnsAttribute(String prefix, String namespaceUri)
   at System.Xml.XmlDictionaryWriter.WriteXmlnsAttribute(String prefix, XmlDictionaryString namespaceUri)
   at System.Runtime.Serialization.XmlWriterDelegator.WriteXmlnsAttribute(XmlDictionaryString ns)
   at System.Runtime.Serialization.XmlWriterDelegator.WriteAttributeQualifiedName(String attrPrefix, XmlDictionaryString attrName, XmlDictionaryString attrNs, XmlDictionaryString name, XmlDictionaryString ns)
   at System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteTypeInfo(XmlWriterDelegator writer, XmlDictionaryString dataContractName, XmlDictionaryString dataContractNamespace)
   at System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteTypeInfo(XmlWriterDelegator writer, DataContract contract, DataContract declaredContract)
   at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithXsiType(XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle objectTypeHandle, Type objectType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle, Type declaredType)
   at System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle)
   at WriteCenDTOToXml(XmlWriterDelegator , Object , XmlObjectSerializerWriteContext , ClassDataContract )
   at System.Runtime.Serialization.ClassDataContract.WriteXmlValue(XmlWriterDelegator xmlWriter, Object obj, XmlObjectSerializerWriteContext context)
   at System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteDataContractValue(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
   at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithoutXsiType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
   at System.Runtime.Serialization.DataContractSerializer.InternalWriteObjectContent(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
   at System.Runtime.Serialization.DataContractSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
   at System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
   at System.Runtime.Serialization.XmlObjectSerializer.WriteObject(XmlDictionaryWriter writer, Object graph)
   at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeParameterPart(XmlDictionaryWriter writer, PartInfo part, Object graph)
   at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeParameter(XmlDictionaryWriter writer, PartInfo part, Object graph)
   at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeParameters(XmlDictionaryWriter writer, PartInfo[] parts, Object[] parameters)
   at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeBody(XmlDictionaryWriter writer, MessageVersion version, String action, MessageDescription messageDescription, Object returnValue, Object[] parameters, Boolean isRequest)
   at System.ServiceModel.Dispatcher.OperationFormatter.SerializeBodyContents(XmlDictionaryWriter writer, MessageVersion version, Object[] parameters, Object returnValue, Boolean isRequest)
   at System.ServiceModel.Dispatcher.OperationFormatter.OperationFormatterMessage.OperationFormatterBodyWriter.OnWriteBodyContents(XmlDictionaryWriter writer)
   at System.ServiceModel.Channels.BodyWriter.WriteBodyContents(XmlDictionaryWriter writer)
   at System.ServiceModel.Channels.BodyWriterMessage.OnBodyToString(XmlDictionaryWriter writer)
   at System.ServiceModel.Channels.Message.ToString(XmlDictionaryWriter writer)
   at System.ServiceModel.Channels.Message.ToString()
   at CID.TopicAnalyst.CIA.Test.Utils.MessageInspector.BeforeSendRequest(Message& request, IClientChannel channel) in D:\git\...\MessageInspector.cs:line 25
   at System.ServiceModel.Dispatcher.ImmutableClientRuntime.BeforeSendRequest(ProxyRpc& rpc)

「BeforeSendRequest」の実装(クラッシュは.ToString()で発生します):

public object BeforeSendRequest(ref Message request, IClientChannel channel)
        {
            if(request.Headers.Count > 0)
            {
                request.Headers.RemoveAt(0);
            }
            MessageBuffer buffer = request.CreateBufferedCopy(Int32.MaxValue);
            request = buffer.CreateMessage();
            var message = buffer.CreateMessage().ToString();
            var resultFile = ConfigurationManager.AppSettings.GetValues("requestFile").First();
            _serializer.Write(resultFile, message);
            return null;
        }

テスト自体は、サービスの参照を使用する別個のソリューションです。サービスの実装では、操作は次のようになります。

    [ServiceContract]
    public interface ISoapService
    {
        [OperationContract]
        SomeListResponseMessage GetSomeList(SomeListRequestMessage request);
     }

    [MessageContract]
    public class SomeListRequestMessage : BaseRequestMessage
    {
        ...

        [MessageBodyMember]
        public CenDTO Cen { get; set; }
        ...

     }

    [DataContract(Namespace = "")]
    [KnownType(typeof(SemValueDTO))]
    public class CenDTO
    {
        ...

        [DataMember]
        public object Value { get; set; }
    }

テストソリューションのいくつかのコード:

static class Program
    {
        static void Main(string[] args)
        {

            while(true)
            {

                var client = new SoapServiceClient("BasicHttpBinding_ISoapService");
                client.Endpoint.Behaviors.Add(new InspectorBehavior());

                var soapService = client.ChannelFactory.CreateChannel();

                var co = new CooRequestCreator(soapService);
                co.CreateAndWriteRequests();

                Console.WriteLine("Press y to repeat");
                var str = Console.ReadLine();
                if(str != "y") break;
            }

        }

サービスを呼び出す前に要求メッセージを作成します。

class CooRequestCreator : BaseRequestCreator<SomeListRequestMessage>
    {
        SemValueDTO _semaValue = new SemValueDTO
        {
            Key = "fb",
            Label = "Guild",
            Type = "org"
        };

        public CooRequestCreator(ISoapService soapService) : base(soapService)
        {
        }

        protected override SomeListRequestMessage CreateMinRequest()
        {
            return new SomeListRequestMessage
                       {
                          Cen =
                               new CenDTO
                                   {

                                       Value = _semaValue,
                                   },
                           MaxCount = 5
                       };
        }

たぶん誰かが同じ経験をしてそれを手伝うことができますか?

4

0 に答える 0