35

This is driving me crazy. I'm using ASP.NET MVC. I have a controller with an HttpPost action that acts as a callback URL that is called by another server (not under my control). I want to dynamically read JSON posted to it without using WebAPI or Model Binding. The URL also has a query string parameter passed to it.

The callback URL looks something like this:

http://domain.com/callback?secret=1234

I've tried reading the posted input using:

[HttpPost]
public ActionResult Callback( String secret )
{
    String jsonData = new StreamReader(this.Request.InputStream).ReadToEnd();

    // ...
}

However "jsonData" is always null or empty.

I just want to get the posted input and stick it into JsonFx so I can dynamically access the contents. Any ideas on how to do this the easiest possible way?

UPDATE

I've discovered the following ...

While the above DOES NOT work (jsonData will be null or empty), the following DOES if I configure what little options I have on the calling server so as to omit the "secret" query string parameter, which is about all I can do on that end since it is not my server. In this case, jsonData will have the correct posted JSON string:

[HttpPost]
public ActionResult Callback( /* String secret */ )
{
    String jsonData = new StreamReader(this.Request.InputStream).ReadToEnd();

    // ...
}

This is very frustrating to work around and I don't know an easy way to accept both a query string and posted JSON data on a standard MVC controller.

I have a "callback controller" with Action methods that accept various data (via GET, via form POST, via JSON POST, via JSON POST w/ a Query String, etc.) from different third-party servers. These are merchant-type callbacks where I have no control over the formats or methods used to convey information. I just need to accept the callbacks and process the information that should be there.

All of it works fine in my Controller, except the case of "JSON POST w/ a Query String".

This appears (at least to me) to be a shortcoming in standard ASP.NET MVC controllers. ???

Can anyone suggest a solution to this that can be used in a standard ASP.NET MVC controller?

lantram
  • 353
  • 1
  • 3
  • 5
  • when you post it, have all the json equal `jsonData`. e.g. `[{jsonData: [{ ... all json stuff ... }]}];` I haven't tested this, but it may work – mnsr Jul 23 '13 at 23:32
  • I have no control over the server that posts the information. I added an update above. – lantram Jul 25 '13 at 12:18
  • why do you select the name 'jsonData'?, the json data could be coming on a different name, try to inspect FormCollection for the name. – tkt986 Jul 25 '13 at 12:26

3 Answers3

64

Your initial approach should work if you take into consideration the fact, that ASP.NET MVC model binding has already read the stream, so you should rewind it:

[HttpPost]
public ActionResult Callback(string secret)
{
    Request.InputStream.Seek(0, SeekOrigin.Begin);
    string jsonData = new StreamReader(Request.InputStream).ReadToEnd();

    // ...
}
tpeczek
  • 23,867
  • 3
  • 74
  • 77
  • 1
    Awesome! Thank you very much. I knew there had to be a simple solution. – lantram Jul 26 '13 at 21:05
  • this does work but any ideas about this http://stackoverflow.com/questions/21441571/get-post-request-parameters-in-custom-authorizeattribute – PUG Jan 29 '14 at 21:39
3

Reset the position to Zero before reading the stream. Request.InputStream.Position = 0

Amruth
  • 5,792
  • 2
  • 28
  • 41
3

For ASP.NET Core 2,this works for me.

    [HttpPost]
    public ActionResult RawTest() {
        using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8))
        {  
            string content = reader.ReadToEndAsync().Result;
            //...
        }
        //...
    }
guogangj
  • 2,275
  • 3
  • 27
  • 44