Matt Ward

NuGet Support in Visual Studio for Mac 17.4

Changes

  • NuGet 6.3.1 support
  • Fixed multiple NuGet.Config load error dialogs
  • Fixed wrong NuGet.Config file path when failing to save file

More information on all the new features and changes in Visual Studio for Mac 17.4 can be found in the release notes.

NuGet 6.3.1 support

NuGet 6.3.1.1 is now included with Visual Studio for Mac 17.4.

Fixed multiple NuGet.Config load error dialogs

On opening or creating a new solution, and the global NuGet.Config file was invalid, two error dialogs would be displayed indicating a problem with the NuGet.Config file.

Now the error dialog is only displayed once when opening a solution.

Fixed wrong NuGet.Config file path when failing to save file

When there is an error saving the NuGet.Config the error message shows the path to the file. However this was using SpecialFolder.ApplicationData instead of the correct path ~/.nuget/NuGet/NuGet.config.

NuGet Support in Visual Studio for Mac 17.3

Changes

  • NuGet 6.2.1 support
  • Improved NuGet restore support for a solution containing classic and SDK style projects
    • Fixed unable to find WorkloadAutoImportPropsLocator SDK restore error with classic and SDK style projects
    • Fixed invalid framework identifer restore error with classic and SDK style projects
    • Fixed error restoring Mapsui.Mac.sln

More information on all the new features and changes in Visual Studio for Mac 17.3 can be found in the release notes.

NuGet 6.2.1 support

NuGet 6.2.1.2 is now included with Visual Studio for Mac 17.3.

Improved NuGet restore support for a solution containing classic and SDK style projects

NuGet restore has been improved for a solution contains a mix of classic (non SDK style projects) and SDK style projects. Problems can occur in this case because classic projects require MSBuild on Mono, whilst SDK style projects typically require .NET MSBuild.

The following sections contain information about the individual problems that have been fixed in Visual Studio for Mac 17.3

Fixed unable to find WorkloadAutoImportPropsLocator SDK restore error with classic and SDK style projects

If a solution contained a .NET 6 project, and a .NET 4.7.2 SDK style project, and Building with MSBuild on Mono was unchecked in Solution Properties – Build – General, the restore would fail with an error when only .NET 6.0.300 SDK was installed:

Unable to find SDK 'Microsoft.NET.SDK.WorkloadAutoImportPropsLocator'

To fix this Visual Studio for Mac now does not load referenced projects when getting restore information for a specific project using its MSBuild host. When all projects were loaded by the MSBuild host, the project load would fail since the MSBuildSDKsPath was not defined because .NET SDK was being used since none supported using MSBuild on Mono.

Fixed invalid framework identifer restore error with classic and SDK style projects

If a solution contained a non-SDK style project then MSBuild on mono was always used to restore if the solution contained more than 10 projects. This prevented some solutions from being restored if they contained mix of .NET 6.0 projects and classic non-SDK style projects, and had a global.json that pinned the .NET SDK to 6.0.300. The restore would fail when MSBuild on mono was used with an error about an invalid framework identifier.

1
2
3
4
5
6
7
MonoBundle/MSBuild/Current/bin/NuGet.targets(162,5):
error MSB4018: The "WriteRestoreGraphTask" task failed unexpectedly.
error MSB4018: NuGet.Frameworks.FrameworkException: Invalid framework identifier ''.
error MSB4018:   at NuGet.Frameworks.NuGetFramework.GetShortFolderName (NuGet.Frameworks.IFrameworkNameProvider mappings)
error MSB4018:   at NuGet.Frameworks.NuGetFramework.GetShortFolderName ()
error MSB4018:   at NuGet.ProjectModel.PackageSpecWriter.WriteMetadataTargetFrameworks (NuGet.RuntimeModel.IObjectWriter writer, NuGet.ProjectModel.ProjectRestoreMetadata msbuildMetadata)
error MSB4018:   at NuGet.ProjectModel.PackageSpecWriter.SetMSBuildMetadata (NuGet.RuntimeModel.IObjectWriter writer, NuGet.ProjectModel.PackageSpec packageSpec)

