在WCF中反序列化复杂DTO具有空List <t>

时间:2015-08-21 16:48:46

标签: c# wcf

我们最近将我们的解决方案从Asp.Net 4.0升级到4.5.1,现在我们在反序列化一些复杂的DTO时遇到错误。在所有情况下,DTO都具有未初始化的List<T>属性,并且在尝试将对象添加到集合时反序列化失败。我确保getter和setter初始化属性如下:

[DataMember]
public List<objBusinessActivityGroup> BusinessActivities
{
   get { return m_groupList ?? ( m_groupList = new List<objBusinessActivityGroup>()); 
}
set {
      m_groupList = (value != null) ? new List<objBusinessActivityGroup>(value) : new List<objBusinessActivityGroup>();
}
}

但这没有效果。我们还为每个父DTO和子DTO添加了[OnDeserializing]属性,以尝试初始化这些属性,但仍然没有帮助。我们已经浏览了所有类和接口,并确保每个[ServiceContract]属性都具有Namespace值,并且所有DTO都具有[DataContract]属性并具有相同的Namespace设置。我添加了一些在[OnDeserializing]回调被命中时生成日志条目的代码,并且可以看到调用回调的位置,但是由于无法保证调用回调的时间,我不能说是否它们会及时被调用,以便反序列化器将项添加到相应的集合中。

完整的环境是WinForms应用程序,它访问由自定义STS保护的WCF服务。就像我说的那样,在我们将Web服务解决方案升级到4.5.1之前一切正常。 WinForms应用程序仍在使用v4.0客户端配置文件,目前我们无法更改它。

这是我们得到的例外:

  

System.ServiceModel.FaultException 1 was unhandled by user code HResult=-2146233087 Message=The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://sure.amc.faa.gov/ws:far. The InnerException message was 'The get-only collection of type 'System.Collections.Generic.List 1 [[GlobalServices.Objects.objFABusinessActivity,GlobalServices,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null]]'返回空值。输入流包含集合项,如果实例为null,则无法添加这些集合项。考虑在getter中初始化集合。'有关更多详细信息,请参阅InnerException。     来源= mscorlib程序     行动= http://schemas.microsoft.com/net/2005/12/windowscommunicationfoundation/dispatcher/fault

     

堆栈跟踪:       服务器堆栈跟踪:          在System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime操作,ProxyRpc&amp; rpc)          在System.ServiceModel.Channels.ServiceChannel.Call(String action,Boolean oneway,ProxyOperationRuntime operation,Object [] ins,Object [] outs,TimeSpan timeout)          在System.ServiceModel.Channels.ServiceChannel.Call(String action,Boolean oneway,ProxyOperationRuntime operation,Object [] ins,Object [] outs)          在System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall,ProxyOperationRuntime操作)          在System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage消息)       在[0]处重新抛出异常:          在System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg,IMessage retMsg)          在System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData&amp; msgData,Int32 type)          在Services.WebServices.FundingAgreementService.IFundingAgreementRepository.SaveRevision(objFundingAgreementR far,Boolean issubmit,Int32 userid)          at Services.WebServices.FundingAgreementService.FundingAgreementRepositoryClient.SaveRevision(objFundingAgreementR far,Boolean issubmit,Int32 userid)in c:\ Projects \ SURe_Client_1_5 \ Services \ Service References \ WebServices.FundingAgreementService \ Reference.cs:line 4519          at Services.Models.IAAModel.DoSaveRevision(Object sender,DoWorkEventArgs e)位于c:\ Projects \ SURe_Client_1_5 \ Services \ Models \ IAAModel.cs:第1192行          在System.ComponentModel.BackgroundWorker.WorkerThreadStart(Object参数)     InnerException:

这就是说,父DTO(远)的属性为List<objBusinessActivityGroup>。每个objBusinessActivityGroup都有List<objFABusinessActivity>类型的属性。当反序列化器将项添加到List<objFABusinessActivity>时,它为空。

这是我们初始化集合的方式:

[DataMember]
public List<objFABusinessActivity> BAList
{
    get
    {
        if (_baList == null)
        {
            _baList = new List<objFABusinessActivity>();
         }
         return _baList;
    }
    set {
            _baList = (value != null) ? new List<objFABusinessActivity>(value) : new List<objFABusinessActivity>();
        }
    }

1 个答案:

答案 0 :(得分:0)

您是否考虑过应用Data Contract Know类型?它允许您事先指定在反序列化期间应包括的类型以供考虑。查看更多详情here

[KnownType(typeof(List<objFABusinessActivity>))]
[DataContract]
public class YourDtoClass
{
   [DataMember]
   public List<objFABusinessActivity> BAList
   {
     get
     {
        if (_baList == null)
        {
            _baList = new List<objFABusinessActivity>();
         }
         return _baList;
     }
     set 
     {
            _baList = (value != null) ? new List<objFABusinessActivity>(value) : new List<objFABusinessActivity>();
     }
   }
}