tylerjensen/ServiceWire

Exception in SyncInterface

krjaction50 opened this issue · 7 comments

Hello,

Using ServiceWire over TCP/IP in .NET 4.8 to replace WCF. The first issue we found is the ServiceWire assembly does not have a strong name. Therefore, I used the StrongNamer to add a strong name to ServiceWire.dll across 2 projects we use it in. The first project is the server and the second project is the client. Locally in debug mode everything works fine (after using StrongNamer). I can communicate from client to server. When we made our release mode assemblies and deployed, I get the following error when spinning up a connection and trying to make a remote method call from the client.

Related LogID = 206686441 Callstack: System.Exception: The GJSE instance "appserver_qafeature_mt_1" is not running ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.TypeAccessException: SyncInterface failed. Type or version of type unknown. at ServiceWire.StreamingChannel.SyncInterface(Type serviceType, String username, String password) at ServiceWire.TcpIp.TcpChannel.Initialize(String username, String password, Type serviceType, IPEndPoint endpoint, Int32 connectTimeoutMs) at GJSESWInterfaceProxy..ctor(Type , IPEndPoint , ISerializer , ICompressor ) --- End of inner exception stack trace --- at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor) at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at ServiceWire.ProxyFactory.CreateProxy[TInterface](ProxyBuilder proxyBuilder, Object channelCtorValue, ISerializer serializer, ICompressor compressor) at ServiceWire.ProxyFactory.CreateProxy[TInterface](Type channelType, Type ctorArgType, Object channelCtorValue, ISerializer serializer, ICompressor compressor) at ATWebBusinessLogic.BusinessLogic.GJSE.GJSEBL.ManageServiceWireClientConnection(GJSEInstance instance) in e:\Staging_Autobuild\BuildSources\7_2_1\ATWebBusinessLogic\BusinessLogic\GJSE\GJSEBL.cs:line 61 --- End of inner exception stack trace --- at ATWebBusinessLogic.BusinessLogic.GJSE.GJSEBL.ManageServiceWireClientConnection(GJSEInstance instance) in e:\Staging_Autobuild\BuildSources\7_2_1\ATWebBusinessLogic\BusinessLogic\GJSE\GJSEBL.cs:line 81 at ATWebBusinessLogic.BusinessLogic.GJSE.GJSEBL.IsInstanceRunning(String instanceName) in e:\Staging_Autobuild\BuildSources\7_2_1\ATWebBusinessLogic\BusinessLogic\GJSE\GJSEBL.cs:line 327

I traced this to the following lines of code in the SyncInterface methd.

            //read sync data
            var len = _binReader.ReadInt32();
            //len is zero when AssemblyQualifiedName not same version or not found
            if (len == 0) throw new TypeAccessException("SyncInterface failed. Type or version of type unknown.");
            var bytes = _binReader.ReadBytes(len);
            if (null != _zkCrypto)

Any idea what could be the issue?

Thanks

Try it without strong naming. See if that eliminates the problem. ServiceWire has never been tested with strong naming. It spins an assembly in memory that would not be strong named and that may be the issue. It may also be reflection of types in the sync validation between client and server. Sorry I can't be more help. There aren't many cases where string naming is justified. If it works without it, consider not using the GAC and strong naming.

Consider dropping strong naming if you don't really need it for one of these reasons. https://learn.microsoft.com/en-us/dotnet/standard/assembly/strong-named#why-strong-name-your-assemblies

Unfortunately, strong naming is mandated at my company. We do not GAC our assemblies. It works strong named locally on my workstation but not on our servers. We do not have a firewall on our backend servers and we are using the same IP and port as it used for WCF. I'm going to create a small client and server test apps without strong naming and see if I can get them to work. Push comes to shove I'll download the master code and add some additional logging.

Thanks

Mandated? That is strange and very likely due to a misunderstanding of what strong naming is and why you might use it. Good luck.

Yes, large company and I totally agree with you. I will report back once I figure out this issue. I have no doubt it's environmental.

OMG, took me two days, downloading your code, signing it myself to still have the issue. Turns out it was something super silly and has nothing to do with strong naming.

ATWebBusinessLogic.BusinessLogic.GJSE.GJSESWInterface, ATWebBusinessLogic
Found service
GJSESWInterface
SyncInterface error 0., System.IO.FileLoadException: Could not load file or assembly 'System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
File name: 'System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'
at ServiceWire.DefaultSerializer.Serialize[T](T obj)
at ServiceWire.Host.ProcessSync(ZkSession session, BinaryReader binReader, BinaryWriter binWriter, Stopwatch sw) in D:\ServiceWire-master\src\ServiceWire\Host.cs:line 354

So we have tokenized config files because our software runs on like 40 different environments from Dev, QA, Pilot and Prod. Turns out when I added ServiceWire into our projects from Nuget it did indeed make the necessary change to the App.Config file BUT I neglected to copy those changes into our App.Config.Tokenized file and that's the file that gets de-tokenized at build time and then pushed to each environment. Everything working fine now using the Nuget package and the StrongNamer Nuget to sign it.

My bad.

Thanks, love the component, it's a perfect replacement for the way we were using WCF for inter-process communication.

I'm glad you figured it out. Best of luck.