0

I've got an action on a controller that is used to process requests from a payment gateway. They send json in the request's body to a url on my server that executes this action. This code is working fine when they send their data:

[ValidateInput(false)]
public ActionResult WebHookHandler()
{
    var json = new StreamReader(Request.InputStream).ReadToEnd();
    if (string.IsNullOrEmpty(json))
        return new HttpStatusCodeResult(400); // bad request

    ...

    // return ok status
    return new HttpStatusCodeResult(200); // ok
}

The problem is I want to test this action on my end by submitting test data to it but I can't get it to work. Everything I've tried results in a 400 response which means the json I sent wasn't extracted on the server side. I think MVC 3 is trying to be too smart and is handling the json I'm sending it in a manner that doesn't allow it to be retrieved from the Request.InputStream property because that property is always empty on any ajax configuration I've tried.

I've tried all kinds of combinations like stringify the data, setting the processData to false, different contentType's and nothing is letting the data go through in a manner that allows my server-side code to grab it from the Request.InputStream.

Here is what my javascript looks like:

var data = $("#stripeJSON").val();

$.ajax({
    url: "http://localhost/PaymentStripe/WebHookHandler",
    type: "POST",
    data: data,
    processData: true,
    contentType: "application/json",
    success: function (data, textStatus, jqXHR) {
        $("#result").html("success");
    },
    error: function (jqXHR, textStatus, errorThrown) {
        $("#result").html("failed:<br/>" + textStatus + errorThrown);
    },
    complete: function (jqXHR, textStatus) {
    }
});

And here is some dummy json data:

{
    "pending_webhooks": 1,
    "type": "invoice.payment_succeeded",
    "object": "event",
    "created": 1347318097,
    "livemode": false,
    "id": "evt_0LMvt7Q9vL1oFI",
    "data": {
        "object": {
            "currency": "usd",
            "ending_balance": null,
            "customer": "cus_0LMvSw8LEmOcJG",
            "discount": null,
            "id": "in_0LMvHGx1XutT7p",
            "object": "invoice",
            "amount_due": 0,
            "date": 1347318097,
            "total": 0,
            "subtotal": 0,
            "charge": null,
            "period_end": 1347318097,
            "next_payment_attempt": null,
            "livemode": false,
            "attempted": true,
            "period_start": 1347318097,
            "starting_balance": 0,
            "lines": {
                "subscriptions": [{
                    "quantity": 1,
                    "period": {
                        "end": 1349910097,
                        "start": 1347318097
                    },
                    "amount": 0,
                    "plan": {
                        "livemode": false,
                        "trial_period_days": null,
                        "amount": 0,
                        "object": "plan",
                        "name": "ZeroMonthly",
                        "id": "ZeroMonthly",
                        "interval_count": 1,
                        "currency": "usd",
                        "interval": "month"
                    }
                }],
                "prorations": [],
                "invoiceitems": []
            },
            "paid": true,
            "closed": true,
            "attempt_count": 0
        }
    }
}

Suggestions?

TugboatCaptain
  • 4,150
  • 3
  • 47
  • 79
  • 1
    Did you try looking at the what is being sent across in Fiddler or some other http sniffer? Compare what you are sending to what "they" are sending. What is the difference? You are making a POST request in your ajax call but you are not using the HttpPost attribute on your action so that it is mapped correctly. – Kevin Junghans Sep 11 '12 at 13:12
  • Try to call `Request.InputStream.Position = 0;` before `ReadToEnd` – nemesv Sep 11 '12 at 13:16
  • @KevinJunghans, thanks, that led me to a fix. I had to do this to get my data into an object format that was good for posting: data = JSON.parse(JSON.stringify(data)); – TugboatCaptain Sep 11 '12 at 14:01

2 Answers2

0

I think the issue is the sending of the URL ... Try looking here. I had the same issue.

Community
  • 1
  • 1
Mihai Labo
  • 1,082
  • 2
  • 16
  • 40
  • It's not a url issue. The url is responding to requests and I am able to set and stop on breakpoints in the code for this action. It just doesn't see anything in the Request.Inputstream when posting through a jquery ajax call. – TugboatCaptain Sep 11 '12 at 13:05
0

So as mentioned in the comments this was fixed by modifying this line:

from this:

var data = $("#stripeJSON").val();

to this:

var data = JSON.parse(JSON.stringify($("#stripeJSON").val()));

The “stripeJSON” field is a textarea on the form and jquery was sending it as a string literal rather than an actual json object.

TugboatCaptain
  • 4,150
  • 3
  • 47
  • 79