NETSDK1005 in SDK-style .xsproj projects with a platform-neutral TargetFramework
Summary
An SDK-style .xsproj with a plain <TargetFramework>net9.0</TargetFramework> can fail with:
error NETSDK1005: Assets file '…\obj\project.assets.json' doesn't have a target
for 'net9.0'. Ensure that restore has run and that you have included 'net9.0'
in the TargetFrameworks for your project.
The assets file contains a target for net9.0-windows7.0 while the build looks up net9.0.
Root cause
XSharp.BeforeCommon.Props unconditionally defaults TargetPlatformIdentifier to Windows
for every .xsproj. That file is imported before Microsoft.Common.props, so $(TargetFramework)
is not known yet and the value cannot be conditioned on the actual TFM.
(XSharp.props additionally sets TargetPlatformVersion to 7.0 unconditionally.)
For .NET 5.0+ the SDK deliberately disables this legacy default via
_EnableDefaultWindowsPlatform=false (Microsoft.NET.TargetFrameworkInference.targets)
so that the platform is derived from the TFM instead. XSharp overrides that.
The result is an inconsistent project: TargetFramework = net9.0, but
TargetPlatformIdentifier = Windows / TargetPlatformVersion = 7.0. Any restore path that
composes the NuGet framework from TFM + platform (the VS project system does) writes
net9.0-windows7.0 into project.assets.json, while ResolvePackageAssets looks the assets up
by the literal $(TargetFramework) — no match, NETSDK1005.
The same inconsistency also makes Visual Studio round-trip the TFM: opening the project and
saving the property page rewrites net9.0 to net9.0-windows7.0 in the .xsproj.
Steps to reproduce
- Create an SDK-style
.xsproj with <TargetFramework>net9.0</TargetFramework>.
- Open it in Visual Studio and let the IDE restore it.
- Build.
dotnet build from the command line is not affected — there restore and build agree on net9.0.
Note for whoever fixes this
Simply removing the TargetPlatformIdentifier default is not enough: the WinForms and WPF
templates create projects with a platform-neutral TFM (net8.0 / net9.0 / net10.0, see
template.json) plus <UseWindowsForms>true</UseWindowsForms>. Without the injected platform
those projects fail with NETSDK1136 ("The target platform must be set to Windows…").
The injected TargetPlatformIdentifier was apparently working around exactly that.
A working approach is to put the platform into the TargetFramework itself (so TFM and platform
stay consistent) from a targets file hooked up via $(BeforeTargetFrameworkInferenceTargets) —
that hook is evaluated after the project body, so the TFM is known there, and before NuGet and
the SDK derive the platform.
Related
The General property page offers no target platform / target OS selection. Its framework list is
built from the SDK's SupportedNETCoreAppTargetFramework / SupportedNETFrameworkTargetFramework
aliases, which are all platform-neutral, so -windows can currently only be set by editing the
.xsproj by hand.
Environment
- XSharp:
- .NET SDK: 10.0.400
- Visual Studio: 2022 / 2026
NETSDK1005 in SDK-style .xsproj projects with a platform-neutral TargetFramework
Summary
An SDK-style
.xsprojwith a plain<TargetFramework>net9.0</TargetFramework>can fail with:The assets file contains a target for
net9.0-windows7.0while the build looks upnet9.0.Root cause
XSharp.BeforeCommon.Propsunconditionally defaultsTargetPlatformIdentifiertoWindowsfor every
.xsproj. That file is imported beforeMicrosoft.Common.props, so$(TargetFramework)is not known yet and the value cannot be conditioned on the actual TFM.
(
XSharp.propsadditionally setsTargetPlatformVersionto7.0unconditionally.)For .NET 5.0+ the SDK deliberately disables this legacy default via
_EnableDefaultWindowsPlatform=false(Microsoft.NET.TargetFrameworkInference.targets)so that the platform is derived from the TFM instead. XSharp overrides that.
The result is an inconsistent project:
TargetFramework=net9.0, butTargetPlatformIdentifier=Windows/TargetPlatformVersion=7.0. Any restore path thatcomposes the NuGet framework from TFM + platform (the VS project system does) writes
net9.0-windows7.0intoproject.assets.json, whileResolvePackageAssetslooks the assets upby the literal
$(TargetFramework)— no match, NETSDK1005.The same inconsistency also makes Visual Studio round-trip the TFM: opening the project and
saving the property page rewrites
net9.0tonet9.0-windows7.0in the.xsproj.Steps to reproduce
.xsprojwith<TargetFramework>net9.0</TargetFramework>.dotnet buildfrom the command line is not affected — there restore and build agree onnet9.0.Note for whoever fixes this
Simply removing the
TargetPlatformIdentifierdefault is not enough: the WinForms and WPFtemplates create projects with a platform-neutral TFM (
net8.0/net9.0/net10.0, seetemplate.json) plus<UseWindowsForms>true</UseWindowsForms>. Without the injected platformthose projects fail with NETSDK1136 ("The target platform must be set to Windows…").
The injected
TargetPlatformIdentifierwas apparently working around exactly that.A working approach is to put the platform into the
TargetFrameworkitself (so TFM and platformstay consistent) from a targets file hooked up via
$(BeforeTargetFrameworkInferenceTargets)—that hook is evaluated after the project body, so the TFM is known there, and before NuGet and
the SDK derive the platform.
Related
The General property page offers no target platform / target OS selection. Its framework list is
built from the SDK's
SupportedNETCoreAppTargetFramework/SupportedNETFrameworkTargetFrameworkaliases, which are all platform-neutral, so
-windowscan currently only be set by editing the.xsprojby hand.Environment