Marnus Steyn Marnus Steyn - 5 months ago 46
jQuery Question

Using HttpListener With Angular's $http.post Instead Of jQuery.Ajax

To break it down simple - On my Web Application side, I post some data to C# Application that is running a HttpListener, this request is caught by the Listener, then some action is completed, lastly a response is sent back to the Web Application in response to the original post.

Here is the Callback Method that is used once the Listener catches a request

private void ListenerCallback(IAsyncResult listenerresult)
{
var context = listener.EndGetContext(listenerresult);
Thread.Sleep(1000);
var data_text = new StreamReader(context.Request.InputStream,
context.Request.ContentEncoding).ReadToEnd();

//Do some work and create the 'responseArray' that is sent back containing some message

var response = context.Response;
response.ContentLength64 = responseArray.Length;
response.Headers.Add("Access-Control-Allow-Origin", "*");
response.Headers.Add("Access-Control-Allow-Methods", "POST, GET");
response.StatusCode = 200;
response.StatusDescription = "OK";
response.OutputStream.Write(responseArray, 0, responseArray.Length);
response.OutputStream.Close();
}


When I use a jQuery Ajax Post to reach the Listener and send it some data it works beautifully, and that variable
data_text
is populated with what I sent. Here is the Ajax Post I use:

jQuery.ajax({
type: "POST",
url: 'http://127.0.0.1:8089/',
data: '{"Variable 1":"Value 1", "Variable 2":"Value 2"}',
crossDomain: true,
success: function (data) {

// Use data here

}
}).fail(function (jqXHR, textStatus, errorThrown) {
alert('Alert user that something went wrong');
});


I now have to move my implementation over to angular, and this is where the problem comes in. When using Angular's $http.post, the Listner does catch the request however the data_text variable is always empty i.e. the data read from the request's data stream is empty. Here is the $http.post I use - Note: I use a service that wraps the $http.post to save time when using Angular's post:

httpService.post('http://127.0.0.1:8089/', data).then(function (result) {
alert(result.msg);
});


And here is the service used to perform the post shown above:

app.service('httpService', function($http, $q) {
this.post = function (url, data) {
try {
return $http.post(url, data || {}, { timeout: 1000 * 20 }).then(function (response) {
if (response.data.success) {
return response.data.obj;
} else {
return ($q.reject(response.data.msg));
}
}, function (error) {
if (error.status === 0) {
return ($q.reject('408' + ' : The server timed out waiting for the request, please try again'));
}
return ($q.reject(error.status + ' : ' + error.statusText));
});
} catch (e) {
alert(e.message);
return $q.reject(e.message);
}
}
});


As far as I know, Angular is built ontop of a lite version of jQuery and when you get to the lowest level(vanilla JS), the jQuery Ajax Post is doing the same thing as the $http.post. What am I missing?

Update: As Mike Feltman pointed out, I can use $httpParamSerializerJQLike on my data and specify the content type in the header:

return $http.post(url, $httpParamSerializerJQLike(data), { headers: { 'Content-type': 'application/x-www-form-urlencoded'}})


This works and I receive data, but in a format I can't use, I need my data in JSON format, so I read up a bit and changed the Content-Type from
application/x-www-form-urlencoded
to
application/json
, but then I once again receive no data.

Answer

You are probably running into differences with how Angular sends post data vs. Jquery. To get around this you have to inject $httpParamSerializerJQLike into your service and then specify to use it on your call to http.post by sending your data to a call to it with something like: $httpParamSerializerJQLike(myData).

This is the angular doc on it: https://docs.angularjs.org/api/ng/service/$httpParamSerializerJQLike

I have a working sample that I can't get to at this moment, but can dig it up later if that's not enough to get you going.

I had a few issues in my service getting it to behave and since I also wrap $http I use something like this:

var transport = $httpParamSerializerJQLike(data);
return $http.post(url, transport, { headers: { 'Content-type': 'application/x-www-form-urlencoded'}})
Comments