MVC控制器:是否从HTTP主体获取JSON对象?

50pmv0ei  于 2023-02-14  发布在  其他
关注(0)|答案(6)|浏览(141)

我们有一个MVC(MVC 4)应用程序,它有时可能会从第三方获得一个JSON事件POST到我们的特定URL(“http://server.com/events/“)。JSON事件在HTTP POST的主体中,并且主体是严格的JSON(Content-Type: application/json-不是在某个字符串字段中包含JSON的表单发布)。
我怎样才能在控制器的主体中接收JSON主体呢?我尝试了以下方法,但是没有得到任何结果

[编辑]:当我说 * didn 't get anything* 时,我的意思是jsonBody总是null,不管我将其定义为Object还是string

[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 }}}
mzaanser

mzaanser1#

似乎如果

  • 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,对于复杂JSON数据类型,必须在控制器操作中的参数名旁边添加[FromBody]属性:

[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();
3vpjnl9f

3vpjnl9f2#

使用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

flseospp

flseospp3#

我一直在尝试让我的ASP.NET MVC控制器解析我使用Postman提交给它的一些模型。
我需要以下内容来让它工作:

  • 控制器作用
[HttpPost]
[PermitAllUsers]
[Route("Models")]
public JsonResult InsertOrUpdateModels(Model entities)
{
    // ...
    return Json(response, JsonRequestBehavior.AllowGet);
}
  • a模型类
public class Model
{
    public string Test { get; set; }
    // ...
}
  • Postman 请求的标头,具体为Content-Type

  • 请求正文中的json

eufgjt7s

eufgjt7s4#

一旦您定义了一个类(MyDTOClass)来指示您期望接收的内容,它就应该像...

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

感谢Julias:
Parsing Json .Net Web Api
确保您的请求与http标头一起发送:
内容类型:应用程序/json

brtdzjyr

brtdzjyr5#

您可以获取json字符串作为ActionResult的参数,然后使用JSON.Net序列化它
HERE显示了一个示例
为了以序列化的形式接收它作为控制器动作的参数,你必须编写一个定制的模型绑定器或动作过滤器(OnActionExecuting),以便json字符串被序列化到你喜欢的模型中,并且在控制器主体中可用。
HERE是使用动态对象的实现

rggaifut

rggaifut6#

如果你用Content-Type: application/json从 Postman 身体发送原始数据,那么它被认为是流数据。请找到下面的方法来获得它。

[HttpPost]
public async Task<IActionResult> Post()
{
            
    string Header_Value = string.Empty;
    if (Request.Headers.TryGetValue("Sequeritykey", out var headerValues))
    {
       Header_Value = headerValues;
    }
           
    StreamReader requestReader = new StreamReader(Request.Body);
    JObject request = JObject.Parse(await requestReader.ReadToEndAsync());
    return Ok();
}

相关问题