Skip to content

NewtonsoftJsonInputFormatter uses incorrect ModelStateDictionary keys for members containing single quotes #39069

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
halter73 opened this issue Dec 15, 2021 · 2 comments
Labels
area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates bug This issue describes a behavior which is not expected - a bug. feature-mvc-formatting
Milestone

Comments

@halter73
Copy link
Member

Given JSON content like "[{\"It's a key\": 1234556}]" which is deserialized as IDictionary<string, short> (the value is too big for a short making this an error), NewtonsoftJsonInputFormatter adds an entry to the ModelStateDictionary with the key "['It\\'s a key'].It's a key" instead of ['It\\'s a key'] as expected.

    [Fact]
    public virtual async Task JsonFormatter_EscapedKeys_SingleQuote()
    {
        var expectedKey = JsonFormatter_EscapedKeys_SingleQuote_Expected;

        // Arrange
        var content = "{\"It's a key\": 1234556}";
        var formatter = GetInputFormatter();

        var contentBytes = Encoding.UTF8.GetBytes(content);
        var httpContext = GetHttpContext(contentBytes);
        var formatterContext = CreateInputFormatterContext(
            typeof(IDictionary<string, short>), httpContext);
        // Act
        var result = await formatter.ReadAsync(formatterContext);
        // Assert
        Assert.True(result.HasError);
        Assert.Collection(
            formatterContext.ModelState.OrderBy(k => k.Key),
            kvp =>
            {
                // This fails with Expected: ['It\'s a key'], Actual: ['It\'s a key'].It's a key
                Assert.Equal("['It\\'s a key']", kvp.Key);
            });
    }

This is caused by logic in NewtonsoftJsonInputFormatter's ErrorHandler that appends the ErrorContext.Member to the ErrorContext.Path when the Path doesn't already end with Member in order to better report missing required properties.

var path = eventArgs.ErrorContext.Path;
var member = eventArgs.ErrorContext.Member?.ToString();
var addMember = !string.IsNullOrEmpty(member);
if (addMember)
{
// Path.Member case (path.Length < member.Length) needs no further checks.
if (path.Length == member!.Length)
{
// Add Member in Path.Memb case but not for Path.Path.
addMember = !string.Equals(path, member, StringComparison.Ordinal);
}
else if (path.Length > member.Length)
{
// Finally, check whether Path already ends with Member.
if (member[0] == '[')
{
addMember = !path.EndsWith(member, StringComparison.Ordinal);
}
else
{
addMember = !path.EndsWith("." + member, StringComparison.Ordinal)
&& !path.EndsWith("['" + member + "']", StringComparison.Ordinal)
&& !path.EndsWith("[" + member + "]", StringComparison.Ordinal);
}
}
}

ErrorContext.Path escapes the ', but ErrorContext.Member doesn't meaning the !path.EndsWith() checks don't cover this scenario. We could scan ErrorContext.Member for any ' characters and manually escape it before doing the !path.EndsWith() checks, but that feels like playing whac-a-mole. I'm guessing there are even more edge cases the !path.EndsWith() checks don't cover.

I really want to get rid of the addMember logic altogether and have Json.NET either give us the path we want to begin with or expose an ErrorContext.ErrorType so we only do the addMember logic for missing required properties where we know the member is never in the path. The latter option was proposed a while back but never implemennted in Json.NET. See JamesNK/Newtonsoft.Json#1903

See #39058 (comment) for more context about this issue.

@halter73 halter73 added area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates bug This issue describes a behavior which is not expected - a bug. labels Dec 15, 2021
@mkArtakMSFT mkArtakMSFT added old-area-web-frameworks-do-not-use *DEPRECATED* This label is deprecated in favor of the area-mvc and area-minimal labels and removed area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates labels Dec 16, 2021
@rafikiassumani-msft rafikiassumani-msft added this to the .NET 7 Planning milestone Dec 21, 2021
@ghost
Copy link

ghost commented Dec 21, 2021

Thanks for contacting us.

We're moving this issue to the .NET 7 Planning milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s).
If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues.
To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

@ghost
Copy link

ghost commented Oct 11, 2022

Thanks for contacting us.

We're moving this issue to the .NET 8 Planning milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s).
If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues.
To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

@captainsafia captainsafia added area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates and removed old-area-web-frameworks-do-not-use *DEPRECATED* This label is deprecated in favor of the area-mvc and area-minimal labels labels Jun 20, 2023
@captainsafia captainsafia modified the milestones: .NET 8 Planning, Backlog Mar 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates bug This issue describes a behavior which is not expected - a bug. feature-mvc-formatting
Projects
No open projects
Status: No status
Development

No branches or pull requests

6 participants
@halter73 @captainsafia @brunolins16 @mkArtakMSFT @rafikiassumani-msft and others