MSBuild on mono does not support .NET 6.0.300 sdk and, because of the global.json file, Visual Studio for Mac did not downgrade to an older supported .NET SDK which then caused the restore to fail since it cannot resolve the target framework.

To avoid this problem the restore now checks the Build with MSBuild on Mono setting, in Solution Properties – Build – General, and if unchecked the restore will succeed.

Fixed error restoring Mapsui.Mac.sln

The Mapsui.Mac.sln from https://github.com/Mapsui/Mapsui would fail to restore with following error when Build with MSBuild on Mono was disabled in Solution Properties:

error MSB4019: The imported project "/usr/local/share/dotnet/sdk/6.0.300/Xamarin/iOS/Xamarin.iOS.CSharp.targets" was not found.

The Mapsui.Mac.sln contains .NET 6.0 maui and some classic Xamarin projects. It is not possible to restore these all projects with either MSBuild on Mono or .NET’s MSBuild. The solution also contains more than 10 projects which results in Visual Studio for Mac running MSBuild directly out of process instead of using its MSBuild host. Since neither MSBuild on mono, nor .NET’s MSBuild can restore the solution, this would fail.

To fix this Visual Studio for Mac no longer runs MSBuild directly out of process to run the restore when a solution contains a mix of project types that require different MSBuild’s. Instead Visual Studio for Mac runs the restore with its MSBuild hosts, which support both MSBuild on Mono and .NET’s MSBuild. Each project then has the GenerateRestoreGraphFile MSBuild target run separately using the correct MSBuild. This requires the Build with MSBuild on Mono option to be unchecked, and allows the Mapsui.Mac.sln to be restored.

NuGet Support in Visual Studio for Mac 17.0

Changes

  • NuGet 6.0 support
  • NuGet.Config file location changed
  • NuGet package source passwords now stored in the Keychain
  • Improved clear text password handling for NuGet package sources
  • Support NuGet restore with .NET MSBuild and MSBuild on mono
  • NuGetizer support removed

More information on all the new features and changes in Visual Studio for Mac 17.0 can be found in the release notes.

NuGet 6.0 support

NuGet 6.0.0.262 is now included with Visual Studio for Mac 17.0.

NuGet.Config file location changed

Visual Studio for Mac 17.0 now runs on .NET 6 instead of Mono. This means the NuGet.Config file location has changed.

Old NuGet.Config file location used by Visual Studio for Mac 8.10 and mono:

~/.config/NuGet/NuGet.Config

New NuGet.Config file location used by Visual Studio for Mac 17.0 and the dotnet command line interface:

~/.nuget/NuGet/NuGet.Config

NuGet package source passwords now stored in the Keychain

The dotnet command line interface does not support encrypting NuGet package source passwords.

This is because the ProtectedData class used by NuGet to encrypt and decrypt the package source passwords is not available for .NET. The ProtectedData class is available for mono and .NET Framework v4.

One workaround is to store the passwords in clear text in the NuGet.Config file.

This can be done via dotnet nuget add source.

dotnet nuget add source https://someServer/myTeam -n myTeam -u myUsername -p myPassword --store-password-in-clear-text

Or by editing the ~/.nuget/NuGet/NuGet.Config file.

1
2
3
4
5
6
7
8
9
10
11
<configuration>
  <packageSources>
    <add key="myTeam" value="https://someServer/myTeam" />
  </packageSources>
  <packageSourceCredentials>
    <myTeam>
        <add key="Username" value="myUsername" />
        <add key="ClearTextPassword" value="myPassword" />
      </myTeam>
  </packageSourceCredentials>
</configuration>

Now that Visual Studio for Mac 17.0 runs on .NET 6 it is also affected by NuGet not being able to store encrypted passwords in the NuGet.Config file.

