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 }}}
share|improve this question
so how will you parse hundreds of different variants of JSON then, using if/else? – TheVillageIdiot Oct 24 '12 at 1:54
@TheVillageIdiot: they are dumped to logs as a one JSON object each. So that's why I only care about them as a JSON object or a string - don't care what's inside them. – Sid Oct 24 '12 at 2:07

3 Answers

you can get the json string as a param of your ActionResult and afterwards serialize it using JSON.Net

HERE an example is being shown


in order to receive it in the serialized form as a param of the controller action you must either write a custom model binder or a Action filter (OnActionExecuting) so that the json string is serialized into the model of your liking and is available inside the controller body for use.


HERE is an implementation using the dynamic object

share|improve this answer
you can get the json string as a param of your ActionResult - how? That's the original question as I'm unable to get jsonBody with data. jsonBody == null even if I define jsonBody as string or Object ! – Sid Oct 24 '12 at 6:00
up vote 1 down vote accepted

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

    }
share|improve this answer

use Request.Form to get the Data

Controller:

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

I write this to try

View:

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

and write Request.Form[0] or Request.Params[0] in controller can get the data.

I don't write <form> tag in view.

share|improve this answer
There is no form in the HTML POST body - the body of the HTML POST is pure json. So Request.Form[0] = null (it's count is 0). – Sid Oct 24 '12 at 6:08
Not having a <form> tag doesn't matter - the HTTP header from your code is Content-Type: application/x-www-form-urlencoded; charset=UTF-8. Check the output in fiddler. That's what makes it looks like a FORM submission. – Sid Oct 24 '12 at 8:17

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.