Confused with JSON string returned by webservice - ajax

I just started to play around with Kendo-UI, web services and JSON. First I created and deployed my asp.net web service (I did not plan to use WCF). I checked the ASMX file which returned the following result:
[
{"Id":"4e7dc3f8-db50-4978-be10-09808a6216a7","CompanyName":"company1"},
{"Id":"d156a2cd-1768-439e-98eb-134366a6c9be","CompanyName":"company2"},
{"Id":"7acba8b5-b773-4071-bfd5-2537d7d20e1e","CompanyName":"company3"}
]
I checked the above result with a web based JSON validator (copy/paste, not via calling the web service), which resulted in a successful parsing. So far everything seemed to be OK.
The next step was to populate a kendoDropDownList with the results:
var dataSource = new kendo.data.DataSource({
transport: {
read: {
url: "/scws/qpm.asmx/GetSuppliers",
dataType: "json"
}
}
});
$("#supplier").kendoDropDownList({
dataSource: dataSource,
dataValueField: "Id",
dataTextField: "CompanyName"
});
Well, it did not work. I tried several variations, until I gave up and tried to call my web service a different way, just for testing:
$.ajax({
url: "/scws/qpm.asmx/GetSuppliers",
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json",
cache: false,
success: function (msg) {
// data is returned
},
error: function (xhr, status, error) {
// handle error
alert(status);
alert(xhr.status);
alert(xhr.responseText);
alert(error);
}
});
Well, I got a parser error (200). The response text is different from what I got with directly testing the ASMX file. The response text seems to be longer:
[
{"Id":"4e7dc3f8-db50-4978-be10-09808a6216a7","CompanyName":"company1"},
{"Id":"d156a2cd-1768-439e-98eb-134366a6c9be","CompanyName":"company2"},
{"Id":"7acba8b5-b773-4071-bfd5-2537d7d20e1e","CompanyName":"company3"}
]
{"d":null}
I am sure I did some basic thing very badly... I would appreciate your help.

