We're trying to upgrade to the latest Csla 4.5 on .Net 4.0. We're still using remoting for the time being and will at some future point move to WCF, but for now remoting it is. I've hit a problem where the BinaryFormatter hangs when deserizlizing one of our types. The odd part is that it does work the first few times, it only fails after a few back and forths. So I'm trying to move us to the NetDataContractSerializer, which we'd use on WCF anyway.
My issue there is that immediately we get an exception (before any of the remoting even happens) when trying to serialize the very first type. It fails with a SerializationException: Type is not resolved for member "ABC" I've not been able to find any useful information, and its my understanding the NDCS should pretty much be a drop in replacement for BinaryFormatter and thus honor the Serializable / NonSerializable attributes.
This failure is happening just running our unit tests over remoting, both in R# and in the NUnit GUI. Here's a portion of the stack trace (omitted parts are our code / remoting proxy calling into serialize the object):
at System.AppDomain.GetHostEvidence(Type type)
at System.Security.Policy.AppDomainEvidenceFactory.GenerateEvidence(Type evidenceType)
at System.Security.Policy.Evidence.GetHostEvidenceNoLock(Type type)
at System.Configuration.ClientConfigPaths.GetEvidenceInfo(AppDomain appDomain, String exePath, String& typeName)
at System.Configuration.ClientConfigPaths.GetTypeAndHashSuffix(AppDomain appDomain, String exePath)
at System.Configuration.ClientConfigPaths..ctor(String exePath, Boolean includeUserConfig)
at System.Configuration.ClientConfigPaths.GetPaths(String exePath, Boolean includeUserConfig)
at System.Configuration.ClientConfigurationHost.RequireCompleteInit(IInternalConfigRecord record)
at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Boolean requestIsHere, Object& result, Object& resultRuntimeObject)
at System.Configuration.BaseConfigurationRecord.GetSection(String configKey)
at System.Runtime.Serialization.Configuration.NetDataContractSerializerSection.TryUnsafeGetSection(NetDataContractSerializerSection& section)
at System.Runtime.Serialization.XmlObjectSerializerWriteContextComplex..ctor(NetDataContractSerializer serializer, Hashtable surrogateDataContracts)
at System.Runtime.Serialization.NetDataContractSerializer.InternalWriteObjectContent(XmlWriterDelegator writer, Object graph, DataContract contract, Hashtable surrogateDataContracts)
at System.Runtime.Serialization.NetDataContractSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph)
at System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.XmlObjectSerializer.WriteObject(Stream stream, Object graph)
Have you tried to hook into AppDomain.TypeResolve event?
This should at least give some indication of which type and assembly that is not found (resolved).
It could be that some assembly is not available in the folder that the testrunner is loading assemblies from or maybe even an old version that is missing some types is in that folder.
You could also use ProcMon from Sysinternals to trace which assemblies is "searched" for and "loaded" and from which "folders". This might also help you identify whether the correct assemblies is loaded or not.
I figured out our main problem was our remoting proxy. Instead of returning TaskFactory.StartNew with an Action that called the remote data portal, I changed to code to use TaskCompletionSource and called SetResult / SetException as appropriate. Once that was out of the way, the NDCS still didn't work in the unit tests but did in the main application (and no more issues with the application hanging while awaiting a DP_F call).
I then changed back to BinaryFormatter for serialization and now the unit tests run as well. Looking at the Fusion logs it appears that R# 8 is probing the \Program Files (x86)\JetBrains\ReSharper\v8.2\Bin folder which of course contains none of the needed assemblies. Turning of shadow copying didn't seem to work either; it looks like for some reason the NDCS ends up running in a new AppDomain which causes this shift. I don't know why the BinaryFormatter works as expected though.
I'd like to solve this as we do want to move to WCF and I think the team will want to keep remote dataportal enabled as part of the tests we have, so if there's a way to get this working I'd still like to know.
Also, what is weird is that there are a few unit tests that have always failed serializing with the same message, and those tests and the NDCS always fail with the same type, which is our custom principal.
Do you use the CslaTaskScheduler - If not then the problem is likely that the background thread does not get the CurrentPrincipal and ApplicationContext from the calling thread.
No, we weren't using that.. would that cause the Task to hang and never return? I notice that on .Net 4 the WcfProxy does something similar; it uses BackgroundWork and then awaits a TaskCompletionSource's Result property instead of calling via TaskFactory.StartNew. I was wondering if the same issue had shown up there as I would have expected to be able to use TaskFactory.StartNew.
No., it shouldnt cause the thread to hang (unless you are calling an async dataportal call in the background thread).
TaskFactory.StartNew will make the code run on a background thread and you could end up loosing the synchronizationcontext and not be able to reenter the thread if you make an async Dataportal Fetch call from that background thread.
You code would also change to have the default Principal on the background thread - unless you have added your own mechanism to transfer the calling thread Principal to the background thread or call AppDomain.SetThreadPrincipal to set the default principal in a Windows (WinForms/WPF app).
Copyright (c) Marimer LLC