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!