NuGet/Home

NuGet.VisualStudio.Client throws NullReferenceException for projects without an assets file, preventing other VS extensions from adding their own nodes.

開放

#14,758 建立於 2026年2月12日

 (3 則留言) (0 個反應) (0 位負責人)HTML (292 個分叉)batch import
Functionality:VisualStudioUIPartner:Project-SystemPriority:2Product:VS.ClientType:Bughelp wanted

倉庫指標

星標
 (1,459 顆星)
PR 合併指標
 (平均合併 464天 23小時) (30 天內合併 1 個 PR)

描述

NuGet Product Used

Visual Studio Package Management UI

Product Version

Visual Studio 18.2.0

Worked before?

Has not worked previously.

Impact

Other

Repro Steps & Context

Ours is a custom project system based on CPS and we use the IRelation and IRelatableItem mechanism to inject custom nodes beneath specific kinds of project nodes in Solution Explorer. We see that when the NuGet client's AssetsFileTopLevelDependenciesCollectionSourceProvider does not find an assets file for the project, it still continues to return an attached collection source, but that source returns null items. That causes an NRE in AggregateCollection.AddSourceCollection, which prevents our sources from being able to supply our custom nodes on the project.

The following code "fixes" the issue for us, though it is clearly a hack given that we have to call an async method in a sync method. At the bottom of TryCreateCollectionSource within AssetsFileTopLevelDependenciesCollectionSourceProvider, the following code skips returning a source if there is no assets file:

           // *** BEGIN HACK ***
            // Only return a source if we can verify the project has an assets file
            // that might contain relevant data. Otherwise, we risk returning a source
            // with null Items, which causes NullReferenceException in AggregateCollection.AddSourceCollection.
            var configuredProject = unconfiguredProject.Services.ActiveConfiguredProjectProvider?.ActiveConfiguredProject;
            if (configuredProject != null)
            {
                var properties = configuredProject.Services.ProjectPropertiesProvider?.GetCommonProperties();
#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits
                var assetsFile = properties?.GetEvaluatedPropertyValueAsync("ProjectAssetsFile").GetAwaiter().GetResult();
#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits
                if (string.IsNullOrEmpty(assetsFile) || !File.Exists(assetsFile))
                {
                    containsCollectionSource = null;
                    return false;
                }
            }

           // *** END HACK ***

            containsCollectionSource = collectionSource;
            return true;

Verbose Logs

貢獻者指南