WCF响应超时、序列化出错报错处理及配置

作者:陆金龙    发表时间:2015-07-24 01:05   


1、接收对 http://xxx.svc 的 HTTP 响应时发生错误。这可能是由于服务终结点绑定未使用 HTTP 协议造成的。
     这还可能是由于服务器中止了 HTTP 请求上下文(可能由于服务关闭)所致。有关详细信息,请参阅服务器日志。

原因1:WCF服务返回数据记录较多,超出默认设置大小。

解决:在WCF服务端的配置文件中将maxItemsInObjectGraph配置项设置为2147483647,具体位置及配置示例如下:

   <system.serviceModel>
      <behaviors>
          <serviceBehaviors> 
                  <behavior> 
                         <dataContractSerializer maxItemsInObjectGraph="2147483647" />
               </behavior>
        </serviceBehaviors> 
      </behaviors>
   </system.serviceModel>

原因2:接口返回父类,但是实际返回的是子类,WCF在向客户端返回数据时,序列化出错就会出现这个错误。WCF的方法,不能返回ObjectICollectionIList之类的不明确的数据类型

解决:在服务接口或操作契约的定义上增加ServiceKnownTypeAttribute应用在服务契约类型上,已知类型在所有实现了该契约的服务操作中有效,如果应用于服务契约的操作方法上,则定义的已知类型在所有实现了该契约的服务对应的操作中有效。

[ServiceContract]
[ServiceKnownType(typeof(MyClass))]
public interface ISearchService
{
        BaseClass Get();
}
 
public class SearchService
{
      public  BaseClass Get()
       {
            return new MyClass()
       }
}
 
解决(不推荐):返回类型为接口或抽象类的定义添加KnowType特性。例如在定义BaseClass时添加KnowType特性,指定MyClass。不过不推荐这样使用,这违反抽象或接口不应该依赖细节的设计原则。特别是基类或接口于实现类在不同程序集,为了能成功添加特性,抽像层不得不去引用实现类所在的程序集,这几乎是w。
[KnownType(typeof(MyClass))]
public class BaseClass
{
    //
}

2、格式化程序尝试对消息反序列化时引发异常: 尝试对参数 http://tempuri.org/ 进行反序列化时出错: 。InnerException 消息是“对象图中可以序列化或反序列  化的项目数目上限为“65536”。请更改对象图或增加 MaxItemsInObjectGraph 的配额。 ”。有关详细信息,请参阅 InnerException。

原因:如果是从WCF获取数据,反序列化发生在客户端接收数据后。关键点是反序列化的项目数目上限为“65536”。

解决:修改客户端配置文件,将客户端配置的maxItemsInObjectGraph配置项的值增大到2147483647。如下

<system.serviceModel>下增加如下配置节点
<behaviors>
<endpointBehaviors>
<behavior >
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
</behavior>
</endpointBehaviors>
</behaviors>

3. 格式化程序尝试对消息反序列化时引发异常:

  作为WCF接口的参数或返回值,其成员必须有public的set属性,否则不会传递。

4、超过59秒的报错提示:System.TimeoutException: The request channel timed out while waiting for a reply after 00:00:59.9320000. Increase the timeout value passed to the call to Request or increase the SendTimeout value on the Binding. 

      超时报错处理。以下配置中默认为00:01:00 即1分钟。数据量大是超过59秒会报错。以下是改为10分钟

      closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00"

5.枚举类型数据传递失败

 解决:对于枚举类型,类型定义添加[DataContract]特性,每一项的定义都需要添加[EnumMember]特性。

附:客户端完整配置:

<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IServiceDataSync" closeTimeout="00:10:00"
openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647"
maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://192.168.0.230/WcfDataSync/ServiceDataSync.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IServiceDataSync"
contract="ServiceDataSync.IServiceDataSync" name="BasicHttpBinding_IServiceDataSync" />
</client>

<behaviors>
<endpointBehaviors>
<behavior >
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
</behavior>
</endpointBehaviors>
</behaviors>

</system.serviceModel>