Offline Publishing ASP.NET Core Apps

It is my personal view that Microsoft designed .NET Core/ASP.NET Core with little offline experience in consideration, which makes it quite difficult for an enterprise with firewalls and proxies to fully embrace the technology. Thus, a post like this would discuss the investigation I just finished and hope it can help companies with external network access restrictions to set up their internal environment properly.

A Quick Review

So the following test case would be used,

  • Make a test web app, by running dotnet new mvc. Of course, this generates an ASP.NET Core MVC sample project.
  • On a machine with internet access, dotnet publish -r win-x64 will generate the x64 deployment binaries for Windows. You can use dotnet publish -r win-x64 --self-contained if you need self contained deployment.

Offline/Internal Network

To simulate the offline/internal network situation, I created an Azure virtual machine and enabled Hyper-V on it. Then I created a Hyper-V guest of Windows Server, where I can switch its network adapter to either external/internal easily.

I enabled external access, so that I can install .NET Core SDK (2.1.4 right now) and Visual Studio Code (with C# extension). Then of course, I have to disable external access to see what would break.

dotnet new mvc still works in this case, and give me the same test project. It is a little bit surprising, as I assume here it needs internet access to download the project template. So somehow Microsoft ships the default templates in the SDK.

dotnet restore or dotnet build does work, as .NET Core SDK has a fallback folder (will discuss later) with all needed packages cached.

However, dotnet publish -r win-x64 failed,

error: Unable to load the service index for source

as the default NuGet source setting contains which is not accessible at this moment.

Here I use dotnet new nuget to create a nuget.config file here to override the default sources,

<?xml version="1.0" encoding="utf-8"?>
        <clear />
        <add key="test" value=".\local" />
        <add key="fallback" value="C:\Program Files\dotnet\sdk\NuGetFallbackFolder" />

The local folder must be manually created, and we can leave it empty right now. You should now understand where the fallback folder is, right?

However, dotnet publish -r win-x64 would not work again for other errors, like

error NU1101: Unable to find package No packages exist with this id in source(s): fallback, test

Well, there are multiple packages missing as the errors indicate. So they must be manually downloaded from and put into the local folder.

Note that the package version number should be the latest, such as 2.0.5.

Note that there should be an easy way to locate the packages, which would be added here if I find out.

Well, another run of dotnet publish -r win-x64 won’t succeed yet,

error NU1605: Detected package downgrade: Microsoft.NETCore.DotNetHostResolver from 2.0.5 to 2.0.0. Reference the package directly from the project to select a different version.

The error message is misleading, as to fix it, you should change the command to dotnet publish /p:RuntimeFrameworkVersion=2.0.5 -r win-x64. This would force all packages to be matching .NET Core 2.0.5 release.

OK. You should now see no error and the deployment binaries are published.

To publish linux-x64 you can run dotnet publish /p:RuntimeFrameworkVersion=2.0.5 -r linux-x64 which should generate another list of missing packages, which you can later deploy to the local folder.

Note that local folder here can be replaced by the internal NuGet server your company uses. This internal server must support the necessary NuGet protocols, ideally matching NuGet 3.4 and above. You need to verify on your own, as there are so many NuGet server products out there.

Side Notes

A real world web app can be much more complicated, which might need more NuGet packages to be added to local folder. Right now I see no easy tooling to scan dependencies, except letting dotnet restore and dotnet publish show the errors. Anyway, the experience is not very pleasant, and hope future tooling can improve in this area.

© Lex Li. All rights reserved. The code included is licensed under CC BY 4.0 unless otherwise noted.

© - Lex Li. All rights reserved.

Using the Chirpy theme for Jekyll.

Last updated on June 24, 2024