If a NuGet package source with a password is created in Visual Studio for Mac 17.0 the password will be stored in the Keychain rather than using a clear text password.

Add NuGet package source with password in preferences

Package source password saved in Keychain

Improved clear text password handling for NuGet package sources

In Visual Studio for Mac 8.10 when the package sources where saved in Preferences – NuGet – Sources any clear text passwords were encrypted in the saved NuGet.Config file.

In Visual Studio for Mac 17.0 package sources that use clear text passwords will not have their passwords encrypted in the NuGet.Config file.

Support NuGet restore with .NET MSBuild and MSBuild on mono

In order to support classic Xamarin projects, and projects that require mono, Visual Studio for Mac 17.0 supports MSBuild on Mono and dotnet msbuild.

If any project in a solution has mono as a target runtime then the solution is restored with MSBuild on mono. If all projects target the dotnet runtime then dotnet’s MSBuild will be used. This prevents the restore failing for classic Android and iOS projects since dotnet’s MSBuild cannot resolve the Xamarin MSBuild targets files, causing errors similar to the following:

error MSB4019: The imported project "/usr/local/share/dotnet/sdk/6.0.101/Xamarin/Android/Xamarin.Android.CSharp.targets" was not found.
Confirm that the expression in the Import declaration

If the solution is configured to build with MSBuild on Mono then large solutions are restored with MSBuild on Mono.

NuGetizer support removed

Integrated support for NuGetizer has been removed from Visual Studio for Mac 17.0. This is because the NuGetizer project is no longer being maintained.

dotnet pack can be used as an alternative.

NuGet Support in Visual Studio for Mac 8.10

Changes

  • Manage NuGet Packages dialog now uses native macOS UI
  • NuGet 5.9 support
  • Support disabling NuGet restore in NuGet.Config
  • Fixed automatic restore may still run if disabled in preferences
  • Fixed $(SolutionDir) not defined when restoring large solutio

More information on all the new features and changes in Visual Studio for Mac 8.10 can be found in the release notes.

Manage NuGet Packages dialog now uses native macOS UI

The Manage NuGet Packages dialog is now displayed using Xamarin.Mac.

Manage NuGet packages dialog

Previously the dialog was displayed using GTK#.

The following UI changes were also made:

  • Tabs are now used for each page
    • Previously a link was used to select a page
  • Search has moved to the same line as the window title
  • NuGet package sources have moved to the bottom of the dialog
  • Show pre-release packages check box has been renamed to Include prereleases
  • Hyperlinks that were used to view the license and project pages have been replaced with buttons
  • Close button has been removed

NuGet 5.9 support

NuGet 5.9.0.7134 is now included with Visual Studio for Mac 8.10.

Support disabling NuGet restore in NuGet.Config

A NuGet.Config file can disable package restore via a enabled setting, as shown below.

<configuration>
  <packageRestore>
    <add key="enabled" value="false" />
  </packageRestore>
</configuration>

This is now supported in Visual Studio for Mac and will disable automatic package restore overriding the setting in Preferences.

Fixed automatic restore may still run if disabled in preferences

Certain actions in SDK style projects, such as saving a project file in the editor, and adding a reference to another project, would run a package restore even if automatic restore was disabled in preferences.

Now, if automatic restore is disabled in preferences, no automatic restore will be run. Restores can still be run from the main menu and the Solution window.

Fixed $(SolutionDir) not defined when restoring large solution

When a solution contains more than 10 projects then MSBuild is used directly to restore the projects. If a project was using the SolutionDir property to import an MSBuild file then this would fail since SolutionDir is not defined because no solution was being passed to MSBuild.

One way to reproduce this was to have an SDK style project that does not define a TargetFramework itself but conditionally imports a project, using a path that includes the $(SolutionDir) property, that defines the TargetFramework. The NuGet restore would fail with an error about an invalid framework identifier.

error MSB4018: The “WriteRestoreGraphTask” task failed unexpectedly.
error MSB4018: NuGet.Frameworks.FrameworkException: Invalid
    framework identifier ‘’.

To fix this Visual Studio for Mac now runs the GenerateRestoreGraphFile target specifying the solution, not just the projects. This allows MSBuild to define the $(SolutionDir) property.

NuGet Support in Visual Studio for Mac 8.9

Changes

  • Fixed implicit NuGet packages being updated

More information on all the new features and changes in Visual Studio for Mac 8.9 can be found in the release notes.

Fixed implicit NuGet packages being updated

Updating all NuGet packages, from the Solution window, in a .NET Core 2.1 project would fail with an error.

1
Package Microsoft.NETCore.App 2.2.8 is not compatible with netcoreapp2.1 (.NETCoreApp,Version=v2.1). Package Microsoft NETCore.App 2.2.8 supports: netcoreapp2.2 (.NETCoreApp,Version=v2.2)

The problem was that implicitly defined (or auto-referenced) NuGet package references were being updated when they should be ignored since they cannot be updated. Now Visual Studio for Mac does not attempt to update implicitly defined NuGet package references.

NuGet Support in Visual Studio for Mac 8.8

Features

  • Azure DevOps NuGet package source authentication with signed in account
  • NuGet 5.8 support

More information on all the new features and changes in Visual Studio for Mac 8.8 can be found in the release notes.

Azure DevOps NuGet package source authentication with signed in account

Visual Studio for Mac now has integrated support for accessing Azure DevOps NuGet package sources using the account signed into the IDE without requiring a personal access token (PAT).

Azure DevOps NuGet package source prompting for sign in in Visual Studio for Mac

If you are not signed in then the account sign in dialog will be opened when an Azure DevOps NuGet package source is accessed that requires authentication.

NuGet 5.8 support

NuGet 5.8.0.6860 is now included with Visual Studio for Mac 8.8.

NuGet Support in Visual Studio for Mac 8.7

Changes

  • NuGet 5.7 support
  • .NET Core 3.1.401 support
    • Supported in Visual Studio for Mac 8.7.1
  • .NET 5 preview 6 and 7 support
  • Fixed tests not discovered by VS Test adapter for imported NuGet packages
  • Fixed dependent projects not being restored after project reference added
  • Fixed SDK resolution errors with vstool

More information on all the new features and changes in Visual Studio for Mac 8.7 can be found in the release notes.

NuGet 5.7 support

NuGet 5.7.0.6702 is now included with Visual Studio for Mac 8.7.

.NET Core 3.1.401 support

The NuGet packages shown in the Solution window in the Dependencies folder would not show child dependencies when .NET Core 3.1.401 SDK was installed.

The ResolvePackageDependenciesDesignTime MSBuild target’s behaviour changed in .NET Core 3.1.401 to no longer return the full set of NuGet dependencies and now returns only the top level depdnencies.

The logic that was originally in this design time MSBuild target has been added to Visual Studio for Mac so the full tree structure of the NuGet package dependencies can be displayed in the Solution window.

Note that .NET Core 3.1.401 is supported in Visual Studio for Mac 8.7.1

.NET 5 preview 6 and 7 support

Restoring an ASP.Core project targeting .NET 5 would fail with an error when the ResolvePackageAssets task was run.

