Skip to content
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

JsonSerializer does not require that value of an enum is defined #35900

Closed
jasonycw opened this issue May 6, 2020 · 5 comments
Closed

JsonSerializer does not require that value of an enum is defined #35900

jasonycw opened this issue May 6, 2020 · 5 comments

Comments

@jasonycw
Copy link

jasonycw commented May 6, 2020

Consider the following:

var dayOfWeek = JsonSerializer.Deserialize<DayOfWeek>("9");
Console.WriteLine(dayOfWeek);

The serializer does not complain when an out-of-range enum value is presented.


Original text

Let's say we have the following as our request model

public enum Currency
{
   Dollar, Yen
}

public class Request
{
    public Currency Currency {get; set; }
}

In the controller, if we have

[HttpPost("test")]
public async Task<ActionResult> Post([FromQuery]Request request)

and we POST /test?currency=3, we will have an invalid model state.

If we have

[HttpPost("test/{currency}")]
public async Task<ActionResult> Post([FromRoute]Currency currency)

and we POST /test/3, we will also have an invalid model state.

However, if we have

[HttpPost("test")]
public async Task<ActionResult> Post([FromBody]Request request)

and we POST /test with a JSON body

{
   "currency": "3"
}

The model state will be valid and the controller will get request.Currency = 3 which does not make sence.

If we add and attribute to the enum property like the following
(thanks to this very old StackOverflow answer)

public class Request
{
    [EnumDataType(typeof(Currency ))]
    public Currency Currency {get; set; }
}

And POST /test with the same JSON body again, we can get invalid model state, which is expected behavior.

Further technical details

  • ASP.NET Core version: 3.1
  • Include the output of dotnet --info:
.NET Core SDK (reflecting any global.json):
 Version:   3.1.201
 Commit:    b1768b4ae7

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.18363
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\3.1.201\

Host (useful for support):
  Version: 3.1.3
  Commit:  4a9f85e9f8
  • The IDE (VS / VS Code/ VS4Mac) you're running on, and it's version: VS 16.5.4
@dotnet dotnet deleted a comment from javiercn May 6, 2020
@pranavkm pranavkm removed their assignment May 6, 2020
@pranavkm pranavkm transferred this issue from dotnet/aspnetcore May 6, 2020
@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added area-Infrastructure-libraries untriaged New issue has not been triaged by the area owner labels May 6, 2020
@ghost
Copy link

ghost commented May 6, 2020

Tagging subscribers to this area: @safern, @ViktorHofer
Notify danmosemsft if you want to be subscribed.

@pranavkm pranavkm changed the title Enum model binding [FromBody] is incorrect compare to [FromRoute] [FromQuery] JsonSerializer does not require that value of an enum is defined May 6, 2020
@ghost
Copy link

ghost commented May 6, 2020

Tagging subscribers to this area: @jozkee
Notify danmosemsft if you want to be subscribed.

@pranavkm
Copy link
Contributor

pranavkm commented May 6, 2020

@jasonycw neither of the two serializers (S.T.Json \ Newtonsoft.Json) that MVC supports enforce that an enum value is defined. MVC's model binding does which is why you see a validation error appear for model bound values. The EnumDataTypeAttribute validates that enum values are within range for an enum. I'd use that to enforce this behavior consistently.

Moving the issue to the runtime repo in the event they want to consider enforcing this using a converter.

@layomia
Copy link
Contributor

layomia commented May 6, 2020

Enum.(Try)Parse does not enforce this, so I'm not sure that the serializer should (at least by default). A custom converter can be added to enforce that the input is within range.

As mentioned, there's a pattern for validating enum values in MVC using EnumDataTypeAttribute, so there's a workaround for the motivating scenario here.

@layomia layomia removed the untriaged New issue has not been triaged by the area owner label May 6, 2020
@layomia layomia added this to the Future milestone May 6, 2020
@layomia
Copy link
Contributor

layomia commented Sep 14, 2020

Although this issue is older, I'll close it as a dup of #42093 which has more discussion.

@layomia layomia closed this as completed Sep 14, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Dec 9, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants