Navigate to another Page after appointment has been saved in kendo scheduler - kendo-ui

I have got this scheduler displayed but not binding to tasks. The scheduler in the view. I am using java script method to read/create call to web api
#(Html.Kendo().Scheduler<TaskViewModel> ()
.Name("AppointmentSearchScheduler")
.DataSource(dataSource => dataSource
.Custom()
.Schema(schema => schema
.Model(m => {
m.Id(f => f.TaskID);
m.Field(f => f.OwnerID).DefaultValue(1);
}))
.Transport(new {
read = new Kendo.Mvc.ClientHandlerDescriptor() {
HandlerName = "customRead"
},
create = new Kendo.Mvc.ClientHandlerDescriptor() {
HandlerName = "customCreate"
}
})))
Below is javascript handler method I am not including create handler for brevity.
function customRead(options){
//get the selected Row of the kendo grid
var selectedRow = $("#locationgridKendo").find("tbody tr.k-state-selected");
var scheduler = $("#AppointmentSearchScheduler").data("kendoScheduler")
//get SelectedRow data
var rowData = $('#locationgridKendo').data("kendoGrid").dataItem(selectedRow);
if (rowData !== null) {
//Convert data to JSON
var rowDataJson = rowData.toJSON();
//extract the location ID
var locationId = rowDataJson.LocationID;
var CalenderweekStartDate = new Date().toISOString();
baseUrl = $('base').attr('href');
$.ajax({
url: baseUrl + 'Schedular/api/GetAppPerLocation?locationId=' + locationId + '&date=' + CalenderweekStartDate,
type: 'GET',
cache: false,
contentType: 'application/json',
success: function (result) {
//This method is hitting and i can see the data being returned
console.log('data is received : ' + result.Data);
options.success(result.Data);
},
error: function (xhr, status, error) {
//alert("Error: Search - Index.js - submitAppointment()");
var err = eval("(" + xhr.responseText + ")");
alert(err.Message);
}
});
}
}
Here is the web API controller called by making ajax call . The controller works perfectly when i used the basic read/create syntax . The ajax call complete and it does hit back the success method and returns the data but scheduler for some reason is not binded to incoming data. Here is my controller code
[HttpGet]
[Route("api/GetAppPerLocation")]
public DataSourceResult GetAppointmentPerLocation([ModelBinder(typeof(Usps.Scheduling.Web.ModelBinders.DataSourceRequestModelBinder))] DataSourceRequest request, int locationId, DateTime date) {
List < TaskViewModel > locationAvailableAppointmentList = new List < TaskViewModel > ();
locationAvailableAppointmentList = data.Select(appt => new TaskViewModel() {
TaskID = appt.ServiceAppointmentId,
Title = "Appointment Available",
Start = DateTime.SpecifyKind(appt.AppointmentBegin, DateTimeKind.Local),
End = DateTime.SpecifyKind(appt.AppointmentEnd, DateTimeKind.Local),
Description = "",
IsAllDay = false
}).ToList();
return locationAvailableAppointmentList.ToDataSourceResult(request);
}
For some reason the scheduler is not binding to incoming data . the incoming data works perfectly when i use a basic binding approach but not using transport . My goal for using this approach is once i am done with read(scheduler is not binding now) , on create I need to grab the ID of the newly created task returned by my controller and then pass that id to another mvc controller to render a confirmation page. Any other approach to accomplish this goal will be highly recommended.
Please excuse me for any mistake since this is my first question on stackoverflow.

My goal for using this approach is once i am done with read(scheduler is not binding now) , on create I need to grab the ID of the newly created task returned by my controller and then pass that id to another mvc controller to navigate render a confirmation page.
I speculated that read was not returning correct result so i had to fix that .Also my basic goal was redirection to another page after with appointment id and displaying a confirmation screen. This is how accomplished it . I understand this is not the best approach but it has been more than a year no body answered by question. Here is the approach i took .
I added a error to the model state like this in my controller
if (!String.IsNullOrEmpty(task.TaskID.ToString()))//redirect to confirmation page if the appointment was added to the queue
ModelState.AddModelError("AppointmentID", confirmationNumber);
then on client side i configure the error event on grid like this
.Events(
events => events.Error("RedirectToConfirmationPage"))
Here is the Javascript method details
function RedirectToConfirmationPage(e) {
console.log('RedirecToConfirmationPage method......');
console.log(e);
if (e.errors) {
var appointmentID = "";
// Create a message containing all errors.
$.each(e.errors, function (key, value) {
console.log(key);
if ('errors' in value) {
$.each(value.errors, function () {
appointmentID += this + "\n";
});
}
});
console.log('Newly Generated AppointmentID = ' + appointmentID);
// Redirect URL needs to change if we're running on AWS instead of on local developer machines
if (window.location.href.indexOf('/TestProject.Scheduling') > 1) {
window.location.href = '/Scheduler/AppointmentConfirmation?confirmationNumber=' + appointmentID
}
else {
window.location.href = '/Scheduler/AppointmentConfirmation?confirmationNumber=' + appointmentID
}
}
}
Hope it is helpfull to someone down the road.

Related

Kendo UI Large Parameters Value (414 Request-URI Too Long) error

Hy This code is part of my grid.
grid._parameterMap = function (data, type) {
if (type !== "read" && data.models)
return { models: kendo.stringify(data.models) };
var warehouseCodeList = [];
var selectedWarehouse_OnPhysicalCountDefinition = '';
$.each(KendoData('mltWarehouse_OnPhysicalCountDefinition').dataItems(), function (index, value) {
selectedWarehouse_OnPhysicalCountDefinition += value.WarehouseCode + ',';
});
selectedWarehouse_OnPhysicalCountDefinition = selectedWarehouse_OnPhysicalCountDefinition.slice(0, -1);
var parameters = {
warehouseCodeList: selectedWarehouse_OnPhysicalCountDefinition,
periodDateString: $('#dpcPeriodDate_OnPhysicalCountDefinition').val(),
Page: data.page,
PageSize: data.pageSize
}
return kendo.data.transports["odata"].parameterMap(parameters, type);
};
And parameters value is
Page
:
1
PageSize
:
50
periodDateString
:
"17/10/2022"
warehouseCodeList
:
"480176,480172,480003,480166,480109,480025,480090,480089,480002,480088,
480061,480101,480016,480009,480095,480008,480094,480093,480006,480092,480005,480091,480004,
480117,480033,480114,480060,480113,480163,480030,480059,2011,480157,480028,480045,480048,
480039,480029,480120,480046,480156,480049,480072,480063,480062,48006100,480071,480070,480069,
480068,480067,480066,480065,480064,480077,480076,480085,480084,480082,480078,480073,480075,480079,
480074,480083,480127,480128,480057,480129,480058,480081,480080,480141,480132,480131,480130,480140,
480138,480137,480136,480135,480134,480133,480146,480145,480154,480153,480151,480147,480142,480144,
480148,480143,480152,480139,480150,480149,480106,480126,480055,480165,480167,480100,480123,480053,
480096,480168,480162,480159,480158,480038,480102,480017,480013,480122,480047,480116,480032,480034,
480107,480040,480118,480098,480051,480110,480026,480111,480027,480108,480103,480115,480031,480035,
480087,480086,480036,480119,480112,480010,480097,480155,480124,480054,480019,480099,480104,480171,
480164,480041,480042,480121,480043,480044,480014,480052,480170,480037,480050,480012,480105,480169,
480161,480174,480173"
You can see that my data and that large data not going my controller becouse of that large warehouseCodeList.You can see Request below.This request is Send Get Request in Controller.If I can change Post I think gone work bu HOW! =)
Request URL: https://zzzz/Inv/yyy/xxxx/?%24inlinecount=allpages&%24format=json&warehouseCodeList=480176%2C480172%2C480003%2C480166%2C480109%2C480025%2C480090%2C480089%2C480002%2C480088%2C480061%2C480101%2C480016%2C480009%2C480095%2C480008%2C480094%2C480093%2C480006%2C480092%2C480005%2C480091%2C480004%2C480117%2C480033%2C480114%2C480060%2C480113%2C480163%2C480030%2C480059%2C2011%2C480157%2C480028%2C480045%2C480048%2C480039%2C480029%2C480120%2C480046%2C480156%2C480049%2C480072%2C480063%2C480062%2C48006100%2C480071%2C480070%2C480069%2C480068%2C480067%2C480066%2C480065%2C480064%2C480077%2C480076%2C480085%2C480084%2C480082%2C480078%2C480073%2C480075%2C480079%2C480074%2C480083%2C480127%2C480128%2C480057%2C480129%2C480058%2C480081%2C480080%2C480141%2C480132%2C480131%2C480130%2C480140%2C480138%2C480137%2C480136%2C480135%2C480134%2C480133%2C480146%2C480145%2C480154%2C480153%2C480151%2C480147%2C480142%2C480144%2C480148%2C480143%2C480152%2C480139%2C480150%2C480149%2C480106%2C480126%2C480055%2C480165%2C480167%2C480100%2C480123%2C480053%2C480096%2C480168%2C480162%2C480159%2C480158%2C480038%2C480102%2C480017%2C480013%2C480122%2C480047%2C480116%2C480032%2C480034%2C480107%2C480040%2C480118%2C480098%2C480051%2C480110%2C480026%2C480111%2C480027%2C480108%2C480103%2C480115%2C480031%2C480035%2C480087%2C480086%2C480036%2C480119%2C480112%2C480010%2C480097%2C480155%2C480124%2C480054%2C480019%2C480099%2C480104%2C480171%2C480164%2C480041%2C480042%2C480121%2C480043%2C480044%2C480014%2C480052%2C480170%2C480037%2C480050%2C480012%2C480105%2C480169%2C480161%2C480174%2C480173&periodDateString=17%2F10%2F2022&Page=1&PageSize=50
Request Method: GET
Status Code: 200 OK
And Finaly I try the give dataSource remote but not work .But I can give that data ın Ajax call.Can you Help me ?
What can I do in this situation?
There is a type option for the dataSource transport configuration that you can set. It will set the type of request the dataSource would make ("POST", "GET", "PUT" or "DELETE").
Thanks aleksandar.The code I use is below
<script>
var dataSource = new kendo.data.DataSource({
transport: {
read: {
/* omitted for brevity */
type: "POST"
}
}
});
</script>

