Search code examples
asp.netasp.net-corejson-apiasp.net-core-3.1

ASP .NET Core 3.1 Login constructor returns NULL. The Login properties are not binded from the Post request by JsonApiDotNetCore


I am currently upgrading an ASP .NET Core Web API from 2.2 to 3.1. I am testing the controllers through PostMan to make sure everything is OK. It is not. When I first try to login, I send a valid username and password in the HttpPost request via Postman to the web API. However, when it calls the login constructor, it returns NULL, which means that the model does not contain the username and password that I just passed. Does anyone know why this is happening?

Note 1: I am confident that the Post request that I am submitting through PostMan is correct because I can successfully submit the same request to the .NET Core 2.2 web API.

Note 2: The WebApi is running .NET Core 3.1 with JsonApiDotNetCore 4.0.0-alpha4 whereas the model is contained in a separate .NET Standard 2.1 project with JsonApiDotNetCore 3.1 (I cannot upgrade to 4.0.0-alpha4 because it does not support .NET Standard 2.1). Could this be causing it?

Login Controller

using Test_Model.Users;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;

namespace Test_WebApi.Controllers.Tokens
{
    public class TokensController : ControllerBase
    {
        public TokensController(
            IConfiguration objConfig,
            ILogger<TokensController> objLogger,
            IServiceProvider objServiceProvider)
            : base(objConfig, objLogger, objServiceProvider)
        { }

        [AllowAnonymous]
        [HttpPost("/clients/login")]
        public async Task<IActionResult> LoginAsync([FromBody] Login objLogin)
        {
            return new JsonResult(objLogin);
        }
    }
}

Login Model

using JsonApiDotNetCore.Models;
using System.ComponentModel.DataAnnotations;

public class Login
{
    // Constructor
    public Login() { } // When I place a breakpoint here, the debugger returns a NULL model in 3.1 but returns the model with the correct values from PostMan.

    // Properties
    [Required]
    [EmailAddress]
    [Attr("username")]
    public string UserName { get; set; }

    [Required]
    [Attr("password")]
    public string Password { get; set; }

    [Required]
    [Attr("rememberme")]
    public bool RememberMe { get; set; }
}

the jsonapidotnet is not populating the properties.

Update

Postman post request:

{
    username: "[email protected]",
    password: "12345",
    rememberme: "false"
}

Postman post settings:

Body = Raw

Headers (Key / Value):

Accept / application/json
Content-Type / application/json

Solution

    1. As of 3.0, ASP.NET Core uses System.Text.Json as the default JSON Serializer/Deserializer, which requires a strict JSON syntax. This behavior is different from the old Newtonsoft.JSON.

    2. Actually, even the payload is supported by Newtonsoft.JSON, it is not a valid JSON:

      {
          username: "[email protected]",
          password: "12345",
          rememberme: "false"
      }
      

      (A JSON property should be a string that starts with ", see JSON.org:

      object

      string

    3. If you want to use JSON like what we did in old days, follow this docs: