Sorting out the DLL hell, Part 1: The Problem

Let me tell you right away if you need to read this post at all. If you never wrote a single .NET class library intended to be used as a .NET interoperability assembly from C/AL, or if you never ever deployed a .dll file into the Add-ins folder of either Service or RoleTailored Client, then you probably don’t want to read this post.

Good, since you are still reading it means that you either deployed your own or somebody else’s .NET stuff into NAV’s client or server’s Add-ins folders. If you ever did so, you probably did not enjoy the experience too much. If you did enjoy the experience, maybe you should not read any further either.

Even better! Since you are still here it means that you didn’t enjoy deploying assemblies. Let me break some good news – all your problems are now gone! And I am not talking NAV 2016, I am talking NAV 2013 and anything newer.

There are several problems with deploying assemblies.

First, if the assembly is in use, you must close the client, or the restart the service tier. That’s not always possible because people might just be needing the server at that very moment.

Second, if you use client-side assemblies, you have to make sure they are available on every single machine. This is easier said than done. Server can take care of it as long as it’s NAV 2015 or newer, but it does not do an overly good job at this. The assembly is copied once, and if you need to redeploy you must either version it up (which is a double-edged sword during development) or you need to dig through user’s file system to locate and delete assemblies to trigger redeployment. You can also use ClickOnce deployments, but you have to play around with configuration and you will experience pain when it comes to properly versioning.

Third, if you don’t version your assemblies – it’s gonna be a mess during development when you change things. If you do version your assemblies – it’s still gonna be a mess during development. Redeploying assemblies and making sure all of them are present exactly where they need to be present will cost you time.

And last, but not least – when moving your application to another server, you must redeploy the assemblies, again making sure everything is deployed properly.

To make it worse, the more assemblies you have to handle, the more fun you’ll have juggling around with them.

Now, you may say: I don’t care, because in NAV 2016 there is automatic deployment of any kind of assemblies from the database to both client and server. This solves the problem, because assemblies are stored in the database and are deployed to whomever needs them, whenever.

Well, there are three problems with this database assembly deployment.

First, it only works under NAV 2016. If you are still running anything older, and chances are you are, then this new feature won’t help you.

Second, in NAV 2016 it doesn’t really work as advertised. Everything is hunky-dory with JavaScript, but when it comes to deploying .NET interoperability assemblies, I didn’t manage to get a single one deployed. Try it yourself, and I bet you’ll figure out that it doesn’t work for you either. But in all honesty, Microsoft will probably fix it over the next couple of cumulative updates, so this is likely a temporary bug, not a big deal, really.

And third – and here I’ll have to be brutally blunt – even when Microsoft fixes the current bugs with this feature, the whole Add-in table and deployment features are just terribly badly designed.

So, let me hang around this latest claim for a bit.

When control add-ins were introduced, back in 2009 SP1, whoever designed the feature wasn’t thinking much of possible consequences of expansion of NAV stack to their design decisions. Namely – the problem is add-in identification.

To identify a control add-in, you need two pieces of information Control Add-in Name, and public key token. Control Add-in Name comes from the ControlAddInExport attribute of the class you are exposing, and public key token comes from the assembly strong name signature.

There is an immediate problem – the (Client) Add-in table also has the version field. This field is a part of the key, but it’s not the part of the control add-in identification in the Development Environment. If you have two assemblies with the same name and public key token, just with different version number, how can you tell which one will be picked by the client? I can’t.

But still, we could live with this, using a single version at a time can go long way. Not the best solution, but works.

However, the biggest issue becomes visible the moment you want to use this table for anything else but JavaScript control add-ins under NAV 2016. The issue is – to deploy assembly properly, you need to be able to identify it. And .NET assembly is not identified by ControlAddInExport attribute, it’s identified by: assembly name, assembly version, culture, and public key token. Out of those four elements, we only have one and a half covered: we have public key token alright, but what about the Add-In Name property?

Again – for client add-ins it comes from the ControlAddInExport attribute, and it’s easy. But what to do with .NET assemblies? Documentation says you must name your control add-in exactly as the assembly is named. Good, but what about culture? Yes, we can argue whether or not having culture-specific assemblies for general purpose, but hey – it’s sometimes not you who decides.

In any case, any identification which ignores the .NET way of identifying .NET assemblies – and that is through fully qualified assembly name – is just wrong. Why reinventing a wheel, and then come up with a bad wheel, when .NET already has built-in way of uniquely identifying assemblies?

Unless the Add-in table is redesigned to take into account the .NET way of identifying assemblies, this table will be only good for JavaScript assemblies, and possibly somewhat good for .NET control add-ins. But for .NET interoperability,  it just doesn’t cut it.

Okay – now that I have laid out the problem, is there a solution for automatically deploying .NET interoperability assemblies? Yes, of course there is. I wouldn’t be writing this long post if there weren’t one.

So, stay tuned for the next post, in which I’ll explain how you can pull some .NET magic to enable simple and powerful management of external .NET assemblies on which your solution might depend.

12 thoughts on “Sorting out the DLL hell, Part 1: The Problem”

    1. Actually, I have already posted and scheduled the remaining two posts in this series – one for Monday, with solution explanation, and one for Tuesday with code. Call me a bitch for not posting it all at once – it’d be one veeeeery long post.

  1. As per usual a very thourough post.
    When 2015 announced Client add-ins could be placed on the server and server would handle distribution on-the-fly, I was very happy.

    As you also discovered, this works in mysterious ways.

    What i do, is let the client grab the add-in from the web. Greatly inspired by Gunnar http://www.dynamics.is/?p=1709 (Who in turn was inspired by you 🙂 )

    1. Yes, I presented this at TechDays 2013 indeed. But this solution I am talking about here is nothing like it. That solution is case-by-case, for every .NET type you need to call it and deploy the assembly individually. The solution I write about here is generic, it handles all situations, code is written once, and deployed only once. And – it’s pure C/AL.

  2. Great job Vjeko (as always) and thanks for sharing with us! Won’t be able to make it to TechDays 2015 but I’ll be there next year. Anyone attending your session(s) is in for a treat.

Leave a Reply