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());
Related
When selecting an item from a bootstrap dropdown, I need to be updating a property on the page model to reflect the selection.
To achieve this, I'm doing an ajax post with jquery to the handler method:
function setStream(streamId, streamName) {
// If streamId is NaN or undefined, set to 0, assuming user is viewing all streams.
streamId = (streamId === NaN || streamId === undefined) ? 0 : streamId;
console.log(`setStream(${streamId}, ${streamName})`);
streamName = streamName === undefined ? "All streams" : streamName;
$("#Booking_Stream_Id").val(streamId);
$("#titleStream").html(`| ${streamName}`);
// Update the stream on the model.
const _streamId = parseInt(streamId);
$.ajax({
method: "GET",
url: "/Index?handler=Stream?newStreamId=" + _streamId,
headers: {
"RequestValidationToken": "#token"
},
error: function (data) {
console.log(data);
}
});
}
Dev tools shows the request succeeded:
Request URL: https://localhost:5001/Index?handler=Stream?newStreamId=0
Request Method: GET
Status Code: 200
But the breakpoint was never hit and the property never updated.
public async Task OnGetStream(int newStreamId)
{
logger.LogInformation("Current stream on booking is {stream}", this.Booking.Stream.Id);
var stream = await context.Streams.FindAsync(newStreamId);
if (stream is null)
{
// Assume user is attempting to view all streams.
this.Booking.Stream = new Stream { Id = 0, Name = "All streams" };
}
else
{
this.Booking.Stream = stream;
}
logger.LogInformation("NEW stream on booking is {stream}", this.Booking.Stream.Id);
}
Additionally my calls to the logger aren't being written to the console but that's more of a minor issue.
Given the above code, is there something I've done wrong here? I feel like this is dead simple stuff but for whatever reason I can't seem to get it working.
Any assistance will be appreciated.
url: "/Index?handler=Stream?newStreamId=" + _streamId,
You have a ? instead of & separating your query string values. Try this instead:
url: "/Index?handler=Stream&newStreamId=" + _streamId,
I have a controller that applies to an edit view in asp.net MVC. I have an actionlink that sends the row Id to the controller which then brings back the correct row to see in the associated view.
I then have a partial view below that. That also requires a parameter in order to bring associated data from another table.
I have a Jquery .post call that runs after the page is loaded. I can alert out and show the exact value I want to send to the controller.
$(document).ready(function () {
var url = "/Home/MmsAndNotes";
var Uc = $("#Id").serialize();
alert(Uc);
$.post(url, {Id: Uc}, function (data) {
alert("what is Uc now? " + uc); //just for testing
});
})
I have also used it this way.
$(document).ready(function () {
var url = "/Home/MmsAndNotes";
var Uc = $("#Id").val();
alert(Uc);
$.post(url, Uc, function (data) {
});
})
the alerts come up and show the value I want. However, when the .post call runs, it sends a null value. Here is my controller.
public ActionResult MmsAndNotes(string Id)
{
//Declare LogisticsVM for individual policy info
LogisticsMMS_NotesVM model;
if(uc == null)
{
return Content("uc is empty.");
}
int val = Convert.ToInt32(uc);
using (Db db = new Db())
{
LogisticsMMS_NotesDTO dto = db.LogisticsMMS.Find(val);
//confirm policy exists
if (dto == null)
{
return Content("This policy cannot be found." + val);
}
model = new LogisticsMMS_NotesVM(dto);
}
return PartialView(model);
}
It always returns as uc is empty. I repeat, when the alerts come up. I get the correct value to send to the controller. But once it sends, something happens and it converts to null. HELPPPPP.. please .. I'm losing my mind over this one.
I don't know why, but changing my $.post() call to an $.ajax({}) call solved the issue. As you can see above, I had the $.post call. Using this instead,
$.ajax({
type: "POST",
url: "/Home/MmsAndNotes",
dataType: 'text',
data: { Id: Uc }
});
Solved it. I thought Jquery's shortened calls worked the same way. They certainly might, but doing it this way was the only way it worked for me.
P.S. Thanks Tyler (above) for your comments.
this solution should be work :
$(document).ready(function () {
$.ajax({
url: '/Home/MmsAndNotes',
type: 'GET',
dataType: "html",
data: { uc : $("#Id").val() },
success: function (result) {
code here
}
});
})
You need to verify if $("#Id").val() is not empty
I have a regular form on view with a set of inputs. I use jQuery to serialize and post it.
$("#formId").submit(function (e) {
e.preventDefault();
var fields = {};
var formSerialized = $("#formId").serializeArray();
$.each(formSerialized, function (i, field) {
fields[field.name] = field.value; });
e.data = fields;
$.post("myUrl", {
FirstName: e.data.FirstName,
LastName: e.data.LastName
}, function (success) {
if (success) {
alert('Ok')
} else {
alert('fail');
}
});
}
});
On backend I have ASP.NET WebAPI2 server with action that gets this request and automatically binds all properties to model.
Now I need to add multiple file inputs to the same form.
Is there a way to:
- send files and regular properties that I send in code sample in the same time in the same request?
- is it possible to extend model on WebAPI side with HttpPostedFileBase properties and to keep automatic binding of data?
What is the best way to send regular text properties (values from form) + multiple files in the same request to process them in one single method on WebAPI2 side?
Thanks!
This answer discusses some options, but you might run into some browser compatibility issues:
jQuery Ajax File Upload
If it's an option, you might consider doing a regular non async form submission, and making sure your form has enctype="multipart/form-data", but if not, you can try some of the things discussed in that link. Hope this helps
Edit - another approach is to use this jQuery form plugin: http://malsup.com/jquery/form/
In this case, I wasn't using a viewmodel but instead was binding the inputs directly to parameters, but I can't think of any reason why it wouldn't work the exact same way with a typical vm.
Example use:
Front end
#using (Html.BeginForm("SaveComment", "Comments", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
[text and file inputs, submit button]
}
<script>
$('#addNote form').ajaxForm({
success: function (response) {
$.notify(response.result, {
className: "success",
position: "top center"
});
//reload comments section
$.ajax({
url: './Comments/Index',
data: {
labelId: '#Model.LabelId',
orderNumber: '#Model.OrderNumber'
},
success: function (response) {
$('#commentsSection').html(response);
}
});
},
error: function () {
$.notify("Failed to save note");
},
beforeSubmit: function () {
$('#addNote').modal('toggle');
}
});
Back end
public JsonResult SaveComment(string saveNote, string labelId, string orderNumber, string comment, string criteria, HttpPostedFileBase file)
{
[text input named saveNote went into saveNote param]
[file input named file went into HttpPostedFileBase file param]
[...process other params...]
var ms = new MemoryStream();
file.InputStream.CopyTo(ms);
deliveryItemComment.Attachment = ms.ToArray();
db.SaveChanges();
var result = "Note Succesfully Added";
return Json(new { result = result }, JsonRequestBehavior.AllowGet);
}
Pretty ugly solution I suppose, but I ended in that way.
JS uses form data:
var formSerialized = $("formId").serializeArray();
var data = new FormData();
var files = $("#fileInputId").get(0).files;
data.append("File", files[0]);
$.each(formSerialized, function (i, field) {
data.append(field.name, field.value);
});
$.ajax({
type: "POST",
contentType: false,
processData: false,
url: "some URL",
data: data
}
});
On WebAPI side I have to separately read form fields and files from form data:
var myModel = new MyModel();
var root = HttpContext.Current.Server.MapPath("~/App_Data/");
var provider = new MultipartFormDataStreamProvider(root);
await Request.Content.ReadAsMultipartAsync(provider);
//Maps fields from form data into my custom model
foreach (var key in provider.FormData.AllKeys)
{
var value = provider.FormData.GetValues(key).FirstOrDefault();
if (value != null && value != "undefined")
{
var prop = myModel.GetType().GetProperty(key);
if (prop != null)
{
prop.SetValue(myModel, value, null);
}
}
}
//Resaves all files in my custom location under App_Data and puts their paths into list
var fileNames = new Collection<string>();
foreach (var file in provider.FileData)
{
var fileExt = file.Headers.ContentDisposition.FileName.Split('.').Last().Replace("\"", string.Empty);
var combinedFileName = string.Format("{0}.{2}", file.Headers.ContentDisposition.Name.Replace("\"", string.Empty), fileExt);
var combinedPath = Path.Combine(root + "CustomDirectory/", combinedFileName);
File.Move(file.LocalFileName, combinedPath);
fileNames.Add(combinedPath);
}
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.
I am trying to solve an issue with webservice call in my MVC 4 project. What I am doing is that when user submits form on page, I call webservice and wait for result. Meanwhile server returns callbacks (it is returning strings containing finished steps of work on server side). What I would like to do is to display contents of "log" I am building from callback on the page and refresh it repeatedly to display the progress.
The issue I run into is, that either I will have asynchronous call of webservice in my controller in which case I am not waiting for result from webservice and that means that user will not stay on the page that should be displaying progress, or I will call it synchronously, in which case javascript on the page will not get response from controller until the final response arrives (so no updates are displayed).
My desired flow is:
User submits the form
Server is called in controller
Server sends callbacks, controller processess them by expanding "log" variable with whatever arrives
User still sees the same page, where "log" (contained in specific div) is being periodically refreshed by javascript while controller waits for final result from server
Server returns final result
Controller finishes its code and returns new view
This is my post method, which currently doesnt wait for the response and proceeds immediately further:
[HttpPost]
public async Task<ActionResult> SubmitDetails
(DocuLiveInstallationRequest submittedRequest, string command)
{
request = submittedRequest;
try
{
switch (command)
{
case "Test":
{
request.OnlyTest = true;
DocuLiveInstallationStatus installStatus
= await IsValidStatus();
if (installStatus == null)
{
ViewBag.Fail = Resources.AppStart.TestNoResult;
return View("SubmitDetails", request); ;
}
else
{
status = installStatus;
if (status.Result)
{
ViewBag.Success = Resources.AppStart.TestSucces;
ViewBag.Log = installLog;
}
TempData["installationStatus"] = installStatus;
return View("SubmitDetails", request);
}
}
case "Submit":
{
request.OnlyTest = false;
DocuLiveInstallationStatus installStatus = await Install();
if (installStatus == null)
{
ViewBag.Fail = Resources.AppStart.InstallationNoResult;
return View("SubmitDetails", request); ;
}
else
{
status = installStatus;
TempData["installationStatus"] = installStatus;
TempData["installLog"] = installLog;
return RedirectToAction("Login",controllerName:"Login");
}
}
}
ViewBag.TestFail = Resources.AppStart.SubmitFailure;
return View("SubmitDetails", request); ;
}
catch
{
return View();
}
}
this is javascript I prepared for the view:
<script type="text/javascript">
$(document).ready(function () {
//$("#submitDetails").click(function () {
var progress = 0;
//$("#submitDetails").attr('disabled', 'disabled');
var statusUpdate = setInterval(function () {
$.ajax({
type: 'GET',
url: "/AppStart/GetInstallProgress",
datatype: "application/html; charset=utf-8",
success: function (data) {
if (data && data != "") {
$("div.status-message").text(progress);
}
}
});
}, 2000);
//});
});
</script>
Currently I just display the log on the next page (at this stage of development server returns response very swiftly), but I need to call the server, display progress from callbacks while waiting for result and THEN navigate to another page (depending on the result). I feel like I am very close, but I can't get it working.
PS: I am open to other solutions than updating page content. I don't really mind how the goal will be accomplished, but updating the page is preferred by the customer.