How to use the same version of Orchard Core NuGet packages in every project across my solution? - Orchard Core Nuggets

Gábor Domonkos's avatar
Update, Orchard Core Nuggets, Theme, Module

You have your own ASP.NET Core project that using Orchard Core NuGet packages, but every time when you update them you have to do it one-by-one across the whole solution? Wouldn't it be easier to just update the package versions in one place? Then you may need to have a Directory.Build.targets file to define the versions!

MSBuild projects that use the standard build process (importing Microsoft.Common.props and Microsoft.Common.targets) have several extensibility hooks that you can use to customize your build process. Directory.Build.targets is imported from Microsoft.Common.targets after importing .targets files from NuGet packages. So, it can override properties and targets defined in most of the build logic, but sometimes you may need to customize the project file after the final import. Without going into too much detail, Directory.Build.targets can be used to provide customizations to project files located under a certain directory, this means that if you create such a file at the root of your solution, it would normally be able to customize all the .csproj files in your solution as they would exist in the child directories. Let's see a small example!

Imagine you have an ASP.NET Core web application with a MyAwesomeWebApp.Web.csproj file. If you referenced Orchard Core in this project, your file contains a similar section:

<ItemGroup>
<PackageReference Include="OrchardCore.Logging.NLog" Version="1.0.0-rc1-10106" />
<PackageReference Include="OrchardCore.Application.Cms.Targets" Version="1.0.0-rc1-10106" />
</ItemGroup>

I assume you also have some custom modules and themes in your solution. The .csproj file of your module (MyAwesomeModule.csproj) could contain a section like:

<ItemGroup>
<PackageReference Include="OrchardCore.ResourceManagement" Version="1.0.0-rc1-10106" />
<PackageReference Include="OrchardCore.DisplayManagement" Version="1.0.0-rc1-10106" />
<PackageReference Include="OrchardCore.Module.Targets" Version="1.0.0-rc1-10106" />
</ItemGroup>

where the OrchardCore.Module.Targets is mandatory if it is a module. Imagine that your theme (MyAwesomeTheme.csproj of course) has the following:

<ItemGroup>
<PackageReference Include="OrchardCore.Theme.Targets" Version="1.0.0-rc1-10106" />
<PackageReference Include="OrchardCore.DisplayManagement" Version="1.0.0-rc1-10106" />
<PackageReference Include="OrchardCore.ResourceManagement" Version="1.0.0-rc1-10106" />
</ItemGroup>

You can see that we referenced OrchardCore.DisplayManagement and OrchardCore.ResourceManagement packages multiple times. If there will be a new release of Orchard Core we have to make sure that we use the same versions of every package across the whole solution. And if we have several projects we have to change the version numbers in every project one by one. To solve this issue add a Directory.Build.targets file at the root of your solution. We set the version in this file and specify how each <PackageReference /> should be updated by MSBuild. Note that here we have to use Update instead of Include.

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<!-- Implicit Package References -->
<PackageReference Update="OrchardCore.Application.Cms.Targets" Version="1.0.0-rc1-10106" />
<PackageReference Update="OrchardCore.DisplayManagement" Version="1.0.0-rc1-10106" />
<PackageReference Update="OrchardCore.Logging.NLog" Version="1.0.0-rc1-10106" />
<PackageReference Update="OrchardCore.Module.Targets" Version="1.0.0-rc1-10106" />
<PackageReference Update="OrchardCore.ResourceManagement" Version="1.0.0-rc1-10106" />
<PackageReference Update="OrchardCore.Theme.Targets" Version="1.0.0-rc1-10106" />
</ItemGroup>
</Project>

Now let's rewrite the content of all the .csproj files and see the result of the MyAwesomeTheme.csproj for an example! The Include attribute specifies the package ID and the Version attribute specifies the version of the package to restore. But as you can see here the only change we did is to remove the Version attribute.

<ItemGroup>
<PackageReference Include="OrchardCore.Theme.Targets" />
<PackageReference Include="OrchardCore.DisplayManagement" />
<PackageReference Include="OrchardCore.ResourceManagement" />
</ItemGroup>

Now nothing will stop you from easily update the Orchard Core NuGet packages of your ASP.NET Core website!

Did you like this post? It's part of our Orchard Core Nuggets series where we answer common Orchard questions, be it about user-facing features or developer-level issues. Check out the other posts for more such bite-sized Orchard Core tips and let us know if you have another question!

4 Comments

  • Robert said Reply

    I had a couple of questions:

    1) Do you have to manually insert the Version numbers in the Directory.Build.targets file? Or is there a way to automate manually editing the file?

    2) I save my modules/themes in folders separate from the solution, then create solution folders in the solution and add the .csproj files to the ~/Modules and /~Themes solution folders. Will placing the Directory.Build.targets at the root of the solution still work in my case since my module and theme projects live outside the physical folder structure of the solution?

    Thanks.

  • Zoltán Lehóczky said Reply

    1. I think you have to do this manually. However, you only have to do this whole setup once.
    2. This will only work if the Directory.Build.targets is in a common root directory of both folders, see the docs: https://docs.microsoft.com/en-us/visualstudio/msbuild/customize-your-build?view=vs-2019#search-scope

  • OmDev said Reply

    Hi,
    Can I use GeneratePathProperty along with the Update attribute in Directory.build.props? If So, how should I add reference to that package.

    Thanks.

    • Zoltán Lehóczky said Reply

      I think so but why would you use GeneratePathProperty with Orchard packages?

Add a Comment