kendu ui datasource read event has null request - c#

I have an Kendo UI scheduler widget on mobile page, which as you can see has a datasource read event.
$("#scheduler").kendoScheduler({
...
dataSource: {
batch: true,
transport: {
read: {
url: "http://mydomain.com/api/Schedule/Tasks_Read",
dataType: "jsonp"
},
...
});
When the read event is called it sends the request as
http://mydomain.com/api/Schedule/Tasks_Read?callback=jQuery1910528280699858442_1396259085815&_=1396259085816
the problem is that when the webapi get method gets the request, the [DataSourceRequest]DataSourceRequest request parameter is null.
[HttpGet]
public DataSourceResult Tasks_Read(
[DataSourceRequest]DataSourceRequest request)
//,DateTime startDate)
{
using (scApp = new ScheduleControllerApplication())
{
...
}
}
Can somebody clue me into why the request parameter is null?
I have a scheduler on a MVC4 page and it works fine and has the same querystring jquery addition.
MY SOLUTION - By no means let this stop you from answering if you have diferent approach.
Being that this call was from a mobile source i changed the httpget signature
[HttpGet]
public string Tasks_Read(
string request)
{
using (scApp = new ScheduleControllerApplication())
{
...
}
}
and it worked and returned the 2 jQuery items i was expecting.

Related

trigger IActionResult using Ajax request in Net Core 3.1 MVC

SOLVED, see end of the post.
I have the following .Net Core 3.1 project, where videos are displayed for a user. It can also select playlists, which holds subsets of those videos.
Once a user selects the playlist from a SelectList element, I would like it to send the playlist ID to the backend, load the videos and load the view again.
However, I would like to have no submit button with my SelectList, once a playlist is selected it should load the videos.
I tried this with Ajax, and it works so far that it sends the playlist ID to a backend method, loads the videos, but then returns the ajax call to the browser.
Controller:
public async<IActionResult> Index(string playlistId = null)
{
// process playlistID and other stuff in viewModel
return View(viewModel);
}
[HttpPost]
public async Task<IActionResult> ProcessIncomingAjaxRequest([FromBody] string data)
{
playlistId = String.IsNullOrEmpty(data) ? "0" : data;
return RedirectToAction(nameof(Index), new { playlistId= playlistId });
}
Ajax call:
$('#PlaylistId').on('change',function () {
var name = $('#PlaylistId').val()
$.ajax({
type: "POST",
url: "/Home/ProcessIncomingAjaxRequest",
data: JSON.stringify(name),
dataType: "json",
contentType: "application/json",
success: function (response) {
alert(response);
},
error: function (error) {
alert(error.status);
}
});
return false;
});
ProcessIncomingAjaxRequest gets called by the Ajax request, calls the RedirectToAction method, both methods go through all the steps and then returns to the browser with the 200 response from the Ajax call, not loading the actual View.
Is there a way to call the View method (index()) from ProcessIncomingAjaxRequest in the Controller and resume the normal way of loading the view?
Solution:
This post answered my question

Parse JSON from C# to AngularJS

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.

How do I refresh UI on request?

I've a Web app with a button that makes a call to an API to refresh data:
[AcceptVerbs("GET")]
[Route("refreshFromService/{guid}")]
public HttpResponseMessage RefreshDataFromService(string guid)
{
if (!string.IsNullOrEmpty(guid) && guid.Length == 36 && new Guid(guid) == new Guid("C943F8E4-647D-4044-B19E-4D97FA38EDE0"))
{
new AdData().RefreshCacheAdData(true);
new JdeData().RefreshCacheJdeData(true);
return new HttpResponseMessage(HttpStatusCode.OK);
}
return new HttpResponseMessage(HttpStatusCode.Forbidden);
}
Actually, it's an AJAX call, so in my Network Tab in Google Chrome, I see the request is in pending for 5 minutes.
How can I make this method an async method and how can I refresh my UI to show progress?
EDIT
When I refresh the page, I want the Progress Status to be updated.
First of all, it has nothing to do with a backend. So solution to your problem lies on frontend site. Ajax are asynchronous by nature so you can do something like that.
const loader = document.createElement('span')
// some styles for the loader
// i'm using body just for example purposes
document.body.appendChild(loader)
fetch('refreshFromService/{guid}')
.then(data => {
document.body.removeChild(loader)
// do something with data
return data
})
You have to handle it on UI like this:
function getFlag() {
var option = {
url: '/controllerName/actionName',
data: JSON.stringify({}),
method: 'post',
dataType: 'json',
contentType: 'application/json;charset=utf-8'
};
$.ajax(option).success(function (data) {
$("#picture").append("<img id=\"img1\" src=" + data.img_path + "\ />");
});
};
I am using this code in UI for getting flags at runtime. So you need to write same type of code and get response from the backend.
url: '/controllerName/actionName' is the controller in MVC and then action implemented in that controller.
Request this method in UI with document.ready
I hope I have made sense to you. If still not clear write back i will explain further.
Cheers!

How to make Angular POST to C# Asp.Net MVC Controller?

I have looked around, but have not found anything (Angular post) that can actually make a successful call to a MVC Controller. I know there are a lot of Angular/.Net devs out there. Can I get some help?
Let's keep answers bare bones simple!!!
If I set a linebreak on the controller, I can see that this code is not actually hitting the controller.
HTML
<!-- I click this button -->
<input type="button" value="click" onclick="postit()" />
Javascript/Angular Post
function postit() {
$http({
method: 'POST',
url: 'Home/Give/',
data: { id: 4 }
}).success(successFn).error(errorFn);
}
function successFn() {
alert("success");
}
MVC C# Controller
[AcceptVerbs("OPTIONS")]
public ActionResult Give(int id)
{
var response = "some response" + id.ToString();
return Json(new JavaScriptSerializer().Serialize(response));
}
king Puppy, I've seen a few responses that dictate that the controller parameters should be an object that matches the object that is being sent, however, it seems that it's a little more forgiving than that. Consider the following example (I've updated your function a little):
Javascript:
$scope.postIt = function() {
var data = {
id = 4
};
$http
.post('Home/Give', data)
.success(function(data, status, headers, config) {
successFn();
})
.errors(function(data, status, headers, config) {
errorFn();
});
};
function successFn() {
alert("success");
};
function errorFn() {
alert("error");
};
MVC:
public ActionResult Give(int id)
{
var response = "some response" + id.ToString();
return Json(new JavaScriptSerializer().Serialize(response));
}
If you set a breakpoint, you will see that the id passed in is 4.
If you needed to pass in an object (so more than just one id), you could either create a matching class or struct on the controller side, or have multiple parameters (provided that they are simple value types)
ie:
public JsonResult Give (int id, int reasonId)
{
...
}
Anyway, I realize the post is old, but perhaps it will help you or others.
#kingPuppy this is my way to how to make angularjs post to mvc controller
first, html button for passing the angular js button click function;
<button class="btn btn-info" id="runButton" ng-click="runService('Hi')">Run</button>
so runService angular click (ng-click) function;
// Operation Type is my mvc controller's param
$scope.runService = function (optionType) {
$http({
url: '/System/RunService',
method: "POST",
data: {operationType : optionType}
}).then(function onSuccess(response) {
// Handle success
console.log(response);
}).catch(function onError(response) {
// Handle error
console.log(response);
});
}
And finally this is system controller's action;
NOT : Dont forget to [HttpPost] attribute
[HttpPost]
public ActionResult RunService(string operationType)
{
// Codes
Response.StatusCode = 200;
return Json(JsonRequestBehavior.AllowGet);
}
Hope this could help to you for how to make angular post to mvc controller. Thanks.
There is nothing special you have to do to get Angular to post to a standard MVC controller, and in fact I have several Angular/MVC apps that are using code almost identical to what you have above to POST to controllers that work fine.
I would use Firebug to confirm that your app is posting to the right place. One thing I noticed is that you might not want that trailing / at the end of your URL (so Home/Give instead of Home/Give/)
Good luck!

Kendo UI Scheduler Edit pop up window wont close after making changes

I am trying out the Kendo UI HTML Scheduler.
I was able to successfully read appointments from the database through my ASP.NET MVC appplication.
For Read : I am sending JsonResult from my ASP.NET controller.
For Update : The controller is getting a URL JSON encoded string which I deserialize and update the database and the return nothing to the caller.
When open an event to edit, make the changes and press "Save". The controller gets called and the record is updated but neither the pop-up window closes nor the scheduler gets updated.
The HTML Demo on Telerik website returns "callback()" on update and works fine but what am I missing on my code that would make the changes reflect.
**view**
<script>
$("#scheduler").kendoScheduler({
// configuration //
dataSource: {
batch: true,
transport: {
read: {
url : "http://localhost/Scheduler/Appointments",
dataType: "json"
},
update: {
Type:"POST",
url: "http://localhost/Scheduler/UpdateAppointment",
dataType: "json"
},
parameterMap: function(options, operation) {
if (operation !== "read" && options.models) {
return {models: JSON.stringify(options.models)};
}
}
},
schema: {
model: {
// my model
}
},
</script>
Controller
public JsonResult UpdateAppointment(String models)
{
if (models != null)
{
char[] charsToTrim = { '[', ']' };
string model_Trimmed = models.Trim(charsToTrim);
// Deserialize
Appointment SerializedAppointment = new JavaScriptSerializer().Deserialize<Appointment>(model_Trimmed);
Models.Entities.Appointment AppointmentToUpdate = db.Appointment.Where(x => x.TaskID == SerializedAppointment.TaskID).Single();
AppointmentToUpdate.Title = SerializedAppointment.Title;
AppointmentToUpdate.Start = SerializedAppointment.Start;
AppointmentToUpdate.End = SerializedAppointment.End;
db.SaveChanges();
}
return new JsonResult() {Data=null, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
Kendo needs to return a valid JSON format in your paramater map, so you could try this:
parameterMap: function(options, operation) {
if (operation !== "read" && options.models) {
return {models: JSON.stringify(options.models)};
}
return {};
}
Maybe this Link will also helps you...
(Copy just to prevent dead Links)
There is a breaking change with the new version of jQuery which affects the Kendo Q1 2013 version 2013.1.319
Since the empty result returned from the server in case everything is executed properly on the server side for the update and destroy requests, the error event of the dataSource is triggered because the empty result is not valid JSON.
The suggested resolutions when using the MVC Extensions are:
Use the Latest Internal Build version 2013.1.327
Change the response of the Update/Destroy actions from just serializing the ModelState to:
return Json(ModelState.IsValid ? new object(): ModelState.ToDataSourceResult());

Categories