简体   繁体   English

Web API POST 请求 object 始终为 null

[英]Web API POST request object is always null

I am using.Net Core API 2.1 I have this in my Controller:我正在使用.Net Core API 2.1 我的 Controller 中有这个:

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

I am trying to invoke the Invoke action method from Postman with the request body as我正在尝试从 Postman 调用 Invoke 操作方法,请求正文为

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

This object is always null in the controller.这个 object 在 controller 中始终是 null。 If i try to invoke the action method from Postman with the request body as如果我尝试从 Postman 调用操作方法,请求正文为

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

Here the object has the data and is working fine. object 在这里有数据并且工作正常。 My question is to invoke the action with the root node like shown below我的问题是使用根节点调用操作,如下所示

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

Is there any possibility to achieve this?有没有可能实现这一目标?

depending on your framework you can use根据您可以使用的框架

public IActionResult Invoke([FromBody]Student studentDetails)

What will happen is that model binding will try and map the json to the class you have specified.将会发生的情况是 model 绑定将尝试和 map json 到 ZA2F2ED4F8EBC2CBB14C21A29DC40 您已指定。

The thing is that Your second attempt fully mimics your Student class, that is why it is mapped to the Student.问题是您的第二次尝试完全模仿了您的学生 class,这就是它映射到学生的原因。

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

If You want to receive an object with field "student" populated with Student json, You can create another class StudentWrapper or InvokeParameters or something like that with Student field.如果您想收到 object 字段“学生”填充学生 json,您可以创建另一个 class StudentWrapper 或 InvokeParameters 或类似的学生字段。

But You better not to do it if You don't really need it.但是如果你真的不需要它,你最好不要这样做。 Usually it is not necessarily and should be omitted.通常它不是必须的,应该省略。 It is only useful if You receive to have several models like Student in Your API action.仅当您在 API 操作中收到多个模型(例如 Student)时才有用。

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

This is the acceptable json for model Student in your default JsonInputFormatter.What you want to pass is an unacceptable json for Student ,you need to custom JsonInputFormatter to meet your requirement:这是默认 JsonInputFormatter 中 model Student可接受的 json。您要传递的是不可接受的 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:启动.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);
}

Result:结果: 在此处输入图像描述

Another way:另一种方式:

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

This json is acceptable for the following model:此 json 适用于以下 model:

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; }
}

Action:行动:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM