Add project reference? Enter 2014….Using NuGet for packaging projects and dependencies
[UPDATE] Sample solution available on OneDrive (https://onedrive.live.com/?cid=5eaaef40eefdaddb&id=5EAAEF40EEFDADDB%21109)
A solution consists of projects, projects uses components, components are of a specific version, changing the components thus requires a versioning strategy….which one are you using? All solutions which are architected into several tiers, have a form of layering with (which I hope) an abstraction of re-usable components. A project which is used to implement automated order approvals (AOA), with a requirement to implement logging, and retrieve something out of the database will likely have the minimum of 3 projects
- Solution AOA
- Project - AOA.Core
- Project - AOA.DataProject
- Project - Common.Logging
Let’s assume, that the Logging library is also used by another solution: BOB
- Solution BOB
- Project – BOB.Core
- Project – BOB DataProject
- Project - Common.Logging
When the requirements of logging change, and the project BOB needs a specific change due to legislation requirements. What options do we have to make sure that either the AOA solution does not break because it’s automatically using the latest version?
- Using the latest version of all the projects / components (e.g. using a build server)
- Project approach: using project references to existing / local projects
- Risk: the latest version has breaking changes
- Using a specific version by copying the dll to a local solution folder
- Project approach: using local dll references
- Risk: Managing the versions will lead to an enormous spreadsheet
- Using a SharedAssemblies folder which contains the latest version
- Project approach: using Shared dll references
- Risk: Managing the versions will lead to an enormous spreadsheet
Basically, we don’t know which version is used, we don’t control any of this, and the solutions provided are not sufficient. Enter NuGet….
So NuGet can be used to overcome this problem, by packaging components, versioning and even manage dependencies. When a project has a dependency and another component, it is possible to define this relationship in a NuGet package, and by doing this, retrieving the NuGet package, will automatically retrieve the dependent package. This allows you to ensure that the correct versions are retrieved, and the self-created dll-hell can be mitigated.
How can we do this? (example feed and solution can be found at: https://onedrive.live.com/?cid=5eaaef40eefdaddb&id=5EAAEF40EEFDADDB%21109)
Our client Contoso is developing a solution, which makes use of the Contoso.SB.Library. This library provides functionality in conjunction with the Azure Service Bus Library, providing automatic property promotion used to enable ‘automatic’ topics/subscriptions (just a example, of a solution that might exist ).
This API is referenced by using a project reference, so the latest version of the SB.Library is always used….we would like to have more control. For this we can create a custom package, using the tool ‘NuGet Package Explorer’. Using this tool, it is possible to create a NuGet package of the Contoso.SB.Library, and be able to manage the used 3rd-party references, versioning and implement a changemanagement process.
We can create a new project
We then need to define the properties (my colleague Sybren Kuiper is working on a NuGet Packager which automatically retrieves this information from the project file), at this moment, we need to do this manually.
The Contoso.SB.Library uses the ServiceBus.v1_1 NuGet Package, so we need to add this dependency. This means that adding a reference to the Contoso.SB.Library will automatically retrieve the ServiceBus.v1_1 package.
Here you see the dependency defined in the Contoso.SB.Library
At this moment we only have a skeleton, we can now add the Library by adding a Lib Folder:
And add the Dll by adding an existing file
Select the dll…
And save the package…
We can publish the package to a feed, such as NuGet.Org, but we can also simply use a file share to build our own private NuGet repository. In this case the repository is ‘C:\Temp\NuGetFeed’, this should offcourse be a UNC Path.
!!BACK TO VISUAL STUDIO!!
Click on: Tool\NuGet Package Manager \ Package Manager Settings
Add a new feed, and specify the path, for example our repository in ‘C:\Temp\NuGetFeed’:
In the solution we can now manage the NuGet packages for the solution;
And add a reference to the Service Bus Library Functions, notice the dependencies (my colleague Sybren Kuiper is working on a NuGet HelpFile builder, which automatically generates a SandCastle help file, from the project file, which is then used in the NuGet package so that the help is available in this window), at this moment, we need to do this manually.
As we can see, the dependency leads to the installation of the ServiceBus.v1_1, the version WE specified!
Restrictions may apply
So far….the same reference, only more work? No…
What we did, was abstracted the versioning and dependencies out of the solution. This means that the package is in control of the dependencies and not the project. This allows for a managed release of components, AND, new versions are available in a notification menu. This can be automated, used in a TFS build, etc.
What happens if we release a new version of the component? (using the NuGet Package Explorer)…
We can save the new version, where the name is generated based on the specified version (at this moment manually). This allows us to have control of which version is used in our project, as we can always go back to a previous version. In this case we would like to see that the project using version 1.0.0 still works, and that we get an update that there a new version. So we are going to save the new version, alongside the existing version.
!!BACK TO VISUAL STUDIO!!
If we manage the NuGet Packages for the solution, we now see that there is an installed version 1.0.0 and that there is an update, when it was published, and the new version 1.0.1. This can be automated, so that we have an overview of the used versions. In this case, we can simply click ‘Update’ to retrieve the new version.
To be able to communicate with the Service Bus, we need several references, and by using the NuGet Packaging solution, we can ensure that we always have the version we need.
There you go, versioning strategy in place….governance fase 1 completed…get the TFS guy and set up the rest….
Some tips:
- The NuGet packages can provide significant added value to components which are used in project, however not always during development
- Conditional dependencies can be usefull
- Added source/content such as sample can also be delivered using Project Templates which are problably more helpfull
HTH,
Sander
Comments