WebServicePortal problem with custom principal and mixed C++ DLL

WebServicePortal problem with custom principal and mixed C++ DLL

Old forum URL: forums.lhotka.net/forums/t/7252.aspx


rsbaker0 posted on Thursday, July 09, 2009

This one is very strange, because it works fine client side.

Our application is mostly in C#, but it includes a small mixed mode managed/unmanaged C++ DLL (long story).

Evidently the C++ runtime initialization is complaining that it cannot resolve the type of our custom principal on the first call to the DLL that occurs on the server side of the portal.

The error being reported is below. The C++ DLL contains no references to the assembly or type shown in the "Additional information", so the runtime initialization seems to be picking up the custom princpal we are using for authentication. Even more strangely, the C# assembly which is calling the C++ DLL and getting this error is the very one that contains the class for the custom principal (e.g. it's the BOL assembly shown in the error).

Any thoughts on how to resolve this?

Error information ------------------>

 A first chance exception of type 'System.Runtime.Serialization.SerializationException' occurred in msvcm90.dll

Additional information: Type is not resolved for member 'Company.Application.BOL.CustomPrincipal,BOL, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

RockfordLhotka replied on Thursday, July 09, 2009

These problems can be a real bear.

The issue is probably that the thread does a context switch (or an AppDomain switch), and so .NET serializes all objects attached to the thread (most notably the principal) to the new context. This is done using the BinaryFormatter.

The BinaryFormatter has an interesting feature/limitation, where the deserialization process doesn't always find all assemblies loaded in the AppDomain. This is because (I'm told) there are actually four lists of loaded assemblies, and the BF doesn't check the list for 'dynamically loaded' assemblies, and on the server that almost always includes your business assemblies.

The Enterprise Services data portal host (server-side code) actually includes a workaround for this issue, because otherwise it wouldn't work at all. Normally you don't encounter this issue in a WCF/remoting/asmx host - but you are doing something a bit different with this C++ code, so there's probably some sort of context switch.

Search the CSLA project for "serialization workaround" to find the code I'm talking about.

rsbaker0 replied on Friday, July 10, 2009

Thanks! I'll look for the known serialization workaround.

I did some more investigating after my original post and proved it was the custom principal causing the problem. Wrapping the call that triggered the C++ DLL load with the following code avoided the exception, so perhaps I can figure a way to use this as a workaround if the other serialization workarounds aren't feasible:

var principal = Csla.ApplicationContext.User;
try
{
    Csla.ApplicationContext.User = GetGenericPrincipal();

    // Error used to occur here....
    LoadProperty<string>(LicenseSummaryProperty, GetSummary());
}
finally
{
    Csla.ApplicationContext.User = principal;
}

EDIT: Followup

The workaround in this thread appears to have solved the problem: http://forums.lhotka.net/forums/2/29700/ShowThread.aspx

However, in this case, the workaround didn't describe how to do the "real" serialization part, which I assume would be necessary since you want your custom principal to be fully serializable, yes?

So, I implemented serialization of the individual fields per examples in CSLA. It also seemed that I needed to implement a deserialization constructor, like this one for my custom principal class:

protected MyPrincipal(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) :

base((IIdentity)info.GetValue("Identity", typeof(IIdentity)))

{

}

Am I on the right track with this?

Copyright (c) Marimer LLC