WCF IClientMessageInspector在序列化时崩溃

时间:2012-07-12 05:51:58

标签: wcf soap-client

我使用IClientMessageInspector和它的方法BeforeSendRequest来检查请求消息。问题是某些请求消息有成员,其成员类型为object(在实际场景中,thre可能是示例字符串或其他值,在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;
        }

测试本身是一个单独的解决方案,它使用服务的参考。 在服务imnplmentation上,操作如下所示:

    [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
                       };
        }

也许某人可以拥有相同的经验并可以帮助解决这个问题?

0 个答案:

没有答案