【问题标题】:Post FromBody Always NullPost FromBody 始终为空
【发布时间】:2017-02-16 15:05:57
【问题描述】:

我有一个使用 ASP.NET Core 构建的新 API,但我无法将任何数据 POST'ed 到端点。

端点如下所示:

[HttpPost]
[Route("StudentResults")]
public async Task<IActionResult> GetStudentResults([FromBody]List<string> userSocs, [FromBody]int collegeId)
{
    var college = await _collegeService.GetCollegeByID(collegeId);
    // var occupations = await _laborMarketService.GetOccupationProgramsBySocsAndCollege(userSocs, college);
    return Ok();
}

这是我通过 Postman 发送的有效负载的样子:

{
    "userSocs": [
            "291123",
            "291171",
            "312021",
            "291071",
            "152031",
            "533011"
        ],
    "collegeId": 1
}

我确保我已将邮递员设置为 POST,Content-Type application/json。我究竟做错了什么?

【问题讨论】:

    标签: c# asp.net-core http-post


    【解决方案1】:

    您总是会得到null,因为您只需要将所有帖子变量封装在一个对象中。像这样:

    public class MyPostModel {
        public List<string> userSocs {get; set;}
        public int collegeId {get; set;}
    }
    

    然后

    public async Task<IActionResult> GetStudentResults([FromBody] MyPostModel postModel)
    

    【讨论】:

    • 这在 .NET 4.5 中不是问题,是吗?我可以发誓我记得在 POST 中发送了多个参数
    • @AlexKibler:仅当您通过表单发送参数或获取查询时。您的主体中只能有一个模型,因此任何非基本类型(int、string 等)都将被序列化为第一个模型。在 ASP.NET Core(独立于 4.5 或 .NET Core)中,您只能有一个 FromBody(在 WebApi 2.x 中它是隐式的),因为 WebAPI 和 MVC 现在合并到一个框架中,它们以前是不同的框架
    【解决方案2】:

    如果模型为空,检查:

    1) 数据发送到哪里:正文,表单?并在此基础上将装饰器添加到操作中。例如:

    [HttpPost]
    public JsonResult SaveX([FromBody]MyVM vm) { ... }
    

    2) 检查ModelState:如果无效则vm不会被绑定,所以为null。

    if (ModelState.IsValid) { ... }
    

    【讨论】:

    • 我花了很多时间调试为什么我得到 null FormData,一切都很好,但我的请求数据无效。所以我的两分钱,请在您的方法的第一行添加if (!ModelState.IsValid) { ... },以首先检查您是否拥有正确的模型:) 首先是
    • 正确,这就是我在第二点描述的内容。事实上,您可以创建一个检查 Model.IsValid 的操作过滤器,如果它无效,则将验证消息返回给客户端。这样您就不必在每一个操作中都执行此操作。
    • ModelState.IsValid 是一个很好的故障排除建议!
    • 老兄,这半天我一直在摸不着头脑。原来 ModelState 是无效的。谢谢兄弟!
    【解决方案3】:

    模型绑定失败(始终为空)的另一个原因是属性的数据类型不匹配。例如这里是一个简单的模型:

    public class MyService {
        public string JobId { get; set; }
        public int ServiceType {get; set;}
    }
    

    这是一些不匹配的 json:

    {"JobId":1, "ServiceType":1}
    

    我在使用 jquery 的 .data 函数检索 JobId 时遇到了这个问题,它会自动将其转换为 int。改用 .attr 函数来修复它。

    【讨论】:

    • 你用这个答案拯救了一天。我有一个 int 字段,它由 axios 作为字符串发送(例如“99”而不是 99)。对我来说很奇怪的是绑定系统不会创建对象并绑定它可以绑定的字段。以这种方式调试似乎要容易得多。您还会认为它可以在某些数据类型之间进行转换。
    【解决方案4】:

    如果你想发送两个或更多模型,你应该使用这个例子:

    [HttpPost]
    public async Task<ActionResult> addUsuario([FromBody] Newtonsoft.Json.Linq.JObject datos)
    {
        Usuarios user = datos["usuario"].ToObject<Usuarios>();
        Empresas empresa = datos["empresa"].ToObject<Empresas>();
        return Json(await _srv.addUsuario(user, empresa));
    }
    

    【讨论】:

    • 或者创建一个包含这两个模型的模型。我宁愿远离 JObect
    【解决方案5】:

    另外,请确保参数类中的这些变量声明为 Public,(否则它们将继续返回为 null)..

    【讨论】:

    • 谢谢!错过了那个简单的事情,这条评论为我节省了很多时间。
    【解决方案6】:

    我知道这与你的情况无关,但我还是在这里发布我的答案。

    这是我在代码中犯的一个愚蠢的错误。我刚刚复制了我的一个Get 请求并将其更改为Post 请求,并忘记用[FromBody] 装饰参数。如果其他人有同样的问题,请确保您使用[FromBody]装饰参数。

    [HttpPost]
    public IApiResponse Update([FromBody] User user) {
        if (user == null) return new ApiBadRequestResponse(ModelState);
        return _userService.Post(user) ? new ApiOkResponse(user) : new ApiResponse(500);
    }
    

    【讨论】:

    • 是的,这是我的问题
    【解决方案7】:

    假设 [FromBody] 类由原始数据类型组成;

    1. [FromBody] 已公开
    2. [FromBody] 有一个空的构造函数()
    3. [FromBody] 是可序列化的。

    【讨论】:

      【解决方案8】:

      对我来说,所有值都以 null 的形式出现,因为我的对象有一个未被解析的枚举。如果你有这个问题,我建议在 Startup.cs 中打开枚举解析 this SO

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-04
        • 1970-01-01
        • 2015-11-05
        • 2018-12-26
        相关资源
        最近更新 更多