Skip to content

NETSDK1005 in SDK-style .xsproj projects with a platform-neutral TargetFramework #2051

Description

@hpetriffer

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

  1. Create an SDK-style .xsproj with <TargetFramework>net9.0</TargetFramework>.
  2. Open it in Visual Studio and let the IDE restore it.
  3. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions