Объект POST-запроса веб-API всегда равен нулю

#c# #.net-core #asp.net-mvc-5 #asp.net-core-webapi #webapi

#c# #.net-ядро #asp.net-mvc-5 #asp.net-core-webapi #webapi

Вопрос:

Я использую .Net Core API 2.1, у меня есть это в моем контроллере:

 [Route("Invoke")]
        [HttpPost]
        public IActionResult Invoke(Student studentDetails)
        {
            DetailsResponse objResponse;
            if(ModelState.IsValid)
                {
                  objResponse= GetDetails(studentDetails);
                }
              return OK(objResponse);  
        }
 

Я пытаюсь вызвать метод действия Invoke из Postman с телом запроса как

 {"student": {"name":"John Doe", "age":18, "country":"United States of America"}}
 

Этот объект всегда имеет значение null в контроллере.
Если я попытаюсь вызвать метод действия из Postman с телом запроса как

 {"name":"John Doe", "age":18, "country":"United States of America"}
 

Здесь объект имеет данные и работает нормально.
Мой вопрос заключается в том, чтобы вызвать действие с корневым узлом, как показано ниже

 {"student": {"name":"John Doe", "age":18, "country":"United States of America"}}
 

Есть ли какая-нибудь возможность добиться этого?

Комментарии:

1. Привет @Rabia Basri, если мой ответ поможет вам решить вашу проблему, не могли бы вы принять его в качестве ответа? См.: Как принять в качестве ответа . Спасибо.

Ответ №1:

в зависимости от вашей структуры вы можете использовать

 public IActionResult Invoke([FromBody]Student studentDetails)
 

Что произойдет, так это то, что привязка модели попытается сопоставить json с указанным вами классом.

Ответ №2:

Дело в том, что ваша вторая попытка полностью имитирует ваш класс Student, поэтому он сопоставляется с Student .

 {"name":"John Doe", "age":18, "country":"United States of America"}
 

Если вы хотите получить объект с полем «student», заполненным Student json, вы можете создать другой класс StudentWrapper или InvokeParameters или что-то в этом роде с полем Student .

Но вам лучше не делать этого, если вам это действительно не нужно. Обычно это не обязательно и должно быть опущено. Это полезно только в том случае, если вы получаете несколько моделей, таких как Student, в вашем действии API.

Ответ №3:

{«имя»: «Джон Доу», «возраст»: 18, «страна»: «Соединенные Штаты Америки»}

Это приемлемый json для model Student в вашем JsonInputFormatter по умолчанию.То, что вы хотите передать, является неприемлемым json Student , вам необходимо настроить JsonInputFormatter в соответствии с вашими требованиями:

 public class CustomJsonInputFormatter : JsonInputFormatter
{
    public CustomJsonInputFormatter(ILogger logger, JsonSerializerSettings serializerSettings, ArrayPool<char> charPool, ObjectPoolProvider objectPoolProvider, MvcOptions options, MvcJsonOptions jsonOptions) : base(logger, serializerSettings, charPool, objectPoolProvider, options, jsonOptions)
    {

    }
    public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
    {
        var request = context.HttpContext.Request;
        using (var reader = new StreamReader(request.Body))
        {
            string content = await reader.ReadToEndAsync();
            JObject jo = JObject.Parse(content);
            Student student = jo.SelectToken("student", false).ToObject<Student>();
            return await InputFormatterResult.SuccessAsync(student);
        }
    }
}
 

Startup.cs:

 public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options =>
    {
        var serviceProvider = services.BuildServiceProvider();
        var jsonInputLogger = serviceProvider.GetRequiredService<ILoggerFactory>().CreateLogger<CustomJsonInputFormatter>();
        var jsonOptions = serviceProvider.GetRequiredService<IOptions<MvcJsonOptions>>().Value;
        var charPool = serviceProvider.GetRequiredService<ArrayPool<char>>();
        var objectPoolProvider = serviceProvider.GetRequiredService<ObjectPoolProvider>();

        var customJsonInputFormatter = new CustomJsonInputFormatter(
                    jsonInputLogger,
                    jsonOptions.SerializerSettings,
                    charPool,
                    objectPoolProvider,
                    options,
                    jsonOptions
            );
        options.InputFormatters.Insert(0, customJsonInputFormatter);
    }).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    //services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
 

Результат:
введите описание изображения здесь

Другой способ:

{«студент»: {«имя»: «Джон Доу», «возраст»: 18, «страна»: «Соединенные Штаты Америки»}}

Этот json приемлем для следующей модели:

 public class Student
{
    public int Age { get; set; }
    public string Name { get; set; }
    public string Country { get; set; }
}

public class Test
{
    public Student student { get; set; }
}
 

Экшен:

 [HttpPost]
public IActionResult Invoke(Test studentDetails)
{
   //...
}
 

Комментарии:

1. Спасибо вам. Я использовал ваш первый подход к созданию пользовательского средства форматирования ввода Json.