skip to Main Content

I’m using mostly .NET 6 development with no additional json dependencies. When I receive a parameter in the controller that is of type collection and I use the postman tool to initiate a web request, the program returns the following result with an error message "The JSON value could not be converted to System.Collections. Generic.List", and there is also a missing field error message, postman body json data is not a problem. So I need to know why the program returns the following result and how to end this problem.

program.cs

using EnglishStudy.Service;
using EnglishStudy.Service.ServiceImpl;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using System.Text;

var builder = WebApplication.CreateBuilder(args);


builder.Services.AddControllers();

builder.Services.AddScoped<IWordService, WordServiceImpl>();

var app = builder.Build();


app.UseHttpsRedirection();
app.UseAuthentication();


app.UseAuthorization();

app.MapControllers();

app.Run();

Controller.cs

using EnglishStudy.Entity;
using EnglishStudy.Service;
using Microsoft.AspNetCore.Mvc;

namespace EnglishStudy.Controllers {
    [ApiController]
    [Route("word")]
    public class WordController : ControllerBase {
       
        private  Result result = new Result();

        private IWordService wordService;


        public WordController(IWordService wordService) {
            this.wordService = wordService;
        }

        [HttpPost("addlist/{type}")]
        public Result AddWord([FromBody] List<Word> wordList,int type = 1) {
            var count = wordService.AddWord(wordList,type);
            return result.Ok(count);
        }
}
}

Word.cs

using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace EnglishStudy.Entity {

    public class Word {
        public string Words { get; set; }
        public string Phonetic { get; set; }
        public string Paraphrase { get; set; }

            
    }
}

HttpRequest Route below

https://localhost:7031/word/addlist/1

My HttpRequest JSON data below

{
    "wordList": [
        {
            "words": "a",
            "phonetic": "a",
            "paraphrase": " art.一(个) 每一(个)"
        }
    ]
}

When I make a network request, the program returns the following result

{
    "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
    "title": "One or more validation errors occurred.",
    "status": 400,
    "traceId": "00-bada468e083e59d9030f0fb71c9f6dfa-722ec90670eed379-00",
    "errors": {
        "$": [
            "The JSON value could not be converted to System.Collections.Generic.List`1[EnglishStudy.Entity.Word]. Path: $ | LineNumber: 0 | BytePositionInLine: 1."
        ],
        "wordList": [
            "The wordList field is required."
        ]
    }
}

I would like to know how to Solve the problem

2

Answers


  1. your list is wrapped with words in you json string. So you have to create a root class

    public class Root
    {
    List<Word> wordList {get; set;}
    }
    

    and change the activity header

      public Result AddWord([FromBody] Root root,int type = 1)
     {
       var wordsList=root.wordList;
    
    Login or Signup to reply.
  2. I agree with the post above and in the comment. I want to add some basic explanation here. Normally speaking, the input parameter determines what we need to pass. Therefore, you defined the input parameter with List<Word> in your code, you need to pass a list. Let’s see the example below, the first one is a list because it is surrounded by [], and the second one is an object because it’s surrounded by {}. Definitely we can add a root class like Serge said, we can also remove wordList like Ian said.

    [
        "property1":{},//大括号代表对象
        "property2":"",
        "property3":[]//中括号代表数组
    ]
    
    {
        "property1":[]
    }
    

    if I needed a lot of different types of List parameters, I would need to create a lot of files, resulting in a lot of project files

    Normally speaking, we created model class according to the business, for example, we have a controller which is designed to manage user, then we should create a User class which including all the required types like username, id, age, role, if we are trying to define an API which is designed to manage many targets, for example users along with user role + user order + user history + some other information, then we do need to create a lot of files, that also represents object-oriented programming I think. Sample and test result below.

    [Route("word")]
    [ApiController]
    public class WordController : ControllerBase
    {
        [HttpPost("addlist/{type}")]
        public IActionResult AddWord([FromBody] Root root, int type = 1)
        {
            var count = 1;
            return Ok(count);
        }
    }
    
    public class Word
    {
        public string Words { get; set; }
        public string Phonetic { get; set; }
        public string Paraphrase { get; set; }
    }
    
    public class Word2
    {
        public int MyProperty { get; set; }
    }
    
    public class Root { 
        public List<Word> wordList { get; set; }
        public List<Word2> wordList2 { get; set; }
        public string prop1 { get; set; }
    }
    

    enter image description here

    But we can reject creating so many classes like what JS does. Just define the input parameter as an JsonObject. Sample and test result like below. But we can see obviously that it’s more complex to get the target value, and it also brings much trouble to help understand the usage for each property inside the request body. So it’s better to create the classes for the models.

    using Microsoft.AspNetCore.Cors.Infrastructure;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Http.HttpResults;
    using Microsoft.AspNetCore.Mvc;
    using Newtonsoft.Json;
    using System.Text.Json.Nodes;
    
    [Route("word")]
    [ApiController]
    public class WordController : ControllerBase
    {
        [HttpPost("addlist/{type}")]
        public IActionResult AddWord([FromBody] JsonObject root, int type = 1)
        {
            var res = root["prop1"];
            var res2 = root["wordList"];
            var res3 = root["wordList"].AsArray()[0]["words"];
    
            return Ok();
        }
    }
    

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search