ajax call does not work in angular js

I have the scenario as follow:
I have a text box and button and whenever I add sth in textbox I want to add the text in the table my code is as follow:
var app = angular.module('app', []);
app.factory('Service', function() {
var typesHash = [ {
id :1,
name : 'lemon',
price : 100,
unit : 2.5
}, {
id : 2,
name : 'meat',
price : 200,
unit : 3.3
} ];
var localId = 3;
var service = {
addTable : addTable,
getData : getData,
};
return service;
function addTable(name) {
typesHash.push({id:localId++, name:name, price:100,unit:1});
}
function getData() {
return typesHash;
}
});
app.controller('table', function(Service) {
//get the return data from getData funtion in factory
this.typesHash = Service.getData();
//get the addtable function from factory
this.addTable = Service.addTable;
});
and the plnkr is as follow:
plnkr
Now as you can see I add whatever inside the text in the table and everything works fine but now I want to add whatever inside the textbox and also I want to get some information from the servlet and add those to the table as well. so for that I use ajax call as follow:
function addTable(name) {
typesHash.push({id:localId++, name:name, price:100,unit:1});
var responsePromise = $http.get("http://localhost:8080/purchase/AddInfo");
responsePromise.success(function(data, status, headers, config) {
typesHash.push( {id:data.id,name : data.name, price : data.price,unit:2.5 });
});
}
but when I use that I get he following error:
ReferenceError: $http is not defined
can anyone help? (just a quick note: this code is smaller version of my real code and I purposely used factory since I need it)
inside of your controller attr your should insert an $http argument:
app.controller('CTRL1', function($scope, $http){
//Now your can use $http methods
})
or insert $http argument in your service decleration if you are using $http request methods from inside of your service

AntiForgeryToken not being received when using plupload in form submission

I'm using Plupload to allow multiple images to be uploaded to an mvc3 web app.
the files upload OK, but when i introduce the AntiForgeryToken it doesn't work, and the error is that no token was supplied, or it was invalid.
I also cannot get the Id parameter to be accepted as an action parameter either, it always sends null. So have to extract it myself from the Request.UrlReferrer property manually.
I figure plupload is submitting each file within the upload manually and forging its own form post.
My form....
#using (#Html.BeginForm("Upload", "Photo", new { Model.Id }, FormMethod.Post, new { id = "formUpload", enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
#Html.HiddenFor(m => m.Id)
<div id="uploader">
<p>You browser doesn't have HTML5, Flash or basic file upload support, so you wont be able to upload any photos - sorry.</p>
</div>
<p id="status"></p>
}
and the code that wires it up...
$(document).ready(function ()
{
$("#uploader").plupload({
// General settings
runtimes: 'html5,flash,html4',
url: '/Photo/Upload/',
max_file_size: '8mb',
// chunk_size: '1mb',
unique_names: true,
// Resize images on clientside if we can
resize: { width: 400, quality: 100 },
// Specify what files to browse for
filters: [
{ title: "Image files", extensions: "jpg,gif,png" }
],
// Flash settings
flash_swf_url: 'Content/plugins/plupload/js/plupload.flash.swf'
});
$("#uploader").bind('Error', function(up, err)
{
$('#status').append("<b>Error: " + err.code + ", Message: " + err.message + (err.file ? ", File: " + err.file.name : "") + "</b>");
});
// Client side form validation
$('uploadForm').submit(function (e)
{
var uploader = $('#uploader').pluploadQueue();
// Validate number of uploaded files
if (uploader.total.uploaded == 0)
{
// Files in queue upload them first
if (uploader.files.length > 0)
{
// When all files are uploaded submit form
uploader.bind('UploadProgress', function ()
{
if (uploader.total.uploaded == uploader.files.length)
$('form').submit();
});
uploader.start();
} else
alert('You must at least upload one file.');
e.preventDefault();
}
});
});
and here is the controller action that receives it...
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Upload(int? id, HttpPostedFileBase file)
{
if (file.ContentLength > 0)
{
var parts = Request.UrlReferrer.AbsolutePath.Split('/');
var theId = parts[parts.Length - 1];
var fileName = theId + "_" + Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
file.SaveAs(path);
}
return Content("Success", "text/plain");
}
As you can see, i have had to make the id parameter nullable, and i extract this manually in the action method.
How can i ensure that the values are sent with each form post correctly?
short answer : YES!
use multipart_params options like this:
multipart_params:
{
__RequestVerificationToken: $("#modal-dialog input[name=__RequestVerificationToken]").val()
}
short answer: you can't.
What you can do in this case is pass your token either as another multipart paramenter (if using that), or as part of the URL as a GET parameter, but nothing from the form will be sent by plupload as it builds its own request.
Another possibility is using custom headers to pass back the token to the server (plupload has a headers option), but whichever is the method you use, you will have to process it on your backend to validate it.

Backbone.js REST URL with ASP.NET MVC 3

I have been looking into Backbone.js lately and i am now trying to hook it up with my server-side asp.net mvc 3.
This is when i discovered a issue. ASP.NET listens to different Actions, Ex: POST /Users/Create and not just POST /users/. Because of that, the Model.Save() method in backbone.js will not work.
How should we tackle this problem? Do i have to rewrite the Backbone.Sync?
The answer is not to override Backbone.sync. You rarely would want to do this. Instead, you need only take advantage of the model's url property where you can assign a function which returns the url you want. For instance,
Forum = Backbone.Model.extend({
url: function() {
return this.isNew() ? '/Users/Create' : '/Users/' + this.get('id');
}
});
where the url used for a model varies based upon whether the model is new. If I read your question correctly, this is all you need to do.
You either have to tell ASP.NET MVC to route proper REST urls or fix Backbone.sync so it sends the GET/POST requests at the proper URLs.
Backbone works with REST not with RESTful URLs. There may be an OS implementation of Backbone.sync that matches your urls though.
Recommend URLs that play more nicely with Backbone:
GET /forums -> index
GET /forums/new -> new
POST /forums -> create
GET /forums/:forum -> show
GET /forums/:forum/edit -> edit
PUT /forums/:forum -> update
DELETE /forums/:forum -> destroy
I wrote a blog post recently describing how to bind .NET MVC to the default Backbone service layer.
Like previous posters have mentioned, there are a number of approaches you could take. I prefer this approach because it requires little configuration.
The controller:
public class ZocController : Controller
{
public ActionResult Docs()
{
return Json(GetDocs(), JsonRequestBehavior.AllowGet);
}
[ActionName("Docs")]
[HttpPost]
public ActionResult HandlePostDoc(Doctor doc)
{
doc.id = Guid.NewGuid();
CreateDoc(doc);
return Json(doc);
}
[ActionName("Docs")]
[HttpPut]
public ActionResult HandlePutDoc(Doctor doc)
{
UpdateDoc(doc);
return new EmptyResult();
}
[ActionName("Docs")]
[HttpDelete]
public ActionResult HandleDeleteDoc(Guid id)
{
DeleteDoc(id);
return new EmptyResult();
}
}
The Backbone
window.Doctor = Backbone.Model;
window.Doctors = Backbone.Collection.extend({
model: Doctor,
url: '/zoc/docs'
});
i found the following code in https://github.com/sgentile/BackboneContacts
/// <reference path="backbone.js" />
ModelBase = Backbone.Model.extend({
defaults: {
id: null
},
url: function (type) {
//expecting the following conventions on the server:
//urlRoot should be the controller : controller/
//create → POST /action
//read → GET /action[/id]
//update → PUT /action/id
//delete → DELETE /action/id
var fqUrl = this.urlRoot;
switch (type) {
case "POST":
fqUrl += "create";
break;
case "PUT":
fqUrl += "update";
break;
case "DELETE":
fqUrl += "delete/" + this.get('id');
break;
case "GET":
fqUrl += "read/" + this.get('id');
break;
}
return fqUrl;
}
});
var methodMap = {
'create': 'POST',
'update': 'PUT',
'delete': 'DELETE',
'read': 'GET'
};
// Helper function to get a URL from a Model or Collection as a property
// or as a function.
var getUrl = function (object) {
if (!(object && object.url)) return null;
return _.isFunction(object.url) ? object.url() : object.url;
};
// Throw an error when a URL is needed, and none is supplied.
var urlError = function () {
throw new Error('A "url" property or function must be specified');
};
Backbone.sync = function (method, model, options) {
var type = methodMap[method];
options.url = _.isString(this.url) ? this.url : this.url(type);
// Default JSON-request options.
var params = _.extend({
type: type,
dataType: 'json'
}, options);
// Ensure that we have a URL.
if (!params.url) {
params.url = getUrl(model) || urlError();
}
// Ensure that we have the appropriate request data.
if (!params.data && model && (method == 'create' || method == 'update')) {
params.contentType = 'application/json';
params.data = JSON.stringify(model.toJSON());
}
// For older servers, emulate JSON by encoding the request into an HTML-form.
if (Backbone.emulateJSON) {
params.contentType = 'application/x-www-form-urlencoded';
params.data = params.data ? { model: params.data} : {};
}
// For older servers, emulate HTTP by mimicking the HTTP method with `_method`
// And an `X-HTTP-Method-Override` header.
if (Backbone.emulateHTTP) {
if (type === 'PUT' || type === 'DELETE') {
if (Backbone.emulateJSON) params.data._method = type;
params.type = 'POST';
params.beforeSend = function (xhr) {
xhr.setRequestHeader('X-HTTP-Method-Override', type);
};
}
}
// Don't process data on a non-GET request.
if (params.type !== 'GET' && !Backbone.emulateJSON) {
params.processData = false;
}
// Make the request.
return $.ajax(params);
};

