ASP.NET Core – Migrating to MSBuild

Migrating to MSBuild Header

This post continues the theme of exploring project structures for Angular and ASP.NET Core applications. The ASP.NET Core framework is in the midst of a transition to a new MSBuild-based project configuration. While there is material to help you start with MSBuild from scratch, many if not most of the published ASP.NET Core examples use the JSON-based project system. By learning how to migrate an existing application to the new MSBuild system, you can leverage the existing code and learn the new system – it's the best of both worlds.

There have been a couple high-profile posts recently around migrating from project.json to MSBuild from Nate McMaster and Scott Hanselman. This post is an overview of the MSBuild migration to help put these recent conversations in context. Why is Microsoft doing it? How can you migrate easily? The post covers these topics and includes links and tips to help with your own migration.

Moving to MSBuild

MSBuild, also known as the Microsoft Build Engine, is an XML-based project system for processing and building software. It's designed specifically for the .NET Framework and Visual Studio but is capable of processing other types of software and frameworks.

When .NET Core was introduced, ASP.NET Core was one of the first application targets available. To make the platform more attractive to open-source web developers, ASP.NET Core adopted a JSON-based project system defined in a project.json file. Looking at Node.js, everything is JSON-based as opposed to XML so this was a sensible design choice to attract new developers.

Prior to .NET Core, .NET projects were all based on MSBuild (or an MSBuild-like system). Typically, the developer didn't have to worry about this. Most projects started from built-in Visual Studio templates and Visual Studio automatically handled updates to project files (.csproj, .vbproj, etc.). Occassionally you had to resolve merge conflicts in the project file because it contained a list of each file in the project which was represented by its own XML node. If two developers independently modified the list of files in a project, this could result in a merge conflict but these issues were typically easy to resolve.

After .NET Core debuted, it quickly positioned itself as the framework for all .NET-based application targets including Universal Windows Platform (UWP) and Xamarin. Non-web developers didn't see the project.json file as an upgrade. They were used to using MSBuild and wanted to continue to use it. So for the greater good of the existing .NET community, Microsoft announced they are going to re-standardize on MSBuild as the build system for .NET Core.

Microsoft has added new capabilities to MSBuild. It went cross platform in 2015 and Microsoft announced enhancements for the build engine. Read more about them in Microsoft's blog post. The first MSBuild-based SDK 'alpha' was released in November, 2016.

New CLI Command, "dotnet migrate"

To aid in the transition to the MSBuild project system, the dotnet command-line interface (CLI) now includes the dotnet migrate command. This command takes a project using JSON-based configuration and converts it to a .csproj file. The command is available in dotnet CLI version 1.0.0-preview3-004056 or later.

The utility carries out several actions. First of all, it takes your existing project.json, global.json, and .xproj files and moves them to a folder named backup. If you are using source control, you can safely delete this folder.

The second thing the utility does is generate a new .csproj file from the contents of the project.json file. Before you delete the old file, consider taking a look at how the project.json and .csproj files compare.

Most of the contents of the project.json convert to PackageReference elements:

<PackageReference Include="Microsoft.AspNetCore.Mvc">

There is a slight difference for tooling dependencies. They are added as DotNetCliToolReference elements.

<DotNetCliToolReference Include="Microsoft.DotNet.Watcher.Tools">

For executing npm scripts in your ASP.NET build to pre-process your TypeScript or Sass code, the new MSBuild script looks like this:

<Target Name="PrepublishScript" BeforeTargets="Publish">
    <Exec Command="npm install" />
    <Exec Command="npm run tsc" />

If you are distraught over the project file moving from a concise JSON schema to a specialized XML-based schema like MSBuild, don't get too upset yet. First, you can continue to use project.json in the short-term by including a global.json file in your project. In the long term, Microsoft has stated they are looking at how to generate MSBuild-based configuration so that ideally you don't have to write it yourself. The dotnet migrate command is an important first step to this commitment. However, as an ASP.NET developer you will most-likely benefit from having a basic understanding of MSBuild.


There is a great post discussing the details of migrating from project.json to MSBuild in Nate McMaster's conversion guide. Also, take a look at the MSBuild documentation to gain a general understanding of the build system.

One important detail to note is that your global.json file must reference a version of the CLI that supports dotnet migrate (1.0.0-preview3-004056 or later). If you see the error No executable found matching command "dotnet-migrate", look to update the sdk in your global.json file.

This last tip is anecdotal. It did cost me time so hopefully describing it may help someone else. While not completely sure the reason yet, there was an issue executing commands, in this case npm scripts, before or after the "Publish" target. If you experience this issue, try using a different target such as Build.

<Target Name="NpmCommands" AfterTargets="Build">
    <Exec Command="npm install" />
    <Exec Command="npm run tsc" />

Finally, look for more resources from Microsoft. They are working to deliver an "RTM quality" version of the SDK in early 2017 so expect many updates to documentation and templates leading up to the release.


The dotnet migrate tool is very helpful. I have found works well at least with smaller projects. This is a considerable shift in configuration and Microsoft has done commendable work to automate the process. Looking forward, it will be interesting to see how they make this configuration easier for web developers coming new to the platform.

Have you been working with the MSBuild project system in .NET Core? What have been your pitfalls or successes? Please share in the comments.

One thought on “ASP.NET Core – Migrating to MSBuild”

Comments are closed.