Fix ShallowCopy DateFormatString side effect overriding DateFormatHandling#65580
Fix ShallowCopy DateFormatString side effect overriding DateFormatHandling#65580kubaflo wants to merge 2 commits intodotnet:mainfrom
Conversation
|
Thanks for your PR, @@kubaflo. Someone from the team will get assigned to your PR shortly and we'll get it reviewed. |
There was a problem hiding this comment.
Pull request overview
This PR fixes a long-standing bug (issue #29532) in NewtonsoftJsonOutputFormatter.ShallowCopy: assigning DateFormatString through the property setter (even to its default value) sets an internal _dateFormatStringSet flag inside Newtonsoft.Json's JsonSerializerSettings, which causes DateFormatString to silently override DateFormatHandling. As a result, users who configure DateFormatHandling.MicrosoftDateFormat would get ISO 8601 output instead. The fix uses reflection to only copy DateFormatString when it was explicitly set. The PR also bundles several new agentic skill definition files for GitHub Actions automation.
Changes:
NewtonsoftJsonOutputFormatter.cs: Uses reflection to check_dateFormatStringSetflag before copyingDateFormatStringinShallowCopyNewtonsoftJsonOutputFormatterTest.cs: Adds regression test verifyingDateFormatHandling.MicrosoftDateFormatis respected whenDateFormatStringis not set.github/skills/files: Adds multiple new agentic workflow skill definitions and scripts for automated issue fixing
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
src/Mvc/Mvc.NewtonsoftJson/src/NewtonsoftJsonOutputFormatter.cs |
Core fix: reflection-based conditional copy of DateFormatString in ShallowCopy |
src/Mvc/Mvc.NewtonsoftJson/test/NewtonsoftJsonOutputFormatterTest.cs |
Regression test verifying DateFormatHandling.MicrosoftDateFormat produces Microsoft date format output |
.github/skills/fix-issue/SKILL.md |
New 5-phase agentic workflow skill for end-to-end issue fixing |
.github/skills/write-tests/SKILL.md |
New skill for creating unit tests for issues |
.github/skills/verify-tests/SKILL.md |
New skill for verifying tests catch bugs |
.github/skills/try-fix/SKILL.md |
New skill for attempting alternative fixes |
.github/skills/ai-summary-comment/SKILL.md |
New skill for posting automated progress comments on PRs |
.github/skills/ai-summary-comment/scripts/post-ai-summary-comment.sh |
Shell script that reads phase outputs and posts/updates a unified AI summary comment |
.github/skills/fix-issue/tests/test-skill-definition.sh |
Bash test script validating the fix-issue skill definition |
.github/skills/fix-issue/tests/test-ai-summary-comment.sh |
Bash test script validating the ai-summary-comment scripts |
src/Mvc/Mvc.NewtonsoftJson/src/NewtonsoftJsonOutputFormatter.cs
Outdated
Show resolved
Hide resolved
src/Mvc/Mvc.NewtonsoftJson/src/NewtonsoftJsonOutputFormatter.cs
Outdated
Show resolved
Hide resolved
…dling When ShallowCopy copies DateFormatString via the property setter, it sets an internal _dateFormatStringSet flag in Newtonsoft.Json that causes DateFormatString to take precedence over DateFormatHandling. This means users who set DateFormatHandling.MicrosoftDateFormat but not DateFormatString would still get ISO 8601 output. Use reflection to check whether _dateFormatStringSet is true on the source settings, and only copy DateFormatString when the user explicitly set it. This preserves the user's DateFormatHandling preference. Fixes dotnet#29532 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
e5bd631 to
f86f7dc
Compare
Replace FieldInfo reflection with [UnsafeAccessor] for accessing the internal _dateFormatStringSet field on JsonSerializerSettings, as suggested by @pentp. This is faster and avoids runtime reflection costs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
🤖 AI Summary
🔍 Automated Fix Report
🔍 Pre-Flight — Context & Validation
Issue: #29532 — Newtonsoft
ShallowCopysetsDateFormatStringside effect overridingDateFormatHandlingArea:
src/Mvc/Mvc.NewtonsoftJson/Root Cause:
NewtonsoftJsonOutputFormatter.ShallowCopycopiesDateFormatStringvia the property setter, which triggers an internal_dateFormatStringSetflag in Newtonsoft.Json'sJsonSerializerSettings. When this flag is set,DateFormatStringtakes precedence overDateFormatHandling— so users who setDateFormatHandling.MicrosoftDateFormatstill get ISO 8601 output.Classification: Bug — unintended side effect from property copy
🧪 Test — Bug Reproduction
Test File:
src/Mvc/Mvc.NewtonsoftJson/test/NewtonsoftJsonOutputFormatterTest.csTest Added:
DateFormatHandling_IsRespected_WhenDateFormatStringNotExplicitlySet— verifies thatDateFormatHandling.MicrosoftDateFormatproduces\/Date(...)\/output whenDateFormatStringis not explicitly set.Strategy: Created settings with only
DateFormatHandling = MicrosoftDateFormat, formatted a date object, and asserted the output contains the Microsoft date format pattern.🚦 Gate — Test Verification & Regression
Gate Result: ✅ All 250 NewtonsoftJson tests pass
Test Command:
dotnet test src/Mvc/Mvc.NewtonsoftJson/test/Microsoft.AspNetCore.Mvc.NewtonsoftJson.Test.csproj --no-restore -v qRegression: No failures in existing test suite.
🔧 Fix — Analysis & Comparison (✅ 3 passed)
Fix: Avoid triggering
_dateFormatStringSetflag during ShallowCopy when user hasn't explicitly set DateFormatString._dateFormatStringSetfield✅ Attempt 0: PASS
Approach: Reflection check on
_dateFormatStringSetfield, conditionally copy DateFormatString.Added static
FieldInfofor the internal_dateFormatStringSetfield. InShallowCopy, removed DateFormatString from initializer and only copy it when the field istrue(user explicitly set it).📄 Diff
✅ Attempt 1: PASS
Approach: Simply omit DateFormatString from ShallowCopy entirely.
Remove
DateFormatString = settings.DateFormatStringfrom the initializer. The default value is the same ISO 8601 format, so this works for the common case. Caveat: if a user explicitly sets a custom DateFormatString, it won't be copied to the shallow copy. All 250 tests pass.📄 Diff
✅ Attempt 2: PASS
Approach: Compare DateFormatString to a cached default value, only copy when different.
Created
DefaultDateFormatStringstatic field fromnew JsonSerializerSettings().DateFormatString. In ShallowCopy, only copy DateFormatString via property setter when it differs from the default. This avoids reflection while correctly preserving custom format strings.📄 Diff