Tuesday 9 February 2016

.Net remoting (via Spring.net) System.Security.SecurityException ReflectionEmit NHIbernate

Using Spring.Net to implement .Net remoting. Console app is server doing db connection va NHibernate. MVC website is client. Connected okay and server returned NHibernate entity-object when successfully logged in. Problem came when the Client attempted to call a remote object passing in the NHibernate entity. The call generated exception:
2016-02-09 11:31:30,503 [5] ERROR ControllerErrors - xxxxxxx.Common.MVCBase.ActionFilters.HandleException: Index: Exception has been thrown by the target of an invocation.
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Security.SecurityException: Request for the permission of type 'System.Security.Permissions.ReflectionPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.
   at System.Security.CodeAccessSecurityEngine.Check(Object demand, StackCrawlMark& stackMark, Boolean isPermSet)
   at System.Security.CodeAccessPermission.Demand()
   at System.Reflection.Emit.AssemblyBuilder.DefineDynamicModuleInternalNoLock(String name, Boolean emitSymbolInfo, StackCrawlMark& stackMark)
   at System.Reflection.Emit.AssemblyBuilder.DefineDynamicModuleInternal(String name, Boolean emitSymbolInfo, StackCrawlMark& stackMark)
   at System.Reflection.Emit.AssemblyBuilder.DefineDynamicModule(String name, Boolean emitSymbolInfo)
   at Castle.DynamicProxy.ModuleScope.CreateModule(Boolean signStrongName)
   at Castle.DynamicProxy.ModuleScope.ObtainDynamicModuleWithWeakName()
   at Castle.DynamicProxy.ModuleScope.ObtainDynamicModule(Boolean isStrongNamed)
   at Castle.DynamicProxy.Generators.Emitters.ClassEmitter.CreateTypeBuilder(ModuleScope modulescope, String name, Type baseType, Type[] interfaces, TypeAttributes flags, Boolean forceUnsigned)
   at Castle.DynamicProxy.Generators.Emitters.ClassEmitter..ctor(ModuleScope modulescope, String name, Type baseType, Type[] interfaces, TypeAttributes flags, Boolean forceUnsigned)
   at Castle.DynamicProxy.Generators.Emitters.ClassEmitter..ctor(ModuleScope modulescope, String name, Type baseType, Type[] interfaces, TypeAttributes flags)
   at Castle.DynamicProxy.Generators.Emitters.ClassEmitter..ctor(ModuleScope modulescope, String name, Type baseType, Type[] interfaces)
   at Castle.DynamicProxy.Generators.BaseProxyGenerator.BuildClassEmitter(String typeName, Type parentType, Type[] interfaces)
   at Castle.DynamicProxy.Generators.BaseProxyGenerator.BuildClassEmitter(String typeName, Type parentType, IList interfaceList)
   at Castle.DynamicProxy.Generators.ClassProxyGenerator.GenerateCode(Type[] interfaces, ProxyGenerationOptions options)
   at Castle.DynamicProxy.Serialization.ProxyObjectReference.RecreateClassProxy()
   at Castle.DynamicProxy.Serialization.ProxyObjectReference.RecreateProxy()
   at Castle.DynamicProxy.Serialization.ProxyObjectReference..ctor(SerializationInfo info, StreamingContext context)
The action that failed was:
Demand
The type of the first permission that failed was:
System.Security.Permissions.ReflectionPermission
The first permission that failed was:


The demand was for:


The only permitted permissions were:




The method that caused the failure was:
System.Runtime.Remoting.Channels.ServerProcessing ProcessMessage(System.Runtime.Remoting.Channels.IServerChannelSinkStack, System.Runtime.Remoting.Messaging.IMessage, System.Runtime.Remoting.Channels.ITransportHeaders, System.IO.Stream, System.Runtime.Remoting.Messaging.IMessage ByRef, System.Runtime.Remoting.Channels.ITransportHeaders ByRef, System.IO.Stream ByRef)
   --- End of inner exception stack trace ---
Searching internet, it appeared it was to do with Trust Level of client. After lots of testing of trust settings & configuration was still getting the error. Noticed the in the stack trace the reference to Castle.DynamicProxy - made me think it was to do with NHibernate. Bit more researching and think I found the reason - code was throwing exception when serializing proxy object (which was a property of the NHibernate entity). Solution: On server app, set the TCP channel to have binary formatter with Full level filter-type. App.config:
<system.runtime.remoting> <application> <channels> <channel ref="tcp" port="8005" /> <serverProviders> <formatter ref="binary" typeFilterLevel="Full" /> </serverProviders> <clientProviders> <formatter ref="binary" /> </clientProviders> </channels> </application> </system.runtime.remoting>
Except... this didn't work. Under debugging, after the RemotingConfiguration.Configure("myapp.exe.config",false); call the RegisteredChannel still had a server-provider with Low level filter-type. To get it working had to change code to programmatically setup the channel:
                //// Creating a custom formatter for a TcpChannel sink chain.
                BinaryServerFormatterSinkProvider provider = new BinaryServerFormatterSinkProvider();
                provider.TypeFilterLevel = TypeFilterLevel.Full; // required for serialize/deserialize of NHibernate proxy objects
                IDictionary props = new Hashtable();
                props["port"] = 8005;
                //// Pass the properties for the port setting and the server provider in the server chain argument. (Client remains null here.)
                TcpChannel chan = new TcpChannel(props, null, provider);
                ChannelServices.RegisterChannel(chan, false);
Job done!