0

I made POST and PUT APIs and now I am doing attribute validation,

Model

public class Model 
{
    public string user_identifier { get; set; }
    public string name { get; set; }
}

Payload in postman

{
    "user_identifier": "1234",
    "name": "abcd"
}

It works for this, but when I change the type of user_identifier like,

{
    "user_identifier": 1234,
    "name": "abcd"
}

Postman was giving an automatic 400 error for that attribute, which I don't want because I am doing my own validations, so, I added this to suppress those automatic 400 responses,

services.Configure<ApiBehaviorOptions>(options =>
{
    options.SuppressModelStateInvalidFilter = true;
});

Now, when I pass the payload as,

{
    "user_identifier": 1234,
    "name": "abcd"
}

the payload is considered as null, Can anyone please help me with this problem, and also I think it not good to suppress the automatic responses, an alternative would be appreciated.

Thanks in advance.

Ashwin Pandey
  • 125
  • 13
  • This requires some design in your code because the validation is run after the model binding. Your error (resulting in 400) is thrown by the model binding which in this case is based on an `IInputFormatter` (for json). That formatter cannot deserialize your model because of type being mismatched between string and number. You may have to create your own `IInputFormatter` or somehow adjust the json deserializer to accept the type mismatching, but must provide a cue in your deserialized model to indicate that it's invalid so that the next validation can verify it. It's fairly complicated – Hopeless Nov 17 '20 at 07:37
  • add a ModelDTO and map to your Model with Automapper, so that you doesn't need to suppress the model state validation – ale Nov 17 '20 at 07:47
  • Hi @AshwinPandey, any updates about this case? `System.Text.Json` does not support Non-string values for string properties, which cause the issue. Does it work for you by adding Newtonsoft.Json (Json.NET) support in your project? – Fei Han Nov 23 '20 at 09:19
  • @FeiHan I wrote the answer, you can check it out, I basically changed my approach to taking in payload, and by doing that I have more control over the payload validation. – Ashwin Pandey Nov 23 '20 at 13:12

3 Answers3

0

The main problem is that when your json is like the below, it's saying that the user_identifier is an int but you're saying it should be a string.

{
    "user_identifier": 1234,
    "name": "abcd"
}

This is the error that gets returned on a newly created api project.

{
    "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
    "title": "One or more validation errors occurred.",
    "status": 400,
    "traceId": "|8c6385fc-4816d0c11a257a60.",
    "errors": {
        "$.user_identifier": [
            "The JSON value could not be converted to System.String. Path: $.user_identifier | LineNumber: 1 | BytePositionInLine: 27."
         ]
    }
}

Once you know that's the problem (assuming you're using ASP.NET Core >= 3.0.0), you can find The JSON value could not be converted to System.Int32 which explains how they moved from Json.NET in ASP.NET Core 3.0.0. One option would be to install Microsoft.AspNetCore.Mvc.NewtonsoftJson and add it in startup services.AddControllers().AddNewtonsoftJson();

Shoejep
  • 4,414
  • 4
  • 22
  • 26
0

In ASP.NET Core 3.0 and later versions, the default JSON serializer is System.Text.Json.

And in following doc, we can find that System.Text.Json does not support Non-string values for string properties, which cause this issue.

https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-migrate-from-newtonsoft-how-to?pivots=dotnet-core-3-1#non-string-values-for-string-properties

To allow non-string JSON values for string properties in ASP.NET Core 3+ project, as @Shoejep mentioned, we can add Newtonsoft.Json (Json.NET) support in our project by installing the Microsoft.AspNetCore.Mvc.NewtonsoftJson package and updating Startup.ConfigureServices to call AddNewtonsoftJson method.

https://learn.microsoft.com/en-us/aspnet/core/migration/22-to-30?view=aspnetcore-5.0&tabs=visual-studio#use-newtonsoftjson-in-an-aspnet-core-30-mvc-project

Fei Han
  • 26,415
  • 1
  • 30
  • 41
0

Thanks for all the help everyone.

I was not able to find a way to validate the attribute so that .Net doesn't give an automatic 400 BadRequest response.

I figured out the problem, this was happening because I was getting the payload using [FromBody] PayloadModel payload in the parameter of Post request.

Now, I have changed my approach to take the payload using,

var streamReader = new StreamReader(Request.Body);
string requestBody = await streamReader.ReadToEndAsync();
var payload = JsonConvert.DeserializeObject<PayloadModel>(requestBody);

And modified my model class to,

public class PayloadModel 
{
    [JsonProperty("user_identifier")]
    public string UserIdentifier { get; set; }
    
    [JsonProperty("name")]
    public string name { get; set; }
}

This way, I have a bit more granular level control on payload validation.

Ashwin Pandey
  • 125
  • 13