调用带有对象List的WCF方法。通过iPhone应用程序消费

时间:2011-03-07 12:06:18

标签: iphone wcf web-services soap nsmutablearray

我有一个通过iPhone应用程序使用的WCF服务。接受字符串参数或单个对象的所有其他方法都正常工作,但是当我调用一个带有“List<CustomObjectClass> ssf”的方法时。

我正在将NSMutableArray CustomObjectClass传递给此方法,我收到以下错误:

有什么想法吗?

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><s:Fault><faultcode xmlns:a="http://schemas.microsoft.com/net/2005/12/windowscommunicationfoundation/dispatcher">a:DeserializationFailed</faultcode><faultstring xml:lang="en-AU">The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:ssf. The InnerException message was 'Error in line 2 position 6. Expecting state 'Element'.. Encountered 'Text'  with name '', namespace ''. '.  Please see InnerException for more details.</faultstring><detail><ExceptionDetail xmlns="http://schemas.datacontract.org/2004/07/System.ServiceModel" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><HelpLink i:nil="true"/><InnerException><HelpLink i:nil="true"/><InnerException i:nil="true"/><Message>Error in line 2 position 6. Expecting state 'Element'.. Encountered 'Text'  with name '', namespace ''. </Message><StackTrace>   at ReadArrayOfScanShareFriendFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString , XmlDictionaryString , CollectionDataContract )&#xD;
   at System.Runtime.Serialization.CollectionDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)&#xD;
   at System.Runtime.Serialization.XmlObjectSerializerReadContext.ReadDataContractValue(DataContract dataContract, XmlReaderDelegator reader)&#xD;
   at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, Type declaredType, DataContract&amp; dataContract)&#xD;
   at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator xmlReader, Type declaredType, DataContract dataContract, String name, String ns)&#xD;
   at System.Runtime.Serialization.DataContractSerializer.InternalReadObject(XmlReaderDelegator xmlReader, Boolean verifyObjectName, DataContractResolver dataContractResolver)&#xD;
   at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)&#xD;
   at System.Runtime.Serialization.DataContractSerializer.ReadObject(XmlDictionaryReader reader, Boolean verifyObjectName)&#xD;
   at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.DeserializeParameterPart(XmlDictionaryReader reader, PartInfo part, Boolean isRequest)</StackTrace><Type>System.Runtime.Serialization.SerializationException</Type></InnerException><Message>The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:ssf. The InnerException message was 'Error in line 2 position 6. Expecting state 'Element'.. Encountered 'Text'  with name '', namespace ''. '.  Please see InnerException for more details.</Message><StackTrace>   at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.DeserializeParameterPart(XmlDictionaryReader reader, PartInfo part, Boolean isRequest)&#xD;
   at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.DeserializeParameter(XmlDictionaryReader reader, PartInfo part, Boolean isRequest)&#xD;
   at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.DeserializeParameters(XmlDictionaryReader reader, PartInfo[] parts, Object[] parameters, Boolean isRequest)&#xD;
   at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.DeserializeBody(XmlDictionaryReader reader, MessageVersion version, String action, MessageDescription messageDescription, Object[] parameters, Boolean isRequest)&#xD;
   at System.ServiceModel.Dispatcher.OperationFormatter.DeserializeBodyContents(Message message, Object[] parameters, Boolean isRequest)&#xD;
   at System.ServiceModel.Dispatcher.OperationFormatter.DeserializeRequest(Message message, Object[] parameters)&#xD;
   at System.ServiceModel.Dispatcher.DispatchOperationRuntime.DeserializeInputs(MessageRpc&amp; rpc)&#xD;
   at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc&amp; rpc)&#xD;
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc&amp; rpc)&#xD;
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage41(MessageRpc&amp; rpc)&#xD;
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc&amp; rpc)&#xD;
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc&amp; rpc)&#xD;
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc&amp; rpc)&#xD;
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc&amp; rpc)&#xD;
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc&amp; rpc)&#xD;
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc&amp; rpc)&#xD;
   at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)</StackTrace><Type>System.ServiceModel.Dispatcher.NetDispatcherFaultException</Type></ExceptionDetail></detail></s:Fault></s:Body></s:Envelope>

1 个答案:

答案 0 :(得分:2)

看起来从iPhone应用程序发送的SOAP消息不是WCF服务所期望的格式。如果是这种情况,那么在将数组传递给方法时,您可能需要对NSMutableArray CustomObjectClass的序列化进行更多控制。

为了检查这是否是问题,您可以实现并配置WCF消息检查器,该检查器将SOAP请求消息写入文件,然后查看该文件以检查它是否类似于SOAP消息:

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"
            xmlns:a="http://www.w3.org/2005/08/addressing">
    <s:Header>
        <a:Action s:mustUnderstand="1">http://tempuri.org/IService/SendData</a:Action>
        <a:MessageID>urn:uuid:8a582916-1b9a-47f8-8fb1-c9ff18420391</a:MessageID>
        <a:ReplyTo>
            <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
        </a:ReplyTo>
        <a:To s:mustUnderstand="1">net.tcp://localhost:13031/Service</a:To>
    </s:Header>
    <s:Body>
        <SendData xmlns="http://tempuri.org/">
            <ssf xmlns:b="http://schemas.datacontract.org/2004/07/Common"
                 xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
                <!-- Zero or more CustomObjectClass elements-->
                <b:CustomObjectClass>
                    <!-- Zero or more elements for CustomObjectClass properties -->
                </b:CustomObjectClass>
            </ssf>
        </SendData>
    </s:Body>
</s:Envelope>

实施WCF消息检查器:

  1. 实施WCF消息检查器(IDispatchMessageInspector)。
  2. 实施端点行为(IEndpointBehavior)。
  3. 实施自定义行为扩展元素(BehaviorExtensionElement)。
  4. WCF邮件检查器

    public class FileOutputMessageInspector : IDispatchMessageInspector
    {
        public object AfterReceiveRequest( ref Message request, IClientChannel channel,
            InstanceContext instanceContext )
        {
            string path = Path.Combine(
                AppDomain.CurrentDomain.SetupInformation.ApplicationBase,
                Guid.NewGuid().ToString() + ".xml"
            );
            File.WriteAllText( path, request.ToString() );
            return null;
        }
    
        public void BeforeSendReply( ref Message reply, object correlationState )
        { }
    }
    

    终点行为

    public class FileOutputBehavior : IEndpointBehavior
    {
        public void AddBindingParameters( ServiceEndpoint endpoint,
            BindingParameterCollection bindingParameters )
        { }
    
        public void ApplyClientBehavior( ServiceEndpoint endpoint,
            ClientRuntime clientRuntime )
        {
            throw new ApplicationException( "Behavior is not supported on client side." );
        }
    
        public void ApplyDispatchBehavior( ServiceEndpoint endpoint,
            EndpointDispatcher endpointDispatcher )
        {
            FileOutputMessageInspector inspector = new FileOutputMessageInspector();
            endpointDispatcher.DispatchRuntime.MessageInspectors.Add( inspector );
        }
    
        public void Validate( ServiceEndpoint endpoint )
        { }
    }
    

    行为扩展元素

    public class FileOutputElement : BehaviorExtensionElement
    {
        public override Type BehaviorType
        {
            get { return typeof( FileOutputBehavior ); }
        }
    
        protected override object CreateBehavior()
        {
            return new FileOutputBehavior();
        }
    }
    

    配置WCF邮件检查器:

    1. 声明新的行为扩展(确保在type属性中使用了正确的完整类型名称。)
    2. 在端点行为中使用声明的行为扩展名。
    3. 引用端点行为。
    4. 使用以下配置作为参考:

      <system.serviceModel>
          <services>
              <service name="Server.Service">
                  <endpoint address=""
                            binding="netTcpBinding" bindingConfiguration="TCP"
                            contract="Common.IService"
                            behaviorConfiguration="RequestMessageToFile"/>
                  <host>
                      <baseAddresses>
                          <add baseAddress="net.tcp://localhost:13031/Service"/>
                      </baseAddresses>
                  </host>
              </service>
          </services>
          <bindings>
              <netTcpBinding>
                  <binding name="TCP">
                      <security mode="None"/>
                  </binding>
              </netTcpBinding>
          </bindings>
          <behaviors>
              <endpointBehaviors>
                  <behavior name="RequestMessageToFile">
                      <requestFileOutput />
                  </behavior>
              </endpointBehaviors>
          </behaviors>
          <extensions>
              <behaviorExtensions>
                  <add name="requestFileOutput"
                       type="Common.FileOutputElement, Common"/>
              </behaviorExtensions>
          </extensions>
      </system.serviceModel>