【发布时间】:2021-03-15 23:23:53
【问题描述】:
[最终更新 07.12.2020 23:50 --> 供所有寻求答案的人使用]
您可能正在添加一些具有 DEPENDENCIES .NET Core 3.1 字段的 nuget 包。例如 Serilog.AspNetCore 3.4.0。在这个例子中,您可以包含 Serilog.AspNetCore 3.2.0,因为它在 DEPENDENCIES 中只有 .NetStandard 2.0。在@Ogglas 答案中查看更多解释。
地球上没有足够的空间来问一个唯一的问题:“为什么,为什么是微软?”:) 该消息没有明确地将问题与解决方案相关联——这是我能做出的最轻巧的委婉说法: )
对我来说,Blazor 很有前途,但它仍然是一个测试版。而且不仅对我来说。令人兴奋的家伙声称,Blazor 有时会变幻无常。我不能再同意了;)我对此表示赞同。但我想它只有在 .NET 6.0 之后才会成为“现成产品”。
[原创主题]
这太令人沮丧了:)
我讨厌错误,因为我无法简单地互动并理解错误的来源。我知道,我很无知,如果我更加关注“blazor 应用程序是如何创建的”,我眨眼就明白了。
但现在只是令人沮丧。什么是?错误信息:
严重性代码描述项目文件行抑制状态 错误 NETSDK1082 没有可用于指定 RuntimeIdentifier 'browser-wasm' 的 Microsoft.AspNetCore.App 运行时包。 TestBlazorAppNoRuntimeError.Client C:\Program Files\dotnet\sdk\5.0.100\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets 387
真的,你能在这里解决什么问题?:D 嗯嗯。我知道 .NET 5 是一个“新事物”。我知道 Blazor 是一个“新事物”但真的吗?真的很容易“打破”;)(有一条消息什么都不说)
那我做了什么?
我是否创建了包含数十万个文件的非常复杂的项目?
否
我是否添加了数十万个 nuget 包。
否
只需创建 Blazor Webassembly 应用程序并将一个 nuget 包添加到共享(公共)库(仅供参考:IdentityServer4 包)。就这些了。如果你现在愿意的话,这个包确实导致了这个问题(因为我只是错误地发现了):
没有可用于指定 RuntimeIdentifier 'browser-wasm' 的 Microsoft.AspNetCore.App 运行时包。
真的,这里有很大的相关性:错误消息和正在添加的包之间(如果有人错过,这是讽刺:))
因此,如果您想重现它,请创建“Blazor Webassembly”:
我认为所选择的选项不会产生影响。但如果是这种情况 - 你可以看到我选择了什么选项。然后只需将 IdentityServer4 nuget 包添加到共享库:
https://www.nuget.org/packages/IdentityServer4/
就是这样
如果你太懒了 - 下载这个项目并自己检查:
我看到了数百个关于这条消息的 SOF 主题:
没有可用于指定 RuntimeIdentifier 'browser-wasm' 的 Microsoft.AspNetCore.App 运行时包。
但这些都不是那么容易复制的。
我为什么要创建这个主题?
因为我确实尝试实现(通过复制粘贴到我的解决方案)人们在 Blazor 样板中创建的内容: https://github.com/enkodellc/blazorboilerplate
一开始,我错误地添加了 Identity4 NuGet 而不是 Identity4.storage,这就是为什么我确实观察到了这种行为(这样的错误)并将这个包与这个错误相关联。当我从 Identity4 回滚到 Identity4.storage 时,一切都再次正确。但在那之后,我从这个存储库做了很多代码传输。一旦我结束了,现在,一切都在编译,但我又一次:
没有可用于指定 RuntimeIdentifier 'browser-wasm' 的 Microsoft.AspNetCore.App 运行时包。
这让我发疯了。也许您会有一些想法,如何找出导致此错误的原因(与之前的 Identity4 nuget 包导致它完全相同)
[更新 06.12.2020 12:30]
这里的问题更多:“为什么会发生以及如何定位导致问题的包”我知道我可以再次猜测导致此消息出现的原因。
我做了一点调查。此目标中显示此错误:
<ResolveRuntimePackAssets FrameworkReferences="@(FrameworkReference)"
ResolvedRuntimePacks="@(ResolvedRuntimePack)"
UnavailableRuntimePacks="@(UnavailableRuntimePack)"
SatelliteResourceLanguages="$(SatelliteResourceLanguages)"
DesignTimeBuild="$(DesignTimeBuild)">
<Output TaskParameter="RuntimePackAssets" ItemName="RuntimePackAsset" />
</ResolveRuntimePackAssets>
<ItemGroup>
<ReferenceCopyLocalPaths Include="@(RuntimePackAsset)"
Condition="'$(CopyLocalLockFileAssemblies)' == 'true' and ('$(SelfContained)' == 'true' or '%(RuntimePackAsset.RuntimePackAlwaysCopyLocal)' == 'true')" />
</ItemGroup>
所以我谷歌了 ResolveRuntimePackAssets 并找到了这个 repo 和这个文件:
foreach (var unavailableRuntimePack in UnavailableRuntimePacks)
{
if (frameworkReferenceNames.Contains(unavailableRuntimePack.ItemSpec))
{
// This is a runtime pack that should be used, but wasn't available for the specified RuntimeIdentifier
// NETSDK1082: There was no runtime pack for {0} available for the specified RuntimeIdentifier '{1}'.
Log.LogError(Strings.NoRuntimePackAvailable, unavailableRuntimePack.ItemSpec,
unavailableRuntimePack.GetMetadata(MetadataKeys.RuntimeIdentifier));
}
}
看起来是“导致”问题的代码(这需要在消息中写下有关:unavailableRuntimePack.ItemSpec 的信息 - 这会容易得多;))
所以现在唯一要做的就是找到填充此内容的内容:UnavailableRuntimePacks 属性。我没有看到任何代码这样做,所以它必须是一些反思。我找到了可能正在执行此操作的代码:
还有这个方法:
private void ProcessRuntimeIdentifier(
string runtimeIdentifier,
KnownRuntimePack selectedRuntimePack,
string runtimePackVersion,
List<string> additionalFrameworkReferencesForRuntimePack,
HashSet<string> unrecognizedRuntimeIdentifiers,
List<ITaskItem> unavailableRuntimePacks,
List<ITaskItem> runtimePacks,
List<ITaskItem> packagesToDownload,
string isTrimmable,
bool addToPackageDownload)
{
var runtimeGraph = new RuntimeGraphCache(this).GetRuntimeGraph(RuntimeGraphPath);
var knownFrameworkReferenceRuntimePackRuntimeIdentifiers = selectedRuntimePack.RuntimePackRuntimeIdentifiers.Split(';');
string runtimePackRuntimeIdentifier = NuGetUtils.GetBestMatchingRid(
runtimeGraph,
runtimeIdentifier,
knownFrameworkReferenceRuntimePackRuntimeIdentifiers,
out bool wasInGraph);
if (runtimePackRuntimeIdentifier == null)
{
if (wasInGraph)
{
// Report this as an error later, if necessary. This is because we try to download
// all available runtime packs in case there is a transitive reference to a shared
// framework we don't directly reference. But we don't want to immediately error out
// here if a runtime pack that we might not need to reference isn't available for the
// targeted RID (e.g. Microsoft.WindowsDesktop.App for a linux RID).
var unavailableRuntimePack = new TaskItem(selectedRuntimePack.Name);
unavailableRuntimePack.SetMetadata(MetadataKeys.RuntimeIdentifier, runtimeIdentifier);
unavailableRuntimePacks.Add(unavailableRuntimePack);
}
else if (!unrecognizedRuntimeIdentifiers.Contains(runtimeIdentifier))
{
// NETSDK1083: The specified RuntimeIdentifier '{0}' is not recognized.
Log.LogError(Strings.RuntimeIdentifierNotRecognized, runtimeIdentifier);
unrecognizedRuntimeIdentifiers.Add(runtimeIdentifier);
}
}
else if (addToPackageDownload)
{
foreach (var runtimePackNamePattern in selectedRuntimePack.RuntimePackNamePatterns.Split(';'))
{
string runtimePackName = runtimePackNamePattern.Replace("**RID**", runtimePackRuntimeIdentifier);
if (runtimePacks != null)
{
TaskItem runtimePackItem = new TaskItem(runtimePackName);
runtimePackItem.SetMetadata(MetadataKeys.NuGetPackageId, runtimePackName);
runtimePackItem.SetMetadata(MetadataKeys.NuGetPackageVersion, runtimePackVersion);
runtimePackItem.SetMetadata(MetadataKeys.FrameworkName, selectedRuntimePack.Name);
runtimePackItem.SetMetadata(MetadataKeys.RuntimeIdentifier, runtimePackRuntimeIdentifier);
runtimePackItem.SetMetadata(MetadataKeys.IsTrimmable, isTrimmable);
if (selectedRuntimePack.RuntimePackAlwaysCopyLocal)
{
runtimePackItem.SetMetadata(MetadataKeys.RuntimePackAlwaysCopyLocal, "true");
}
if (additionalFrameworkReferencesForRuntimePack != null)
{
runtimePackItem.SetMetadata(MetadataKeys.AdditionalFrameworkReferences, string.Join(";", additionalFrameworkReferencesForRuntimePack));
}
runtimePacks.Add(runtimePackItem);
}
TaskItem packageToDownload = new TaskItem(runtimePackName);
packageToDownload.SetMetadata(MetadataKeys.Version, runtimePackVersion);
packagesToDownload.Add(packageToDownload);
}
}
}
经过分析,Identity4(例如)导致这个问题的原因是因为 runtimePackRuntimeIdentifier 为 null 并且 wasInGraph 为 true :) 但这是什么意思,我们必须进一步挖掘。这里的关键是GetBestMatchingRid方法:
public static string GetBestMatchingRid(RuntimeGraph runtimeGraph, string runtimeIdentifier,
IEnumerable<string> availableRuntimeIdentifiers, out bool wasInGraph)
{
wasInGraph = runtimeGraph.Runtimes.ContainsKey(runtimeIdentifier);
HashSet<string> availableRids = new HashSet<string>(availableRuntimeIdentifiers);
foreach (var candidateRuntimeIdentifier in runtimeGraph.ExpandRuntime(runtimeIdentifier))
{
if (availableRids.Contains(candidateRuntimeIdentifier))
{
return candidateRuntimeIdentifier;
}
}
// No compatible RID found in availableRuntimeIdentifiers
return null;
}
所以在这里我们看到runtimePackRuntimeIdentifier 为空,因为在availableRuntimeIdentifiers 上找不到它。而这个变量定义为:
var knownFrameworkReferenceRuntimePackRuntimeIdentifiers = selectedRuntimePack.RuntimePackRuntimeIdentifiers.Split(';');
那么让我们看看它是如何定义的(在下面的代码中,变量runtimePackForRuntimeIDProcessing 是上面提到的selectedRuntimePack)
KnownRuntimePack runtimePackForRuntimeIDProcessing;
if (knownFrameworkReference.Name.Equals(knownFrameworkReference.RuntimeFrameworkName, StringComparison.OrdinalIgnoreCase))
{
// Only add runtime packs where the framework reference name matches the RuntimeFrameworkName
// Framework references for "profiles" will use the runtime pack from the corresponding non-profile framework
runtimePackForRuntimeIDProcessing = selectedRuntimePack.Value;
includeInPackageDownload = true;
}
else if (!knownFrameworkReference.RuntimePackRuntimeIdentifiers.Equals(selectedRuntimePack?.RuntimePackRuntimeIdentifiers))
{
// If the profile has a different set of runtime identifiers than the runtime pack, use the profile.
runtimePackForRuntimeIDProcessing = knownFrameworkReference.ToKnownRuntimePack();
includeInPackageDownload = true;
}
else
{
// For the remaining profiles, don't include them in package download but add them to unavaliable if necessary.
runtimePackForRuntimeIDProcessing = knownFrameworkReference.ToKnownRuntimePack();
includeInPackageDownload = false;
}
但这是我能做到的。如果没有进一步调查,我不明白应该如何定义这个selectedRuntimePack.RuntimePackRuntimeIdentifiers。这是这里的关键。显然由于某些原因 IdentityServer4 不属于selectedRuntimePack.RuntimePackRuntimeIdentifiers,这就是我正在寻找的答案:)
【问题讨论】:
-
当您在 Visual Studio 中运行它时会发生这种情况,对吗?我们不是在谈论部署到服务器之后。
-
您有重复步骤。去尝试;)但要回答你的问题。不,它不是在部署之后,它是在 VS 2019 16.8.2 中构建的 :) 我什至在 16.9.0 1.0 预览版中尝试过。是一样的。
-
(仅供参考:IdentityServer4 包) 不属于共享项目。仅将其添加到服务器项目中。
-
您不会在客户端项目中放置 100 个包。共享项目包含在客户端中,因此对于两者:尽可能少地添加,并且只添加您知道没问题的内容。假设它不是并调查 ort 测试。
-
你是对的,没有完整的文档也没有工具(afaik)。但是一点常识会大有帮助。
标签: c# asp.net-core blazor blazor-client-side blazor-webassembly