jqGrid display default "loading" message when updating a table / on custom update

I have a case where I need to update a jqgrid based on some search criteria which the user selects. I can get the data to update , but I would want the loading message to show while the new data is being fetched. Can someone please let me know how to get that working ?
Current code follows
var ob_gridContents = $.ajax( {
url : '/DisplayObAnalysisResults.action?getCustomAnalysisResults',
data : "portfolioCategory="+ $('#portfolioCategory').val()
+"&subPortfolioCategory="+ $('#subPortfolioCategory').val()
+ "&subportfolio=" + $('#subportfolio').val(),
async : false
}).responseText;
var ob_Grid = jQuery('#OBGrid')[0];
var ob_GridJsonContents = eval('(' + ob_gridContents + ')');
$('#ob_Grid').trigger("reloadGrid");
ob_Grid.addJSONData(ob_GridJsonContents);
ob_Grid = null;
ob_GridJsonContents = null;
}
If I correct understand what you will, I can recommend you to use jQuery blockUI plugin (http://malsup.com/jquery/block/). Then you don’t need more to use "async : false" parameter of $.ajax function and do something like following:
var WaitMsg = function () {
jQuery('#main').block({ message: '<h1>Die Daten werden vom Server geladen...</h1>' });
};
var StopWaiting = function () {
jQuery('#main').unblock();
};
WaitMsg();
$.ajax({url : '/DisplayObAnalysisResults.action?getCustomAnalysisResults',
data: jQuery.param({portfolioCategory: $('#portfolioCategory').val(),
subPortfolioCategory: $('#subPortfolioCategory').val(),
subportfolio: $('#subportfolio').val()}),
complete: function (data, status) {
if (status === "success" || status === "notmodified") {
var ob_GridJsonContents = jQuery.parseJSON(data.responseText);
...
}
StopWaiting();
},
error: function (xhr, st, err) {
// display error information
StopWaiting();
}
});
I recommend you don’t build parameters with the way like
"portfolioCategory="+ $('#portfolioCategory').val()
+"&subPortfolioCategory="+ $('#subPortfolioCategory').val()
+ "&subportfolio=" + $('#subportfolio').val()
because you can receive encoding problems, if data returned by .val() have some special characters. You could use JavaScript function encodeURIComponent in such cases (like encodeURIComponent($('#portfolioCategory').val()))
or jQuery.param function if you construct a string like p1=val1&p2=val2&...pN=valN.
Best regards
Oleg

Resources