feat: make missing Microsoft.WebApplication.targets configurable#110
feat: make missing Microsoft.WebApplication.targets configurable#110ehasis wants to merge 1 commit into
Conversation
Building with the `dotnet` CLI (Core MSBuild) resolves $(WebApplicationsTargetPath) to a path under the .NET SDK where Microsoft.WebApplication.targets does not exist, failing with a cryptic MSB4019. Make the web-targets import conditional on Exists(...) and add a $(MissingWebApplicationsTargetPathAction) property (default Error) that controls the reaction when it is missing: Ignore | Skip (info message) | Warn | Error Emit message SYSWEB001 (severity per the property) with actionable guidance, and SYSWEB000 for an invalid property value. Add docs/Diagnostics.md as the registry of message IDs and link it from the docs index. Fix: CZEMacLeod#106
| | `SYSWEB000` | Error | Invalid value for the `MissingWebApplicationsTargetPathAction` property (expected `Ignore`, `Skip`, `Warn` or `Error`). | | ||
| | `SYSWEB001` | Error / Warning / message | `Microsoft.WebApplication.targets` could not be resolved at `$(WebApplicationsTargetPath)`. Configurable via the `MissingWebApplicationsTargetPathAction` property — see below. | | ||
|
|
||
| ## `MissingWebApplicationsTargetPathAction` |
There was a problem hiding this comment.
The 2 properties - MissingWebApplicationsTargetPathAction and WebApplicationsTargetPath - should probably be documented in doc\SDK.md.
There are sections for Common Properties (used by the main SDK and RazorLibrary) and the specific ones for the main SDK.
I'd like to keep the Diagnostics.md file 'clean' and only have a table of the codes.
| Messages emitted by `MSBuild.SDK.SystemWeb` use the `SYSWEB` prefix followed by a number. | ||
| This page is the central registry of those messages. | ||
|
|
||
| | ID | Severity | Meaning | |
There was a problem hiding this comment.
Could we have a 4th column for 'more info' with a deep dive link for some errors - e.g. 000 and 001 could point to a generic WebApplicationsTarget.md file which has all the information about how it is normally derived (VSToolsPath) and how to set it externally. Perhaps the example powershell script / github action for vswhere can go there too.
| @@ -0,0 +1,51 @@ | |||
| # Diagnostics (message IDs) | |||
|
|
|||
| Messages emitted by `MSBuild.SDK.SystemWeb` use the `SYSWEB` prefix followed by a number. | |||
There was a problem hiding this comment.
I'm coming round to SYSWEB as the prefix - in another issue I had suggested SWSDK for SystemWebSDK.
| # Useful Information | ||
|
|
||
| ## Diagnostics | ||
| - [Message IDs and the `MissingWebApplicationsTargetPathAction` property](Diagnostics.md) |
There was a problem hiding this comment.
I think this should just reference the Message IDs here.
We could consider breaking the common and specific properties out into separate files and link them here, but I think that that might be a future consideration.
| </PropertyGroup> | ||
|
|
||
| <!-- Reject unknown values up front. --> | ||
| <Error Code="SYSWEB000" |
There was a problem hiding this comment.
The Error and Warn actions should have the HelpLink property pointing to https://github.com/CZEMacLeod/MSBuild.SDK.SystemWeb/blob/main/docs/Diagnostics.md#SYSWEB000 etc.
Hopefully we can put anchors into the markup.
There was a problem hiding this comment.
Either that or we have a file per error (or group of errors) and directly link to that.
| <!-- Reject unknown values up front. --> | ||
| <Error Code="SYSWEB000" | ||
| Condition="'$(MissingWebApplicationsTargetPathAction)' != 'Ignore' and '$(MissingWebApplicationsTargetPathAction)' != 'Skip' and '$(MissingWebApplicationsTargetPathAction)' != 'Warn' and '$(MissingWebApplicationsTargetPathAction)' != 'Error'" | ||
| Text="SYSWEB000: Unknown MissingWebApplicationsTargetPathAction '$(MissingWebApplicationsTargetPathAction)'. Valid values are: Ignore, Skip, Warn, Error." /> |
There was a problem hiding this comment.
I'm not sure if the default is to have the error code at the start of the text - I thought it would be implicit from the Code property...
|
|
||
| <Error Code="SYSWEB001" Text="$(_SystemWebMissingWebTargetsText)" Condition="'$(MissingWebApplicationsTargetPathAction)' == 'Error'" /> | ||
| <Warning Code="SYSWEB001" Text="$(_SystemWebMissingWebTargetsText)" Condition="'$(MissingWebApplicationsTargetPathAction)' == 'Warn'" /> | ||
| <Message Importance="high" Text="$(_SystemWebMissingWebTargetsText)" Condition="'$(MissingWebApplicationsTargetPathAction)' == 'Skip'" /> |
There was a problem hiding this comment.
As the message can't have a helplink or code (yet?), here we could include them directly into the
Text="SYSWEB001: $(_SystemWebMissingWebTargetsText) - $(_SystemWebMissingWebTargetsLink)"|
Regarding your open questions: Naming - I think I put it in the inline comments - but I think SYSWEB is reasonable. I am still unsure if Issue #109 covers updating the other errors and warnings to have codes and links. Keeping this PR to the scope of #106 is good. However, we need to setup the framework for how the other errors will be dealt with. HelpLink="$(_SystemWebSDKHelpLinkBase)#SYSWEBnnn"where required. |
Make missing
Microsoft.WebApplication.targetsconfigurable (MissingWebApplicationsTargetPathAction)Closes #106. Split out from #103 (item 2).
Problem
Microsoft.WebApplication.targetsships with Visual Studio, not with the .NET SDK. When building with thedotnetCLI (Core MSBuild),$(MSBuildExtensionsPath32)points at the .NET SDK rather than a Visual Studio install, so the default$(WebApplicationsTargetPath)doesn't exist and the build fails with a cryptic, low‑level error:Change
Implements the approach you proposed in #106.
The
Microsoft.WebApplication.targetsimport is now conditional onExists('$(WebApplicationsTargetPath)').New property
MissingWebApplicationsTargetPathAction(defaultError) controls what happens when the file can't be found:IgnoreSkipSYSWEB001)WarnSYSWEB001)ErrorSYSWEB001) — defaultThe message (
SYSWEB001) is actionable: install the VS / Build Tools web workload, build from a Developer command prompt, or setVSToolsPath/WebApplicationsTargetPath(e.g. via VSWhere in CI).An invalid property value fails fast with
SYSWEB000.Comparison is case‑insensitive (
error==Error).This composes cleanly with the optional auto‑location work (the other split‑out item): that would set
WebApplicationsTargetPathbefore this check, so when it finds a valid pathExists(...)is true and no action fires.Diagnostics / message IDs
Per your request, this starts a registry of message IDs. New
docs/Diagnostics.mdlists them and is linked from the docs index:SYSWEB000MissingWebApplicationsTargetPathActionvalueSYSWEB001Microsoft.WebApplication.targetscould not be resolvedFiles
src/MSBuild.SDK.SystemWeb/Sdk/Sdk.targets— property default, conditional import, dispatch target.docs/Diagnostics.md— message‑ID registry + property reference (new).docs/README.md— link to the diagnostics page.Testing
Built a minimal
net48project with thedotnetCLI against a locally‑packed SDK, on Windows with VS 2026 (v18) + .NET SDK 10:Errorerror SYSWEB001Warnwarning SYSWEB001, build continuesSkipSYSWEB001message, build continuesIgnoreerror SYSWEB000-p:VSToolsPath=…)Verified with both the
dotnetCLI and the full Visual StudioMSBuild.exe.Open questions
SYSWEBstarting at000/001; happy to change to whatever scheme you prefer before merge.