0

I have an issue where i use two different WebSocket references. One is a newer version, implementing an extended WebSocket called "SocketIO", the other one just a standard RFC6544 WebSocket. The newer one 'inherited' more or less ages ago parts of the older one but they're not really compatible as of today. For various reasons, i need to be able to use both in the project.

Now if i try them out alone, they work just fine.

If i try them in a project together, i get at the newer one throw an exception:

"Could not load type ... from Assembly.... Version = ... etc".

It apparently searches the assembly of the other Websocket reference for its type and cannot find it.

They don't share identic class names e.g. explicitly naming the reference has no effect and there's also no open conflict marked by VisualStudio.

I've googled around but have not been able to find a solution to e.g. how to tell the program exactly where to look for the newer one's assembly.

enter image description here

Update:

So i looked at the SocketIO Manifest and the exact issue is:

  1. The SocketIO references an old version of the WebSocket4Net

  2. The current version of WebSocket4Net lacks some of these old Types

  3. The problem: SocketIO works just fine without either new or old WebSocket4Net Assembly present - but as soon as a reference is available, it parses that assembly and throws an error that it couldn't find a specific outdated type.

enter image description here

  • Check out App Domains –  Jul 24 '20 at 08:04
  • @ MickyD : Dare to elaborate a bit more? E.g. detailing what to look for – Philipp Elhaus Jul 24 '20 at 08:34
  • Checkout the fusionlogs - [howto](https://stackoverflow.com/questions/255669/how-to-enable-assembly-bind-failure-logging-fusion-in-net) this will give you a better idea why the type / assembly is not loading. If not clear you can edit your question with the info from fusion log. – Preben Huybrechts Jul 24 '20 at 08:43
  • In my experience this is normally a conflict with the bitness of the library and your app. Try targeting AnyCPU in your solution platform. – Matt Evans Jul 24 '20 at 09:45
  • Use a sniffer like wireshark or fiddler and compare headers in first request of working and non working application. If you are using a secure connection it could be due to TLS 1.0 and TLS 1.1 being obsoleted and you must use TLS 1.2. The work load could be misleading and actually means it is trying to establish a secure connection. – jdweng Jul 24 '20 at 09:57
  • @ Matt Evans: Didn't work, just tried that as well with all possible Configuration combinations. Seems not to be a bitness issue. – Philipp Elhaus Jul 24 '20 at 10:17
  • 1
    @jdweng why are you confusing the OP about TLS nonsense when this is obviously an assembly loading issue? – CodeCaster Jul 24 '20 at 10:48
  • Why are you saying I'm wrong? The socket isn't starting and if part of starting is a connection that is failing then I'm correct. – jdweng Jul 24 '20 at 11:13
  • 1
    @jdweng you know I don't get a notification if you don't @ mention me. Anyhow, you're wrong because this code doesn't even run, it throws an exception when loading the assembly. No attempt at connecting is made. – CodeCaster Jul 24 '20 at 12:45
  • @PhilippElhaus see below answer –  Jul 25 '20 at 01:59

2 Answers2

1

OP:

i use two different WebSocket references...Now if i try them out alone, they work just fine.
If i try them in a project together, i get at the newer one throw an exception

I suspect neither WebSocket4Net assembliess are strong-named (SN) and if so .NET does not allow you to load two or more non-strong-named assemblies into the same App Domain even if the assemblies have different version numbers.

SNing offers many benefits particularly for CAS scenarios and placing assemblies into the GAC. Some open source people dislike SN but I find their fears are based on the false belief that SN is meant to be some form of software protection. To that they should refer to Authenticode.

MSDN: (my emphasis)

Do not rely on strong names for security. They provide a unique identity only.

.NET assemblies are not SN'd by defaut, refer to the Signing tab in Visual Studio (VS).

A SN assembly is based on four (4) attributes:

  1. It's simple text name. e.g. MyCoolControls
  2. Version number. e.g. 3.2.7.0
  3. Culture information. e.g. en-AU
  4. Public key and digital signature

This defines the assembly uniquely not just across versions but also across cultures within that version.

Solution

To avoid this issue you have two choices:

  1. SN the assembly: The easiest from a coding point of view of coding is SN both WebSocket4Net assemblies. It's easier if you can get the source code (assuming it's open source) then you can compile it with a SN step. Otherwise checkout this page. Once complete, you just need to insure that your version X C# code has a complete namespace reference to assembly X and version Y to assembly Y. Otherwise the compiler which edition you are referring to.

  2. Create child App Domains: a more advanced step requires that you create a child AppDomain per weakly-named WebSocket4Net version. Then place WebSocket4Net-version-specific code in that AppDomain. This allows you to load both original assemblies concurrently into their own space in your process without conflict. This option does not require any modification to WebSocket4Net

Assembly manifests

Personally I try to avoid assembly manifiest and their assembly re-direction likes. They are a bit of a hack and can lead to unexpected runtime issues. They are not addressing the source of the problem. Debugging assembly probing and load orders is never fun.

More

0

After i burned 4h on this, I circumvented the issue by using a different secondary WebSocket (WebSocketSharp instead of WebSocket4Net); the problem disappeared as WebSocketSharp shares no present/past code with SocketIO as Websocket4Net did.

The core problem that was behind this isn't solved though and i estimate this is a fringe problem, e.g. explicitly assigning or ignoring given external assemblies towards individual types.