73

我们有一个 MVC (MVC4) 应用程序,它有时可能会从第 3 方获取一个 JSON 事件 POST 到我们的特定 URL(“ http://server.com/events/ ”)。JSON 事件在 HTTP POST 的正文中,并且正文是严格的 JSON(Content-Type: application/json-不是在某些字符串字段中带有 JSON 的表单发布)。

如何在控制器主体内接收 JSON 主体?我尝试了以下但没有得到任何东西

[编辑]:当我说没有得到任何东西时,我的意思是 jsonBody 始终为空,无论我是否将其定义为Objectstring

[HttpPost]
// this maps to http://server.com/events/
// why is jsonBody always null ?!
public ActionResult Index(int? id, string jsonBody)
{
    // Do stuff here
}

请注意,我知道如果我使用强类型输入参数声明方法,MVC 会执行整个解析和过滤,即

// this tested to work, jsonBody has valid json data 
// that I can deserialize using JSON.net
public ActionResult Index(int? id, ClassType847 jsonBody) { ... }

但是,我们得到的 JSON 是多种多样的,所以我们不想为每个 JSON 变体定义(和维护)数百个不同的类。

我正在通过以下curl命令对此进行测试(此处使用 JSON 的一种变体)

curl -i -H "Host: localhost" -H "Content-Type: application/json" -X POST http://localhost/events/ -d '{ "created": 1326853478, "data": { "object": { "num_of_errors": 123, "fail_count": 3 }}}
4

5 回答 5

157

好像如果

  • Content-Type: application/json
  • 如果 POST 主体没有紧密绑定到控制器的输入对象类

然后 MVC 并没有真正将 POST 主体绑定到任何特定的类。您也不能只获取 POST 正文作为 ActionResult 的参数(在另一个答案中建议)。很公平。您需要自己从请求流中获取并处理它。

[HttpPost]
public ActionResult Index(int? id)
{
    Stream req = Request.InputStream;
    req.Seek(0, System.IO.SeekOrigin.Begin);
    string json = new StreamReader(req).ReadToEnd();

    InputClass input = null;
    try
    {
        // assuming JSON.net/Newtonsoft library from http://json.codeplex.com/
        input = JsonConvert.DeserializeObject<InputClass>(json)
    }

    catch (Exception ex)
    {
        // Try and handle malformed POST body
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }

    //do stuff

}

更新:

对于 Asp.Net Core,[FromBody]对于复杂的 JSON 数据类型,您必须在控制器操作中的参数名称旁边添加属性:

[HttpPost]
public ActionResult JsonAction([FromBody]Customer c)

此外,如果您想以字符串的形式访问请求正文以自己解析它,您应该使用Request.Body而不是Request.InputStream

Stream req = Request.Body;
req.Seek(0, System.IO.SeekOrigin.Begin);
string json = new StreamReader(req).ReadToEnd();
于 2012-10-29T06:26:34.893 回答
7

用于Request.Form获取数据

控制器:

    [HttpPost]
    public ActionResult Index(int? id)
    {
        string jsonData= Request.Form[0]; // The data from the POST
    }

我写这个来试试

看法:

<input type="button" value="post" id="btnPost" />

<script type="text/javascript">
    $(function () {
        var test = {
            number: 456,
            name: "Ryu"
        }
        $("#btnPost").click(function () {
            $.post('@Url.Action("Index", "Home")', JSON.stringify(test));
        });
    });
</script>

并写入Request.Form[0]Request.Params[0]在控制器中可以获取数据。

我不写<form> tag视图。

于 2012-10-24T05:17:27.980 回答
2

我一直试图让我的ASP.NET MVC 控制器解析我使用Postman提交给它的一些模型。

我需要以下内容才能使其正常工作:

  • 控制器动作

    [HttpPost]
    [PermitAllUsers]
    [Route("Models")]
    public JsonResult InsertOrUpdateModels(Model entities)
    {
        // ...
        return Json(response, JsonRequestBehavior.AllowGet);
    }
    
  • 模型类

    public class Model
    {
        public string Test { get; set; }
        // ...
    }
    
  • 邮递员请求的标头,具体来说,Content-Type

    邮递员标题

  • 请求正文中的json

    在此处输入图像描述

于 2019-07-17T17:57:24.523 回答
1

一旦你定义了一个类(MyDTOClass)来表明你期望收到什么,它应该像......

public ActionResult Post([FromBody]MyDTOClass inputData){
 ... do something with input data ...
}

感谢朱莉娅:

解析 Json .Net Web Api

确保您的请求使用 http 标头发送:

内容类型:应用程序/json

于 2017-07-13T14:43:45.573 回答
0

您可以将 json 字符串作为您的参数,ActionResult然后使用JSON.Net对其进行序列化

这里展示了一个例子


为了以序列化形式接收它作为控制器操作的参数,您必须编写自定义模型绑定器或操作过滤器(OnActionExecuting),以便将 json 字符串序列化为您喜欢的模型并在控制器内部可用身体使用。


HERE是使用动态对象的实现

于 2012-10-24T05:26:49.863 回答