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

贡献者指南