I have a button on a website which sends an AJAX request to a .NET HTTPHandler. In the ProcessRequest method of this handler, it then took the query string parameters, and created a new WebRequest to another URL and appended the parameters onto it.
However, the AJAX request has been changed to use POST rather than GET (amongst other things).
This is what I need to do:
public void ProcessRequest(HttpContext context)
{
// Take POST data from request and create a new request
// with it to another URL
}
What makes it more complicated is that the POST data contains multiple arrays all called 'points' which hold latitude, longitude and altitude. So I can't use context.Request["points"] as that doesn't return an array of my points arrays. And I've tried using context.Request.Form.GetValues("points") but that doesn't seem to work, presumably because the data wasn't submitted as a form.
Edit:
AJAX request is:
$.ajax({
url: self.stationsAllFile,
data: data,
type: 'POST',
success: function (response) {
// store stations as kml string
self.stationsCurrent = response;
self.showStations(self.stationsCurrent, false);
self.listStations(self.stationsCurrent, finishedLoading);
var stations = $.parseXML(response),
$stations = $(stations),
$placemarks = $stations.find('Placemark');
$placemarks.each(function () {
var $placemark = $(this),
latLng = $placemark.find('coordinates').text(),
latLngSplit = latLng.split(','),
lng = latLngSplit[0],
lat = latLngSplit[1];
excludePoints.push(lng + ',' + lat + ',0.000000');
});
// do we need to go again?
if(endPoint < route.length) {
self.processRoute(route, endPoint + 1, excludePoints);
}
},
error: function () {
self.showError(self.language.errors.unknownError);
},
dataType: 'text'
});
Example POST data (pasted from Fiddler):
points%5B%5D=-2.2349300000000003%2C53.48073%2C0.000000&points%5B%5D=-2.26805%2C53.559020000000004%2C0.000000&type=route
Related
Overview: Here is an summed up description of what I'm doing - I have a C# application that's running constantly that contains a HTTPListener and waits for a request. Then there is a MVC Web Application where on one of the pages is a button that fires some JS that does an ajax post to the address that the HTTP Listener is listening on, when that button is clicked, the listener catches this request then the C# application performs some other job (not relevant to the problem) and then produces a byte array. This byte array is then sent back as part of the response to the original request, and so the success function of the ajax post that made the request is triggered with the byte array in the success function's data parameter. Now another ajax post is made, but this time to a MVC controller so that the byte array can be saved in my db:
Here is some code.
First, Here is the ajax post that makes the request to the HTTP Listener, the data passed along with the post is just some metadata that I use (for now ignore the code in the success function):
$.ajax({
type: "POST",
url: 'http://127.0.0.1:8089/',
data: '{ "Action":"Enroll", "RefUser":"6" }',
crossDomain: true,
success: function (data) {
//Code that posts array to server to be saved in DB
}); //end of ajax
And here is the HTTP Listener's callback method that catches the request and sends the response:
var context = listener.EndGetContext(listenerresult);
Thread.Sleep(1000);
var data_text = new StreamReader(context.Request.InputStream,context.Request.ContentEncoding).ReadToEnd();
//functions used to decode json encoded data.
JavaScriptSerializer js = new JavaScriptSerializer();
RequestConfiguration RequestConfig = (RequestConfiguration)js.Deserialize(data_text, typeof(RequestConfiguration));
byte[] templateDataArray = null;
//Do some work and assign value to the byte array, 'templateDataArray'
//I append a status code and a message to the array of bytes and send everthing back as a response
//The values are split using the '<>' characters.
byte[] msgDataArray = System.Text.Encoding.UTF8.GetBytes("1<>Success" + "<>");
byte[] responseArray = new byte[msgDataArray.Length + templateDataArray.Length];
msgDataArray.CopyTo(responseArray, 0);
templateDataArray.CopyTo(responseArray,msgDataArray.Length);
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();
Looking now at the success function from the original ajax post:
...
success: function (data) {
//Code that posts array to server to be saved in DB
var returnArray = data.split("<>");
if (returnArray[0] === "1") {
alert(returnArray[1]);
$("#Loader").addClass('hide');
$.ajax({
type: "POST",
url: '#Url.Action("EnrollFingerprintToDB")',
dataType: 'json',
data: { enrollData: NewID + '<>' + returnArray[2] },
success: function (data) {
alert(data.msg);
}
});//end of inner ajax
} //end of if
} //end of success
...
When I do a sample run, here is what I get back in the success function, lets look at the data after it has been split (the var 'returnArray'):
Note that we now post returnArray[2] to the MVC controller, which contains the byte array (encoded as a string right now). Here is the mvc controller that catches that post:
[HttpPost]
public ActionResult EnrollFingerprintToDB(string enrollData)
{
string[] sDataParts = enrollData.Split(new[] { "<>" }, StringSplitOptions.None);
var bytes = System.Text.Encoding.UTF8.GetBytes(sDataParts[1]);
if (FingerprintBLL.InsertFingerprintTemplate(int.Parse(sDataParts[0]),bytes))
{
return Json(new { success = true, msg = "Template successfully saved" });
}
else
{
return Json(new { success = true, msg = "Template could not be saved" });
}
}
What concerns me and what my question is
Why is the array that I send off from the listener different from the one I finally read in the MVC controller? The reason I say that is, Here is the byte array sent from the Listener:
And here is the array the is received at the MVC controller:
As you can see the MVC Controller Action takes in a string that is split into two and the second part is converted to a byte array, and that second part is the byte array in string form received from the listener (take another look at that second ajax post and you'll see it).
I Believe that I'm taking the incorrect approach to send and receive byte data.
I am trying to do something like send an array from js to controller using ajax request. And after some processing I want to redirect to that action with result.
Following is the code...
JavaScript
var arr = ['1','2','3','4'];
function CheckOut()
{
$.ajax({
url: '/Admin/AdminPanel/ProceedToBill',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({ morder: arr }),
success: function (result) {
}
});
}
Controller`
[HttpPost]
public ActionResult ProceedToBill(int[] morder)
{
// morder = [deal_id , quantity]
List<MyModels.CartModel> cart = new List<MyModels.CartModel>();
MyModels.CartModel item = new MyModels.CartModel();
for (int i = 0; i < morder.Length; i+=2 )
{
item.deal = db.Deals.Find(morder[i]);
item.qty = morder[i + 1];
item.price = item.deal.Price * item.qty;
cart.Add(item);
}
return View(cart);
}
So, the problem is there that's an ajax request not a simple one. So I cant return a View. What should I do here now. Please help me.
That's not what Ajax is for. Your Ajax calls should return JSON data. If you want to redirect the user after a successful HTTP call then you'll need to do it client side with Javascript, e.g. window.location = redirect_uri.
I am done. Simply I just received the complete DOM in my result variable in success method. I updated the dom with that result...:)
I am trying to simply write out some data to my webpage as a result of a callback. Everything works up until the point where I need to output the result of the callback.
Client-side:
function toServer(data) {
var dataPackage = data + "~";
jQuery('form').each(function () {
document.getElementById('payload').value = JSON.stringify({ sendData: dataPackage });
$.ajax({
type: "POST",
async: true,
url: window.location.href.toString(),
data: jQuery(this).serialize(),
success: function (result) {
//this does not work because it just puts an entire source code copy of my site in there instead...
//document.getElementById('searchResults').value = result
console.log("callback compelete");
},
error: function(error) {
console.log("callback Error");
}
});
});
}
Server-Side: (on page load)
//holds actions from page
string payload = HttpContext.Current.Request.Form["payload"] ?? String.Empty;
// See if there were hidden requests (callbacks)
if (!String.IsNullOrEmpty(payload))
{
string temp_AggregationId = CurrentMode.Aggregation;
string[] temp_AggregationList = temp_AggregationId.Split(' ');
Perform_Aggregation_Search(temp_AggregationList, true, Tracer);
}
else
{
HttpContext.Current.Session["SearchResultsJSON"] = "";
}
The rest of the server-side code works properly and just handles the parsing of the incoming and performs a search of the db and then parses the search results into a JSON obj.
Currently, the only way the json obj gets written to the page is if I call it without the callback (just call it on page load). Also, in firebug, it looks like the entire page source is posting back as the 'result' of the callback. I do see my json result within the posted back 'result' but it also contains the entire page HTML.
Moreover, I can't seem to get the result to post to the page which is the whole point. Actually, I could get the result to post to the page by simply uncommenting that bit in the client side code but it posts a copy of my site and not the actual result I thought I created...
What am I missing? How do you explicitly state in the C# code what is returned to the JS callback as 'result'?
You get the entire page because you're making a request to an ASP.NET page. In fact, you're requesting the vary same page you're viewing. The server is returning what it would return if you were submitting a form.
To get JSON data, you need to create a web method to handle your request. Read this article, it will help you. It shows you how to return simple text, but you can return JSON too. Information on this MSDN article.
Finally, to make sure jQuery is parsing the server response as JSON, change your request and indicate it explicitly:
function toServer(data) {
var dataPackage = data + "~";
jQuery('form').each(function () {
document.getElementById('payload').value = JSON.stringify({ sendData: dataPackage });
$.ajax({
type: "POST",
async: true,
url: window.location.href.toString(),
data: jQuery(this).serialize(),
dataType: 'json',
success: function (result) {
//this does not work because it just puts an entire source code copy of my site in there instead...
//document.getElementById('searchResults').value = result
console.log("callback compelete");
},
error: function(error) {
console.log("callback Error");
}
});
});
}
I have a usercontrol in a VisualWebPart project.I want to have an ajax call to get a json data and use it in a Jquery plugin.
in simple web applications I use a webservice that returns JSON data and call It in my pages via Ajax,that sounds like I cant use webservices and even Web Methods in my .ascx control,so how can I call a method in my UserControl to get JSON data.
EDIT: I have this code and I want to do this in a UserControl ,too.
in WebService:
public class getTimeLineService : System.Web.Services.WebService
{
[WebMethod]
public String getJsonTimeLine()
{
List<TimeLine> list = new List<TimeLine> { new TimeLine { headline = "Vine", text = "<p>Vine Test</p>", startDate = "1391,12,12", endDate = "1392,1,27" }, new TimeLine { headline = "Sh*t Politicians Say", text = "<p>In true political fashion, his character rattles off common jargon heard from people running for office.</p>", startDate = "1392,1,26", endDate = "1392,1,27" } };
System.Web.Script.Serialization.JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
StringBuilder sb = new StringBuilder();
serializer.Serialize(list, sb);
return sb.ToString();
}
}
and consume this WebService by ajax:
$.ajax({
type: "POST",
url: "getTimeLineService.asmx/getJsonTimeLine",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
var jsonDate = eval( data.d );
},
failure: function (msg) {
alert(msg);
}
});
You can call a webmethod on the page and have the page's method pull from the server code. You could set a session value in the control and pull from that via your webmethod. As controls aren't pages, they're not actually serving anything, only being rendered.
As your using a static webmethod, you'll need to use HttpContext to get your session data.
http://msdn.microsoft.com/en-us/library/system.web.httpcontext.session.aspx
Edit
Store your data from the user control in session:
Session["MyData"] = myDataObj;
You can access Session through your WebMethod this way:
var myRetrievedDataObj = HttpContext.Session["MyData"];
You can return serialized JSON from server objects and collections using the JavaScriptSerialzer class. http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.aspx
You then return that string to your AJAX call and you have your JSON data.
This is my jquery code to call web api
var request = {
RequestId: "123",
DeviceId: "ACU-B2-01-R1",
AccessType: "Unlock",
LoginId: "tester",
Password: "tester"
};
$.ajax({
url: 'http://localhost:55208/api/accesspanel',
type: 'POST',
data: JSON.stringify(request),
dataType: 'jsonp',
contentType: "application/json;charset=utf-8",
success: function (data) {
alert("success");
alert(JSON.stringify(data));
},
error: function (x, y, z) {
alert(x + '\n' + y + '\n' + z);
}
});
When I run this code, nothing happens. Neither the success nor error block gets fired. After checking in the debug console of chrome, this is the error record:
GET http://localhost:55208/api/accesspanel?callback=jQuery18203847100134007633_…22,%22LoginId%22:%22tester%22,%22Password%22:%22tester%22}&_=1364916423737 405 (Method Not Allowed)
send jquery.min.js:2
p.extend.ajax jquery.min.js:2
(anonymous function)
I am, however, able to call my web api method successfully using C# code, which looks like this:
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:55208/");
var request = new DeviceAccessRequest
{
RequestId = Guid.NewGuid().ToString(),
DeviceId = "ACU/B2/01/R1",
AccessType ="Unlock",
LoginId = "tester",
Password = "tester" ,
};
var response = client.PostAsJsonAsync("api/accesspanel", request).Result;
if (response.IsSuccessStatusCode)
{
var deviceAccessResponse = response.Content.ReadAsAsync<DeviceAccessResponse>().Result;
}
}
And this is my web api method:
[HttpPost]
public HttpResponseMessage PostDeviceControl(DeviceAccessRequest deviceAccessRequest)
{
var deviceAccessResponse = new DeviceAccessResponse(deviceAccessRequest.RequestId)
{
Status = "OK"
};
var response = Request.CreateResponse<DeviceAccessResponse>(HttpStatusCode.OK, deviceAccessResponse);
return response;
}
The reason you are seeing a GET request in your console is because you specified dataType: 'jsonp' which works only with GET requests (the reason for that is because jQuery translates this to a <script> tag pointing to the url you specified). If you want to be doing cross domain AJAX with other verbs than GET you cannot use JSONP. If you need to use other verbs (such as POST in your case) you have 2 options:
CORS. Take a look at the following video which illustrates how you could enable CORS on your Web API. Obviously for this to work your client side browser need tio support it
Server side bridge on your domain. The idea here is to have some server side script on the domain hosting your javascript code that will send the HTTP request to the API and return the response to the client. Then you will send a regular AJAX POST request to your own domain