1
2
3
4
/usr/local/share/dotnet/sdk/5.0.100-preview.6.20304.10/Sdks/Microsoft.NET.Sdk/targets/Microsoft.PackageDependencyResolution.targets(5,5):
Error MSB4018: The "ResolvePackageAssets" task failed unexpectedly.
System.MissingFieldException: Field not found: string NuGet.ProjectModel.LockFileItem.AliasesProperty Due to: Could not find field in class
  at Microsoft.NET.Build.Tasks.ResolvePackageAssets+CacheWriter.WriteItems[T] (NuGet.ProjectModel.LockFileTarget target, System.Func`2[T,TResult] getAssets, System.Func`2[T,TResult] filter, System.Action`2[T1,T2] writeMetadata) [0x0008e] in <9d95d6a4081d41288f54edb04b336893>:0 

NuGet 5.7 introduced a new AliasesProperty to the LockFileItem class. MSBuild in Mono 6.12 uses NuGet 5.6 build tasks which do not support this new property causing the NuGet restore to fail.

Visual Studio for Mac now includes version 5.7 of the NuGet.Build.Tasks assembly and associated MSBuild targets. These files are copied to Visual Studio for Mac’s MSBuild host when it is created and replace these files originally copied from Mono’s MSBuild.

Note that .NET 5 preview 8 is not supported by Visual Studio for Mac 8.7 but is supported in by Visual Studio for Mac 8.8.

Bug Fixes

Fixed tests not discovered by VS Test adapter for imported NuGet packages

Test adapter NuGet PackageReferences defined in a Directory.Build.props file were not considered by Visual Studio for Mac. This resulted in the Unit Tests window not showing any unit tests. Only when the test adapter PackageReferences were in the main project file would tests be discovered.

Fixed dependent projects not being restored after project reference added

For a new Blazor Web Assembly project (with ASP.NET Core hosted) adding a new Razor library project, and having the Client project reference the library project, would result in build warnings incorrectly displayed for the Server project due to conflicts between the NuGet packages used by the Client because of the new Razor library project reference.

MSB3277: Found conflicts between different versions of "Microsoft.AspNetCore.Components" 

Running a restore for the solution would fix this build warning.

With two SDK style projects referencing each other as follows:

ProjectB –> ProjectA

If a new SDK project was added, and ProjectA referenced it, the restore would only occur for ProjectA not ProjectB. This would mean the Lib project was not available to ProjectB until a restore was run for ProjectB or for the solution. Depending on the NuGet packages used this could result in build warnings.

To fix this all the projects, that reference the project which is modified due to the new project reference, are now restored.

Fixed SDK resolution errors with vstool

vstool is an application that is included with Visual Studio for Mac and provides a way to run some IDE features from the command line. When one of these features used a project that required an SDK provided by NuGet it would fail to resolve and download that SDK.

For example, running the following would fail to resolve SDKs provided by NuGet packages.

vstool gettext-update --sort -f:Main.sln

An error would be reported:

ERROR: Unable to find SDK 'Xamarin.Mac.Sdk'

The NuGet SDK resolver would fail to find the NuGet.Credentials.dll causing vstool to fail.

FileNotFoundException Could not load file or assembly 'NuGet.Credentials, Version=5.6.0.5.

To fix this the NuGet.Credentials.dll is pre-loaded by Visual Studio for Mac so it is available in the AppDomain when vstool is run.

NuGet Support in Visual Studio for Mac 8.6

Changes

  • NuGet 5.6 support
  • Fixed escape key not closing Manage NuGet Packages dialog

More information on all the new features and changes in Visual Studio for Mac 8.6 can be found in the release notes.

NuGet 5.6 support

NuGet 5.6.0.6591 is now included with Visual Studio for Mac 8.6.

Bug Fixes

Fixed escape key not closing Manage NuGet Packages dialog

When the search text box had focus pressing the escape key would not close the Manage NuGet Packages dialog as it did in previous versions. A change to fix accessibility of the search text box broke the original behaviour of the dialog.

Manage Global NuGet Folders for Visual Studio for Mac

NuGet supports configuring the location of the following global folders:

  • Global NuGet packages cache
    • ~/.nuget/packages
  • HTTP cache
    • ~/.local/share/NuGet/v3-cache
  • NuGet plugins ache
    • ~/.local/share/NuGet/plugins-cache

The above folder locations can be found by running the following command from Terminal.

nuget locals all -list

Here we will take a look at how these can be configured for use by Visual Studio for Mac 8.5 when running on macOS Catalina.

Configuring Global Packages Folder Only

If only the global packages folder needs to be configured then the simplest way is to define the globalPackagesFolder folder in the ~/.config/NuGet/NuGet.Config file.

1
2
3
4
5
6
7
8
<configuration>
  <config>
    <add key="globalPackagesFolder" value="/Volumes/YourDrive/NuGet/.nuget/packages" />
  </config>
  <packageSources>
    <add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
  </packageSources>
</configuration>

Visual Studio for Mac will need to be restarted before it picks up any changes to the NuGet.Config file.

Configuring Global Folders with Environment Variables

Visual Studio for Mac will not use environment variables defined in the Bash profile ~/.bash_profile or the Zsh profile ~/.zprofile unless Visual Studio for Mac is run from the Terminal.

open -n "/Applications/Visual Studio.app"

When Visual Studio for Mac is run from the Dock, or from LaunchPad, it does not inherit these environment variables.

Let us take a look at how we can define these NuGet environment variables so that Visual Studio for Mac will use them without having to launch it from the Terminal.

Create the file ~/Library/LaunchAgents/environment.plist containing the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version=“1.0” encoding=“UTF-8”?>
<!DOCTYPE plist PUBLIC “-//Apple//DTD PLIST 1.0//EN” “https://www.apple.com/DTDs/PropertyList-1.0.dtd”>
<plist version=“1.0”>
<dict>
<key>Label</key>
<string>my.startup</string>
<key>ProgramArguments</key>
<array>
<string>sh</string>
<string>-c</string>
<string>launchctl setenv NUGET_PACKAGES /Volumes/YourDrive/NuGet/.nuget/packages
launchctl setenv NUGET_HTTP_CACHE_PATH /Volumes/YourDrive/NuGet/.nuget/v3-cache
launchctl setenv NUGET_PLUGINS_CACHE_PATH /Volumes/YourDrive/NuGet/.nuget/plugins-cache</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>

Replace the NuGet paths /Volumes/YourDrive/NuGet/ defined above as required.

Restart macOS to have this Launch Agent run.

After restarting you can check the environment variables are being used by NuGet by using the command line:

nuget locals all -list

Now when Visual Studio for Mac is launched from the Dock, or from LaunchPad, it will use these custom NuGet folders.

More Information

launchctl setenv defines environment variables globally so they are available to all macOS applications launched with launchd.

NuGet Support in Visual Studio for Mac 8.5

Changes

  • NuGet 5.4 support
  • Support Plugin-based NuGet Credential Providers
  • Fixed requests bypassing the native macOS HTTP handler

More information on all the new features and changes in Visual Studio for Mac 8.5 can be found in the release notes.

NuGet 5.4 support

NuGet 5.4.0.6315 is now included with Visual Studio for Mac 8.5.

Support Plugin-based NuGet Credential Providers

NuGet credential provider plugins are now supported by Visual Studio for Mac.

Plugins are self-contained executables which provide credentials for NuGet package sources. One example is the Azure Artifacts Credential Provider which Visual Studio for Mac can now use whilst it does not have integrated support for accessing packages sources available from Azure DevOps.

Bug Fixes

Fixed HTTP requests bypassing the native macOS HTTP handler

Restoring or installing a NuGet package into a project that uses PackageReferences was bypassing the native macOS HTTP handler.

This was due to NuGet’s CachingSourceProvider creating its own set of INuGetResourceProviders when it creates a set of new SourceRepository instances. This resulted in the default HttpSourceResourceProvider being used, instead of the custom one provided by Visual Studio for Mac. The default HttpSourceResourceProvider uses Mono’s HttpClientHandler not the native HTTP Client handle NSUrlSessionHandler provided by Xamarin.Mac. This would happen when the Nuget package was was downloaded.

NuGet 5.4 now supports defining custom INuGetResourceProvider factory that is used globally. This is now used by Visual Studio for Mac so all HTTP requests use the native macOS HTTP handler NSUrlSessionHandler.