Not know what your asmx method looks like, it's hard to say exactly. Here is a quick sample asmx I threw together. I did go ahead and switch my method to use a GET instead of a POST.
Webservice
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
[System.Web.Script.Services.ScriptService]
public class Service : System.Web.Services.WebService
{
[WebMethod]
[ScriptMethod (UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]
public List<Person> GetPeople()
{
List<Person> people = new List<Person>();
people.Add(new Person() { Age = 21, Name = "Fred" });
people.Add(new Person() { Age = 31, Name = "Ted" });
people.Add(new Person() { Age = 41, Name = "Ned" });
people.Add(new Person() { Age = 51, Name = "Red" });
return people;
}
}
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
Which returned this json
{"d":[{"__type":"ASMXTest.Person","Name":"Fred","Age":21},{"__type":"ASMXTest.Person","Name":"Ted","Age":31},{"__type":"ASMXTest.Person","Name":"Ned","Age":41},{"__type":"ASMXTest.Person","Name":"Red","Age":51}]}
Here is my kendo dataSource to access that webmethod
var dataSource = new kendo.data.DataSource({
transport: {
read: {
url: "Service.asmx/GetPeople",
dataType: "json",
contentType: "application/json; charset=utf-8"
}
},
schema: {
data: function (response) {
return response.d;
}
}
});
$("#grid").kendoGrid({
dataSource: dataSource,
columns: [
{ field: 'Name' },
{ field: 'Age' }
]
});
If this doesn't get you going, please post your asmx webmethod.

Thank you for your help and time. I am afraid the problem was with my webservice. Now its fine.

Related

Session not retaining TempData through multiple Ajax calls to Controller

Im trying to work with an object (VideoInfo) in several Action methods. A form sends a viewmodel with a video file to the Upload method in VideoController. It uploads the video and returns a generated guid. When the callback has returned, a new ajax call is made to the Convert method which returns the guid. As seen in the javascript part of Create.cshtml it makes two other Ajax calls, one to the Progress method and one to the Azure method.
When trying to fetch the VideoInfo object in the Azure method and the Progress method, videoInfo is null. Though it successfully retains the data between the Upload method and Convert method. Im using TempData.Peek() so that it shouldnt mark it for deletion.
I can see that the Upload and Convert method is using the same instance of VideoController, where as the Progress and Azure method uses another instance, I guess this could have to do with the problem.
InstanceId when running Upload method: 23ef96fa-c746-4722-ad07-e9e40fc95f29
InstanceId when running Convert method: 23ef96fa-c746-4722-ad07-e9e40fc95f29
InstanceId when running Progress method: 0aba24b2-ccb8-434d-a27d-cc66cb52c466
InstanceId when running Azure method: 0aba24b2-ccb8-434d-a27d-cc66cb52c466
How can I retain data between my Ajax calls in the VideoController?
Why is the instance id same for the first two calls but then it changes?
VideoController.cs
using System;
namespace MediaPortal.Controllers
{
[Authorize(Roles = "Admin")]
public class VideoController : Controller
{
private static Guid InstanceId { get; }
static VideoController()
{
InstanceId = Guid.NewGuid();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Upload(CreateVideoViewModel model)
{
if (ModelState.IsValid)
{
if (model.File != null)
{
Debug.WriteLine("Upload method InstanceId: " + InstanceId.ToString());
// ...
TempData[videoInfo.Id] = videoInfo;
videoInfo.cvvm.File.SaveAs(videoInfo.TempPath);
return Json(new { Successfull = true, Id = videoInfo.Id });
}
return null;
}
return null;
}
[HttpPost]
public ActionResult Convert(string id)
{
Debug.WriteLine("Convert method InstanceId: " + InstanceId.ToString());
// Create new object of FFMpegConvertor
var converter = new FFMpegConverter();
VideoInfo videoInfo = (VideoInfo)TempData.Peek(id);
// ...
return Json(new { Successfull = true, Id = videoInfo.Id });
}
[HttpPost]
public ActionResult Azure(string id)
{
Debug.WriteLine("Azure method InstanceId: " + InstanceId.ToString());
VideoInfo videoInfo = (VideoInfo)TempData[id];
// ...
if (videoUpload != null && thumbnailUpload != null)
{
Video video = new Video
{
Id = videoInfo.Id.ToString(),
Name = videoInfo.cvvm.Name,
ProjectId = videoInfo.cvvm.ProjectId,
Type = "mp4",
VideoUri = videoUpload.Uri.ToString(),
ThumbnailUri = thumbnailUpload.Uri.ToString()
};
db.Videos.Add(video);
db.SaveChanges();
return Json(new { Successful = true, Data = Url.Action("Index", new { projectId = videoInfo.cvvm.ProjectId }) });
}
return null;
}
[HttpPost]
public JsonResult Progress(string id)
{
Debug.WriteLine("Progress method InstanceId: " + InstanceId.ToString());
try
{
VideoInfo videoInfo = (VideoInfo)TempData.Peek(id);
return Json(new { Data = videoInfo.Progress });
}
catch
{
return Json(new { Data = "No Video Information in Dictionary for Id: " + id });
}
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
Create.cshtml (JQuery/Ajax)
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.js"></script>
<script src="http://malsup.github.com/jquery.form.js"></script>
<script>
$.noConflict();
jQuery(document).ready(function ($) {
var bar = $('.progress-bar');
var percent = $('.percent');
$('#Myform').ajaxForm({
type: "POST",
contentType: "application/json; charset=utf-8",
beforeSend: function () {
var percentVal = '0%';
bar.width(percentVal);
percent.html(percentVal);
},
uploadProgress: function (event, position, total, percentComplete) {
var percentVal = percentComplete + '%';
bar.width(percentVal);
percent.html(percentVal);
},
complete: function (uploadStatus) {
console.log("Upload finished for video with Id: " + JSON.parse(uploadStatus.responseText).Id);
setTimeout(function () { progress(uploadStatus) }, 1000);
$.ajax({
type: "POST",
url: '#Url.Action("Convert", "Video")?id=' + JSON.parse(uploadStatus.responseText).Id,
dataType: "json",
contentType: "application/json; charset=utf-8",
complete: function (convertStatus) {
console.log("Conversion finished for video with Id: " + JSON.parse(convertStatus.responseText).Id);
$.ajax({
type: "POST",
url: '#Url.Action("Azure", "Video")?id=' + JSON.parse(convertStatus.responseText).Id,
dataType: "json",
contentType: "application/json; charset=utf-8",
complete: function (azureStatus) {
window.location.href = JSON.parse(azureStatus.responseText).Data;
}
});
}
});
}
});
function progress(uploadStatus) {
$.ajax({
type: "POST",
url: '#Url.Action("Progress", "Video")?id=' + JSON.parse(uploadStatus.responseText).Id,
dataType: "json",
contentType: "application/json; charset=utf-8",
complete: function (progressStatus) {
console.log("Progress: " + JSON.parse(progressStatus.responseText).Data);
if (JSON.parse(progressStatus.responseText).Data < 100) {
setTimeout(function () { progress(uploadStatus) }, 1000);
}
else if (JSON.parse(progressStatus.responseText).Data >= 100) {
console.log("Video Conversion Completed");
}
else {
console.log("Something went wrong");
}
}
})
}
});
</script>
It seems IIS Express was the problem. I cant say why though. I realized this because when I deployed the project to my production server in Azure it all worked fine.
So instead of using IIS Express I installed IIS on my development machine, works perfectly after that.

How to pass Ajax Json object to the Controller Class in .Net Core?

We are trying to make a Ajax request to our Core Web API and get the data Json result back to the Controller for further processing, Which include Deserialization of the Json object result, Ajax request is working fine and we are able to get the required Json data in data.
Can anyone here please advise the changes or the alternatives to achieve this?
View (Ajax Request)
#section scripts
{
<script type="text/javascript">
$(document).ready(function () {
GetEventDetails('#Url.Content("~/")');
});
function GetEventDetails(contextRoot) {
$.ajax({
type: "GET",
url: contextRoot + "api/EventsAPI",
dataType: "json",
success: function (data) {
debugger;
var datavalue = data;
contentType: "application/json";
//Send data to controller ???
console.log(data);
},
error: function (xhr) {
alert(xhr.responseText);
}
});
}
</script>
}
Controller.cs
public ActionResult Index()
{
/*Do all stuff before returning view
1. Get Json Data from Ajax request
2. Deserialize the obtained Json Data
3. return to view
*/
return View("Index");
}
Update:
I have tried the solution given by #J. Doe, but still unable to get the result set. Please check the screenshot and below code..
Ajax Request:
function GetEventDetails(contextRoot) {
$.ajax({
type: "GET",
url: contextRoot + "api/EventsAPI",
dataType: "json",
success: function (data) {
debugger;
var datavalue = data;
contentType: "application/json; charset=utf-8";
console.log(data);
var EventJson = data;
console.log(EventJson);
$.ajax({
type: "POST",
url: "#Url.Action("Index")",
dataType: "json",
data: EventJson,
contentType: "application/json; charset=utf-8",
//data: EventJson,
success: function (data) {
alert(data.responseText);
console.log('Data received: ');
console.log(data.responseText);
},
failure: function (errMsg) {
console.log(errMsg);
}
});
},
error: function (xhr) {
alert(xhr.responseText);
}
});
}
Class Properties:
public class RootObject
{
public Embedded _embedded { get; set; }
public Links _links { get; set; }
public Page page { get; set; }
}
Here is Action Result Controller:
public ActionResult Index(RootObject model)
{
if (model != null)
{
return Json("Success");
}
else
{
return Json("An Error Has occoured");
}
//return View("Index");
}
Error Snapshot:
enter image description here
1) Add [FromBody] the controller you are returning to. This will make the controller expect a JSON object.
[HttpPost]
public ActionResult Index([FromBody]RootObject model)
{
if (model != null)
{
return Json("Success");
}
else
{
return Json("An Error Has occoured");
}
//return View("Index");
}
2) If this doesn't work you are not posting a correct json object/you are not posting a json object use console.dir(EventJson); to inspect the object you are passing in the console of the browser.
3) How to create a JSON object in JS: https://www.w3schools.com/js/js_json_stringify.asp
We are trying
Hello soviet sojuz!
But back to question - A 2 months ago i created sample on GitHub with ajax with .Net Core - https://github.com/CShepartd/ASP.Net_Core_-_Ajax_Example
In short:
Make action with objects in controller:
public IActionResult Ajax(string name1, string name2)
{
return View();
}
Next in view send name1 and name2 to action
$('form').submit(function(event) {
event.preventDefault();
var data = {
name1: $("input[name='name1']", this).val(),
name2: $("input[name='name2']",this).val()
};
$.ajax({
type: 'POST',
url: '/Home/Ajax',
dataType: 'json',
data: data,
success: function(response) {
alert(response);
console.log('Data received: ');
console.log(response);
},
failure: function(response) {
//...
},
error: function(response) {
//...
}
});
});

Kendo Datasource not sending string to Controller

I am creating a CRUD application, My application is getting a string from from a Kendo input box, and will need to send it to my controller which is expecting a string that I am getting from my Jquery call. However, the string is not getting to my controller. I have tried various ways and I am not able to send it through my Transport. I have put break point and I can confirm that the value is being picked up in my Kendo Observable.
My Datasource
var client = new kendo.data.DataSource({
transport: {
read: {
url: "Client/SearchClient",
contentType: "application/json; charset=utf-8",
dataType: "json",
},
My Controller
public ActionResult SearchClient()
{
return View();
}
[HttpPost]
public ActionResult SearchClient(string name)
{
Repo repo = new Repo();
var result = repo.GetClient();
return Json(new
{
list = result,
count = result.Count
}, JsonRequestBehavior.AllowGet);
}
This is my Kendo Observable
var viewModel = kendo.observable({
client: {
clientName: "",
clientNumber: "",
clientType: "",
},
dropdownlist: ["HCC", "Tax", "Audit", "Advisory"],
create: function (e) {
var userRequest = $("#clientname").val();
if (userRequest) {
client.read(userRequest);
}
if (!userRequest)
alert("Please Enter Client Name")
}
});
Search Client method wants POST, not GET? The default will be GET. Either change your api method to use HttpGet, or change the transport to method: "post" for read.
var client = new kendo.data.DataSource({
transport: {
read: {
url: "Client/SearchClient",
contentType: "application/json; charset=utf-8",
dataType: "json",
method: "post"
},

Calling a WebAPI from client side through POST method fails

We are trying to call a web-api from client side. The web api contains a Request class with Amount as decimal. We are trying to pass a decimal amount and getting back the same amount in response from webapi along with the status.
The problem is that the web-api is not able to receive the amount. When we try to attach with webapi we see only null in the Amount field in the Request class.
Any help in this regard would be great.
Below is how we call from client side
var requestMessage = { RequestSale: { Amount: '100.545M' } };
var request = {
type: "POST",
contentType: "application/json;charset=utf-8",
datatype: "json",
url: "http://<machinename>/Demo/api/monthlySales/InsertMonthlySales",
successCallback: successCallback,
errorCallback: errorCallback,
filterCriteria: null,
data: JSON.stringify(requestMessage)
//header: { key: "Accept", value: "application/json" },
};
utilityTest.getData(request);
expect(true, true);
utilityTest.getData(request) -- This makes the actual call, below is code
utilityTest.getData = function (request) {
$.ajax({
type: request.type,
contentType: request.contentType,
datatype: request.datatype,
url: request.url,
data: request.data,
cache : false,
beforeSend: function (xmlHttpRequest) {
if (request.header) {
xmlHttpRequest.setRequestHeader(request.header.key, request.header.value);
}
},
success: function (data, textStatus, xmlHttpRequest) {
if (request.successCallback) {
request.successCallback(data, request.filterCriteria);
}
},
error: function (xmlHttpRequest, textStatus, errorThrown) {
if (request.errorCallback)
request.errorCallback(xmlHttpRequest, textStatus, errorThrown);
} });
}
Web-api method
[HttpPost]
public ResponseSale InsertMonthlySales(RequestSale sale)
{
var curMonth = DateTime.UtcNow.Month;
var salesAmount = Convert.ToDecimal(sale.Amount);
ResponseSale response = new ResponseSale();
response.Amount = salesAmount;
response.Id = curMonth;
if (monthlySales.ContainsKey(curMonth))
{
monthlySales[curMonth] += salesAmount;
}
else
{
monthlySales.Add(curMonth, salesAmount);
}
response.Status = "InsertMonthlySales";
return response;
}
Request/Response contract for web-api
namespace DemoContracts.Object
{
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://DemoSchema.ContractSale")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://DemoSchema.ContractSale", IsNullable = false)]
public class RequestSale {
public decimal Amount { get; set; }
}
}
namespace DemoContracts.Object
{
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://DemoSchema.ContractSale")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://DemoSchema.ContractSale", IsNullable = false)]
public class ResponseSale
{
public string Status { get; set; }
public decimal Amount { get; set; }
public int Id { get; set; }
}
}
--JSON as captured from IE
Request Body :
{"RequestSale":{"Amount":100.545}}
Response Body
{"Status":"InsertMonthlySales","Amount":0.0,"Id":9}
In Web API, InsertMonthSales request object RequestSale.Amount is always be 0. We are not getting the passed 100.545 value

Not getting Json object (having a collection) correctly in controller using ajax call

I am sending a json object to controller via ajax call, data property of ajax call showing correct data. On post to controller's method -received parameter having collection and its count is showing perfectly but the properties inside the collection is not showing values.
Here is the code -
Controller-
[HttpPost]
public ActionResult ImageOperations(ImageProcessingModel imageProcessingModel)
{
return Json("sucess");
}
Model-
public class ImageProcessingModel
{
public string Source { get; set; }
private List<ThumbnailImageSubTaskModel> _thumbnailImageSubTaskModel;
public List<ThumbnailImageSubTaskModel> ThumbnailImageSubTaskModel
{
get
{
if (_thumbnailImageSubTaskModel == null)
{
_thumbnailImageSubTaskModel = new List<ThumbnailImageSubTaskModel>();
}
return _thumbnailImageSubTaskModel;
}
}
}
js-
var ImageProcessingModel =
{
"Source": "test",
"ThumbnailImageSubTaskModel":allThumbnails.allItems()
}
allThumnails.allItems is ko.observableArray() which having values.
$.ajax({
url: '/ImageProcessingTask/ImageOperations',
type: 'Post',
data: ImageProcessingModel,
success: function (data, status) {
processEscapeKeyPress = true;
var fn = window[successCallback];
fn(data, passDataToCallback);
},
error: function (xhr, desc, err) {
alert(err);
processEscapeKeyPress = true;
processAjaxError(xhr, desc, err);
},
});
here ImageProcessingModel having all values and source is simple a string so this value is coming in the controller only the ThumbnailImageSubTaskModel showing counts but not its value.
Thanks!!
A common problem encoutered with sending JSON through AJAX to MVC. Many forget to set the type of data in their AJAX request.
Try setting the datatype and contentType:
$.ajax({
url: '/ImageProcessingTask/ImageOperations',
type: 'Post',
**contentType: 'application/json; charset=UTF-8',
dataType: 'json',**
data: ImageProcessingModel,
success: function (data, status) {
processEscapeKeyPress = true;
var fn = window[successCallback];
fn(data, passDataToCallback);
},
error: function (xhr, desc, err) {
alert(err);
processEscapeKeyPress = true;
processAjaxError(xhr, desc, err);
},
});

Resources