views:

97

answers:

3

I have a Page that expects a POST Request and returns some JSON. Essentially it's an .ashx Page, but that doesn't really matter.

When using jQuery, I would use jQuery.Post with "json" as dataType to simply make the POST request and get an object back. However, for the current project I mainly use ASP.net AJAX and I don't want to add jQuery just for the call.

For ASP.net AJAX, I only found information on how to call a "traditional" web service though, which means adding a asp:ServiceReference to the ScriptManager and having a "real" Web Service at the end.

Is there a simpler way to make a POST call to a Page? I could live with getting the raw JSON and then manually eval()ing it, but I don't want to create a full asmx web service (deploying them on SharePoint is a bit painful, and my ashx handler works fine)

+2  A: 

Sys.Net.WebServiceProxy.invoke(url, methodName, useGet, parametersDictionary, onSuccess, onFailure, userContext, timeout);

All params optional except the first.

parametersDictionary is like { foo: bar } -- the parameters will be sent as JSON in the body if you are posting, or as parameters on the query string if it is GET (each parameter separately json serialized -- which btw means strings look like "foo", with the quotes).

onSuccess if a callback that takes the data as the first parameter (already deserialized object).

onFailure gets an error object as the first parameter which contains a get_message() method to get the error message, and some other things.

InfinitiesLoop
Oh also note that depending on which version of MS AJAX you are using, your service might need to return the data wrapped up in a 'd'. For example, if your service returns:[1, 2, 3]It should instead return:{ "d": [1, 2, 3] }This is a security measure I won't get into here. If you are using MS AJAX 4 (beta) you don't need this. But you do in 3.5.If you are using the JavaScriptSerializer to generate the JSON, you can get the 'd' by putting your data into a Dictionary<String,Object>, where 'd' is the key, and the value is your object.
InfinitiesLoop
Thanks, but WebServiceProxy seems to only work against a Web Service, not against a simple page that just happens to read stuff from POST. I can't pass in any variables, as parametersDictionary seems to expect a WebService function instead. Request.Form is empty.
Michael Stum
It sends the parameters in the body of the post, but not as key/value pairs. It's just literally JSON in the body of the post. If you're page is expecting a traditional post, not JSON, then yeah, you'll need to use WebRequest directly.
InfinitiesLoop
+1  A: 

You can use the invoke method of the Sys.Net.WebServiceProxy class directly.

The method signature looks like this:

invoke(path, methodName, useHttpGet, parameters, succeededCallback, failedCallback, userContext, timeout);

Assuming that your service actually returns JSON, then the first argument to succeededCallback should be a JSON object.

Bryan Matthews
Thanks, but WebServiceProxy seems to only work against a Web Service, not against a simple page that just happens to read stuff from POST. I can't pass in any variables, as parametersDictionary seems to expect a WebService function instead. Request.Form is empty.
Michael Stum
A: 

Sys.Net.WebServiceProxy wasn't helpful because it seems to expect a real web service at the end - Request.Form was empty on the server side, parametersDictionary seems to be ignored. There also seems to be no override to wire up another executor instead.

I now solved it by manually creating a Sys.Net.WebRequest. I'l going to take a look at the jQuery sources as this approach is a lot more complex/"bare-metal", but as said, I don't want to add a dependency on jQuery if it isn't needed.

var ApplicationFunctions = {
    showDialog: function(someParam, someOtherParam) {
        var sb = new Sys.StringBuilder("Do you really want to do '");
        sb.append(someParam);
        sb.append("' ?");
        var msg = sb.toString();
        if (confirm(msg)) {
            var myWebRequest = new Sys.Net.WebRequest();
            myWebRequest.set_url('SomeService.ashx');
            myWebRequest.set_httpVerb('POST');
            // Manually build POST body. This would need escaping/urlencoding
            // I think if I couldn't guarantee that the parameters are 'clean'
            var bodySb = new Sys.StringBuilder("postParam=");
            bodySb.append(someParam);
            bodySb.append("&anotherPostParam=");
            bodySb.append(someOtherParam);
            var body = bodySb.toString();
            myWebRequest.set_body(body);
            myWebRequest.get_headers()["Content-Length"] = body.length;
            // also check out usercontext to pass additional data into the completed function
            // http://msdn.microsoft.com/en-us/library/bb397436.aspx
            myWebRequest.add_completed(ApplicationFunctions.onCallCompleted);
            myWebRequest.set_timeout(10 * 1000); // 10 seconds
            myWebRequest.invoke();
        }
    },
    onCallCompleted: function(response) {
        if (response.get_timedOut()) {
            alert("Timed Out!");
            return;
        }
        if (response.get_statusCode() !== 200) {
            alert("Status Code not OK");
            return;
        }
        if (!response.get_responseAvailable()) {
            alert("No data available?!");
            return;
        }
        // Better use a JSON parser
        // http://www.json.org/js.html
        var responseData = eval('(' + response.get_responseData() + ')');
        alert("Success: " + responseData.SomeField);
    }
}
Michael Stum
There is also a built-in JSON parser, Sys.Serialization.JavaScriptSerializer: http://msdn.microsoft.com/en-us/library/bb384128.aspx
Michael Stum