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");
}
});
});
}
Related
I have an array of file names:
[HttpPost]
public JsonResult GetJSONFilesList()
{
string[] filesArray = Directory.GetFiles("/UploadedFiles/");
for (int i = 0; i < filesArray.Length; i++)
{
filesArray[i] = Path.GetFileName(filesArray[i]);
}
return Json(filesArray);
}
I need this in AngularJS as a list of objects so I can ng-repeat it out and apply filters. I'm unable to figure out how to get the JSON from the MVC controller to AngularJS.
I've tried the following to make it visible to the view for angular to grab, but I don't know how to make the ng-init see the function to return the list. It erros on "SerializeObject(GetJSONFilesList())" saying it doesn't exist in current context.
<div ng-controller="MyController" data-ng-init="init(#Newtonsoft.Json.JsonConvert.SerializeObject(GetJSONFilesList()),
#Newtonsoft.Json.JsonConvert.SerializeObject(Model.Done))" ng-cloak>
</div>
EDIT:
I've tried using http.get.
Test one:
alert('page load');
$scope.hello = 'hello';
$http.get('http://rest-service.guides.spring.io/greeting').
then(function (response) {
$scope.greeting = response.data;
alert($scope.greeting);
});
alert($scope.hello);
The alert in the http.get never fires, the other alerts do however.
Test two:
$http({
url: '/Home/testHello',
method: 'GET'
}).success(function (data, status, headers, config) {
$scope.hello = data;
alert('hi');
});
[HttpPost]
public string testHello()
{
return "hello world";
}
This causes the angular to break and nothing in the .js works.
Test three
alert('page load');
$scope.hello = 'hello';
$scope.GetJSONFilesList = function () {
$http.get('/Home/testHello')
.success(function (result) {
$scope.availableFiles = result;
alert('success');
})
.error(function (data) {
console.log(data);
alert('error');
});
alert('hi');
};
alert($scope.hello);
[HttpPost]
public string testHello()
{
return "hello world";
}
Alerts nothing from within it, other alerts work.
Fixed:
After some googling, I've found that using .success and .error are deprecated and that .then should be used. So by using .then this resulted in the C# being hit via debug.
Then after using console.log on the returned value found that to have anything be returned I needed to return the value from C# using "return Json(myValue, JsonRequestBehavior.AllowGet); "
And by viewing the object in the console in Chrome by using console.log, I could see my values were in the data part of the returned object.
It was stored in data as an array (as I was passing an array).
I could then get the data out of there by assigning the returned value.data to a scope and could call that in the view {{result[1]}} etc.
return Json(filesArray, JsonRequestBehavior.AllowGet);
$scope.fileList;
$http.get("/Home/GetFileList").then(function (result) {
console.log(result)
$scope.fileList = result.data;
})
Imagine that you divide your front end in three layers (MVC or MVVM) whatever you want.
When you need info from server, the best practice is to separate the logic that makes the request and the logic that manipulates the data.
More info about how to make the request you can find it reading about REST APIS in Consuming a RESTful Web Service with AngularJS.
Normally one of the layers requires the use of services and you can have your controllers and your services (the place where you get the raw data from the server and you make the request. For that you need to use the $http service from angularjs.
$http: The $http service is a core AngularJS service that facilitates communication with the remote HTTP servers via the browser's XMLHttpRequest object or via JSONP.
So basically it shows you how to make get, post and put requests. One example from the documentation is :
// Simple GET request example:
$http({
method: 'GET',
url: '/someUrl'
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
Pay attention to the url because there is the place where you let your request knwow which method is going to be hit on the server to take the action. If your request is succesful, then you can use the parameter called response. From there, you can do whatever you want. If you decide to make that request part from your controller, you can assign it directly to a variable on your scope. Pay attention if you need to serialize the data. Something like
$scope.myResponseName = response.name ;
The first documentation link from above shows this example which does exactly what I tell you.
angular.module('demo', [])
.controller('Hello', function($scope, $http) {
$http.get('http://rest-service.guides.spring.io/greeting').
then(function(response) {
$scope.greeting = response.data;
});
});
After all the mentioned above, pay attention to what you want to display. Are you going to display the elements of an object array? The use on your HTML the ng-repeat directive. Are you going to display just a variable (No array nor object) then you use need to use an angular expression {{ }}
In summary:
By making an HTTP request, hit the correct method on server.
Make sure you are sending the JSON correctly and that the data is correct.
Retrieve the data on your response.
Assign the data to a variable on your scope and serialize the data if needed.
Display the data correctly depending if it is within an array, if it´s an object or if its just a variable.
I hope the explanation makes sense and check the documentation if you need more info.
You can build your viewmodel so that it contains the data you'd like to serialize and then pass it to angularJS in your view as follows:
<div ng-controller="MyController" data-ng-init="init(#JsonConvert.SerializeObject(myArrayData),
#Newtonsoft.Json.JsonConvert.SerializeObject(Model.Done))" ng-cloak>
and then in your angular controller have a function to receive the data as follows:
$scope.init = function (myArrayData) {
//do something with data
};
The above assumes you're trying to pass data from mvc to angularjs on page load. If you're trying to hit a controller and get data back to angularjs upon some event such as a button click, then you can write an angularjs function similar to the following (this will be an asynchronous request):
app.controller('MyController', function ($scope, $http, $window) {
$scope.ButtonClick = function () {
var post = $http({
method: "POST",
url: "/SomeController/SomeAjaxMethod",
dataType: 'json',
data: { path: $scope.Path},
headers: { "Content-Type": "application/json" }
});
post.success(function (data, status) {
//do something with your data
});
post.error(function (data, status) {
$window.alert(data.Message);
});
}
}
and your controller action would look something like:
[HttpPost]
public JsonResult SomeAjaxMethod(string path)
{
string[] filesArray = Directory.GetFiles(path);
for (int i = 0; i < filesArray.Length; i++)
{
filesArray[i] = Path.GetFileName(filesArray[i]);
}
return Json(filesArray);
}
other answers say to use .success in the angular function, .success and .error are deprecated, instead .then should be used.
Working result:
MVC:
public JsonResult GetFileList()
{
//form array here
return Json(myArray, JsonRequestBehavior.AllowGet);
}
The function needs to be of type JsonResult, and the returned value of Json using JsonRequestBehavior.AllowGet.
AngularJS:
$scope.fileList;
$http.get("/Home/GetFileList").then(function (result) {
console.log(result)
$scope.fileList = result.data;
})
This is in my AJS controller, using .then instead of .success. If you use console.log the result returned from the mvc controller and view it in the browser inspect you'll see the object with lots of other info and the values you want are in the .data section of the object.
So to access the values you need to do result.data. In my case this gives me and array. I assign this to a scope. Then in my view I can access the values by doing {{fileList[1]}} etc. This can also be used in ng-repeat e.g:
<div ng-repeat="file in fileList">
{{fileList[$index]}}
</div>
Each value in the array in the repeat can be accessed using $index which is the number of the repeat starting at 0.
I have an ASP.NET application sending data through AJAX to a handler withing my application. This works as it should when debugging locally, but as soon as I deploy the solution to the server, the handler only receives an empty string. I tried fiddling around with contentType and dataType, but without luck.
Here is my code so far.
aspx of the sending page, while "myData" is a simple string:
$.ajax({
type: "POST",
url: "handlers/changeRiskGroup.ashx",
data: myData,
// tried all those content/dataTypes without any luck
//contentType: "text/plain",
//dataType: "text",
//contentType: "application/json; charset=utf-8",
//dataType: "json",
error: function (xhr, status, error) {
console.log(xhr.responseText);
},
success: function (msg) {
console.log(msg);
}
});
.ashx.cs of the receiving handler:
public void ProcessRequest(HttpContext context) {
//string data = new StreamReader(context.Request.InputStream).ReadToEnd();
var data = String.Empty;
context.Request.InputStream.Position = 0;
using(var inputStream = new StreamReader(context.Request.InputStream)) {
data = inputStream.ReadToEnd();
}
if (data != "") {
// doing something with my data here.
// this is never reached while on the server, but works fine locally!
} else {
context.Response.Write("Please supply data to the risk group service!");
}
}
public bool IsReusable {
get {
return false;
}
}
}
The data variable in the .ashx.cs file is filled when debugging locally, but always "" on the server. I have no clue why.
var para={};
para.myData="abcd"
$.ajax({
type: "POST",
url: "handlers/changeRiskGroup.ashx",
data: para,
error: function (xhr, status, error) {
console.log(xhr.responseText);
},
success: function (msg) {
console.log(msg);
}
});
from server side
string myData=contect.Request.Form["myData"].toString();
Easy, just took me ~20 hours to figure out. Found the answer here: Web service returns "301 error moved permanently" in production environment
In short, I created a blank page within my project to ensure no plugins etc were interfering with the jQuery execution. Further, I created a very simple mask to submit certain data to the handler URL. Within this mask I varied different ways to POST data, when I tried implementing the POST as a [WebMethod] I finally got a clue, as the response was "301 moved permanently" from the WebMethod. Therefore I could start investigating and found out that my server was lowercasing the urls, obviously jQuery/HTTP does not like that.
I hope this post helps others struggling with similar problems.
I have an AJAX request when a branch of my JSSTree is clicked
$("#jstree").bind("select_node.jstree", function(evt, data)
{
var idArgument = data.node.text;
$.ajax(
{
type: "POST",
url: "WebForm1.aspx/brancheSelectionnee",
data: JSON.stringify({ id: idArgument }),
contentType: "application/json; charset=utf-8",
success: function(msg)
{
;
}
});
});
So, I call this function, which make a new "page" (because it's static) and call a function that return a System.Web.UI.WebControls.Table.
public static string brancheSelectionnee(string id)
{
var page = (WebForm1)HttpContext.Current.CurrentHandler;
System.Web.UI.WebControls.Table tableau = page.brancheSelectionneeNonStatique(id);
var stringWriter = new StringWriter();
using (var htmlWriter = new HtmlTextWriter(stringWriter))
{
tableau.RenderControl(htmlWriter);
}
string tableauString=stringWriter.ToString();
return "randomstring";
}
Big problem here: My "tableau" is updated, with what I want (I see this with the htmlWriter) but.. I don't know how put it in my screen!
I have it in my C# code, but I want it in the screen, and not just here.
I have "tableauArticle" which is a real System.Web.UI.WebControls.Table, in my ASP.net code.
I tried some things, like putting "tableauArticle" as Static, then
tableauArticles = tableau;
But I didn't see any changement. I think that I updated a table in the page that I don't display
I think that the main problem is that my pagee isn't refresh or I do my tables wrong.
You do an AJAX request, so there is no page refresh. You just get a string (with HTML) back from your server method. You then have to manually put that string on your page. This happens in the success callback function which in your code is empty. As first step try something like this:
success: function(msg)
{
$('<div class="newtable">').html(msg).appendTo('body');
}
On the server-side your method brancheSelectionnee needs the AjaxMethod attribute so that it can be called with AJAX:
[Ajax.AjaxMethod()]
public static string brancheSelectionnee(string id)
(It also should return tableauString; not "randomstring", right?. And I am not sure if you can use the HttpContext.Current.CurrentHandler there, but that is for a second step if the basic AJAX stuff works.)
Here is one tutorial for all this which gives you an overview.
For the answer, it is 100% Raidri solution :
$('#tableauArticles').empty();
$('<div class="newtable">').html(msg.d).appendTo('#tableauArticles');
this is my function, where i post json only
function test() {
var imgFile = document.getElementById('image');
// var imgData = JSON.stringify(getBase64Image(imgElem));
//var imgData = Convert.FormBase64String(imgElem);
$.ajax({
type: 'POST',
dataType: 'json',
url: "http://localhost:59102/Contacts/AddContact",
data: "json=" + "{\"token\":\"8mVm/nS1OfpU+nlQLbJjqXJ7kJI=VyLGI2GEKkGgtDt0babrAw==\"}",
success: function (returnPayload) {
console && console.log("request succeeded");
},
error: function (xhr, ajaxOptions, thrownError) {
console && console.log("request failed");
},
processData: false,
async: false
});
and i dont know how to add to my data, image, i need to post json and image
this is my controller
[HttpPost]
[AllowAnonymous]
public JsonResult AddContact(string json, HttpPostedFileBase file)
{}
You can't upload files via AJAX (by design) unless you use a plugin that utilises other 'technology' such as flash, or iframes - this is a security measure as JavaScript reading local files on your machine would not be the best idea
There's an option here: http://jquery.malsup.com/form/
...otherwise I suggest looking up one of the many other alternatives!
after you getting the data to a base 64 , your json should be an object
from your controller your json should be something like this
{"json":"something here that is a string","file":"some file"}
Also on the client side you should have a n object on which you invoke JSON.stringify()
var ob = {json:imageDataAsBase64,file:fileDataAsBinary}
although I dont see the reason to send both.
if what you need is just transafering an image that you just need to get the image as base64 and post it as a json
Inside my controller there is JsonResult action which returns me a list of House object.
I want onclick using ajax to retrieve these data and to display json data inside my view.
Inside firebug I'm able to see proper Response and Json result but I dont know how to display inside my view.
function GetTabData(xdata) {
$.ajax({
url: ('/Home/GetTabData'),
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({ id: xdata }),
success: function (result) {
// tried with these but it doesnt work
// result = jQuery.parseJSON(result);
// alert(result.Title);
},
error: function () { alert("error"); }
});
}
public JsonResult GetTabData()
{
...
var temp = getMyData...
return Json(temp, JsonRequestBehavior.AllowGet);
}
// View page
<div id="showContent">
// Json data should appear here
</div>
Inside firebug JSON tab when success:function(result) is empty
I have following data:
Id 149
PropertyType "Apartment"
StreetNumber "202B"
CityName "Sidney"
Title "My test data"
success: function (json) {
var data = null;
$.each(json.items,function(item,i){
data = '<div>'+item.Id+ ' ' + item.CityName +'</div>';
$("#showContent").append(data);
});
}
First of all, you can specify the dataType attribute in your ajax call to 'json' and then don't have to decode the json response again -
dataType: 'json'
Then, you don't need to use parseJSON. Simply use result.Title etc.
success: function (result) {
alert(result.Title);
var showContent = $('#showContent');
showContent.html(result.Id+','+result.Title);
},
EDIT: As Mukesh said, you can have the ajax function return json without using any extra decoding.
The ajax call result is already an object. You can do whatever you want with it it inside the success function.
For example you could create a table of the information dynamically inside the function, or send the data to another function by calling the function inside that success function. Once you leave the success function, the data is not usable anymore.
Access the data object like any object (data.someProperty).