Ive spoken to a few people in the past who have asked about the best way to manage 3rd party references that you want to get as NuGet packages for BizTalk engagements. I have recently had to deal with this so thought it was worth writing something about how we did it.
Firstly as a non BizTalk developer you might be thinking “what is the problem”?, well the problems are this:
- BizTalk requires assemblies to be installed in the GAC and by default nuget packages referenced through Visual Studio add the assembly to your bin directory
- In BizTalk you will be developing multiple applications that will run on a platform that supports side by side deployment. This is an added consideration rather than simply running in a local bin folder
Those are the core problems, but then additionally as someone who cares about implementing BizTalk projects in a way which allows us to effectively work as a development team across many concurrent projects we also have an additional few problems:
- How do I control which NuGet packages are used so its not a free for all
- How do I deploy the NuGet packages to my other environments
- How do I support multiple BizTalk applications wanting to use the same Nuget packages
In the rest of this article I am going to talk through the approach I have implemented and I think you will find it easy to use.
Before we get into the detail, at a high level the approach I am going to take here is to create a single central BizTalk application (lets call this application Acme.BZ.NuGet) that will be used to deploy all NuGet package assemblies. In my other BizTalk application where I am developing my functionality (lets call this Acme.BZ.MyApplication) I can reference NuGet packages as normal through visual studio but I can trust that this central application will take care of all of the packaging and deployment of my NuGet packages and I just need to ensure that its deployed on any server I want to run my custom Acme.BZ.MyApplication BizTalk app on.
Prerequisites & Considerations
Before we get into the approach there are some prerequisites I would like to talk about. These are things which my process will encourage to ensure your development process would work well.
Strong Names Assemblies
In BizTalk we can only use packages from NuGet which are strong named and can be installed into the GAC. If you are using a reference which is not strong named then you will need to get the source code and build it yourself but include a strong name and then take the output assemblies and then manage them this way if you have published them to a NuGet server.
Test Only Assemblies
In your BizTalk solution you may choose to add some NuGet packages which are not intended to be used in production but are simply to support your development effort. An example of such a package could be Specflow. I use this a lot and reference it in my Visual Studio test projects. I think that any NuGet packages which do not require deployment can just be managed locally.
Control over Package Use
One of the benefits of this approach is that by controlling the deployment of 3rd party references with this central BizTalk application it means that my development teams can be governed in terms of what packages they use. They can only use ones which are deployed by the central app and as an architect this gives me confidence that I know what the development teams are doing and there are no stealth approaches being implemented under the radar which will introduce architectural debt later.
One additional idea here is that If I am a BizTalk consultancy I could develop this central NuGet BizTalk application in house and then deploy it at my customers to ensure that consultants working on projects there are all using the same packages. I have seen many times that the same consultancy company has two teams working at different customers who implement projects in quite different ways. This kind of thing can be quite valuable in ensuring your projects are using the same 3rd party NuGet packages so you get some consistency.
Custom NuGet Server
I have not tried this approach yet but it seems logical that this approach will be able to include packages that you pull from a custom nuget server such as your own internal one in addition to packages from the public NuGet repository.
Side-By-Side & New Versions
One of the advantages of BizTalk is that its support for side by side deployment means that when a new version of a nuget package comes out and I want to include it, I could add it to my central BizTalk application and just deploy an update. I would then have both versions of the NuGet package deployed and the functional BizTalk applications could choose to use different versions if required.
Below is the process I used.
Step 1 – NuGet BizTalk Application
As I mentioned I have created a special BizTalk application called Acme.BZ.Nuget. In this application we will have no custom code and no BizTalk artefacts. It will simply be a visual studio solution with build scripts which will create a BizTalk application and load the assemblies from NuGet into the BizTalk application as assembly resources.
In the build we will then create a BizTalk msi just like in any other BizTalk application we create so it can be deployed using our normal deployment processes.
In the build scripts near the start I will have some MsBuild code which will download the versions of NuGet packages that I want using the NuGet command line. Please note here that I will not automatically take the latest, I want specific versions which I have decided to use. The below is an example of using the command line to do this.
At this point in the build the above snippet would have downloaded any Nuget packages we require and put them into the packages folder.
The next step is to import them into BizTalk. Later in the build when we would normally deploy stuff to BizTalk we would use the below snippet to do this.
To call out that last command it looks like the following:
<Exec Command=’BTSTask AddResource /Source:”$(MSBuildProjectDirectory)\packages\Castle.Core.3.3.0\lib\net45\Castle.Core.dll” /ApplicationName:”Acme.NuGet” /Type:System.BizTalk:Assembly /Overwrite /Destination:”%%BTAD_InstallDir%%\Castle.Core.dll” /Options:GacOnAdd,GacOnImport,GacOnInstall’/>
This will take the dll from the packages folder and deploy it to our NuGet BizTalk application. In our build process after this has happened for all of our dependencies we will package it all up and have a resulting BizTalk msi which we can take to any environment to install the dependencies in the way you are used to for all BizTalk applications.
Step 2 – NuGet BizTalk Application Build & Deployment
The next step to consider is build and deployment. As I mentioned above I would have a BizTalk application and Visual Studio solution to manage these resources in Nuget. I would add this to my build server and then when the build is complete I can deploy my msi. One of the key things to note here is that in the earlier considerations section I mentioned that this application would only be allowed to have standard code dll’s and no BizTalk artefacts. This is important to keep things simple as if it is only dll’s then there are no BizTalk application references to worry about. I simply use this NuGet BizTalk application as a container to make it easy to deploy stuff.
When it comes to deploying the application, I can choose to either deploy it to BizTalk as its own application or install it into the “BizTalk Application 1” application. If I am using BizTalk Standard edition then I would probably install it into “BizTalk Application 1” to not use up one of my 5 applications that I am allowed. If I am using BizTalk Enterprise then it doesnt matter. I also think its a good idea to install the msi and also add it to BizTalk. This will give you an easy way to see the assemblies that you have deployed through the application resources like in the below picture.
If I need to deploy an update then I can just install a new version of the msi on top of the existing BizTalk application I chose and it will add any new assemblies or any new versions of existing assemblies along side the ones shown in the resource view.
Using this approach will mean this should just drop into the existing processes that I use for deployment and make my life easy, and also give me clear governance over what has been deployed when.
Just to recap here there is nothing special from a BizTalk angle about how I am deploying these NuGet packages. I am simply using the BizTalk msi as a vehicle to be able to deploy the dll’s to the GAC on all of my BizTalk Servers in a consistent and repeatable way which is something I dont have easily available from NuGet. Using the BizTalk msi should allow me to follow the development and deployment processes I am already using and also give me visibility of what I have deployed through the management console. I should also find this very easy to manage adding new and updates to existing NuGet packages.
Step 3 – My BizTalk Application and using Packages from NuGet
The final step now that I have my packages deployed as a BizTalk application is to use them. Earlier we talked about the BizTalk application called Acme.BZ.MyApplication. This contains the integration logic that I want to write. In the Visual Studio solution that accompanies this BizTalk application I can not work in the normal NuGet way. I can add packages to my solution using the VS addin and the package manager and then use them as required. When I compile and run my BizTalk application, as long as the package I want to use was included in the Acme.BZ.NuGet BizTalk application and then deployed to the machine I want to use then the dll’s will already be in the GAC and running the code should now just work.
In the Acme.BZ.MyApplication application I will not need to do any magic to auto get and deploy NuGet related stuff as part of supporting this code base.
I have been finding this approach works just fine in my development using BizTalk and hopefully I have explained it clearly above so that you can have a pain free experience too. NuGet is a good thing which helps make some things easier in software development and is something we should like to use where appropriate with BizTalk. The unfortunate thing is BizTalk needs a little more consideration around the process you use to really get the best from NuGet but hopefully the above shows that with a simple yet structured approach you can get all of the benefits of NuGet with out having loads of pain.