Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
658 views
in Technique[技术] by (71.8m points)

asp.net mvc - MVC controller : get JSON object from HTTP body?

We have an MVC (MVC4) application which at times might get a JSON events POSTed from a 3rd party to our specific URL ("http://server.com/events/"). The JSON event is in the body of the HTTP POST and the body is strictly JSON (Content-Type: application/json - not a form-post with JSON in some string field).

How can I receive the JSON body inside the controller's body? I tried the following but didn't get anything

[Edit]: When I say didn't get anything I meant that jsonBody is always null regardless of whether I define it as Object or string.

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

Note that I know if I give declare the method with a strongly typed input parameter, MVC does the whole parsing and filtering i.e.

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

However, the JSON we get is very varied, so we don't want to define (and maintain) hundreds of different classes for each JSON variant.

I'm testing this by the following curl command (with one variant of the JSON here)

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 }}}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It seems that if

  • Content-Type: application/json and
  • if POST body isn't tightly bound to controller's input object class

Then MVC doesn't really bind the POST body to any particular class. Nor can you just fetch the POST body as a param of the ActionResult (suggested in another answer). Fair enough. You need to fetch it from the request stream yourself and process it.

[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

}

Update:

for Asp.Net Core, you have to add [FromBody] attrib beside your param name in your controller action for complex JSON data types:

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

Also, if you want to access the request body as string to parse it yourself, you shall use Request.Body instead of Request.InputStream:

Stream req = Request.Body;
req.Seek(0, System.IO.SeekOrigin.Begin);
string json = new StreamReader(req).ReadToEnd();

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...