I'm using .NET web methods to deliver CRUD services to my datasources. I am having a strange issue wherein every time I perform either a create or delete operation previous such operations are duplicated. For instance if I create a record it will call the create method once, but the next time it will call the method twice: once with the new data and once to duplicate the first call. With each new method call all previous create and delete calls are duplicated.
I suspect that the datasource is not getting an expected response from the server so it mistakenly believes that previous operations failed, queues them, and tries again on the next operation.
All my create and destroy web methods take POST operations, and merely absorb the incoming data without replying with data. In fact they are VB.NET subs with no return values. They typically have a small number of string arguments that are passed to a stored procedure in a remote database. Hence my datasource transport has a parametermap function that for all operations simply returns the arguments "stringified" for JSON.
Any idea why the datasource is repeating the create and destroy operations?
22 Answers, 1 is accepted
All prior CRUD operations are being repeated. In my case, I create (POST) a new record. Then I update (PUT) an existing record. Once I click Update, the previous record I created, gets POSTed again, and then my existing record gets updated. As a side effect, the popup editor dialog does not close. If I click update again, a third POST of the previous "new" record is created again, and the record I just updated gets updated again.
This is very odd behavior.
UPDATE:
I figured it out based on the replies in another related forum post. The key here is that your Post method returns the newly created entity. If you don't, the id of the entity you just added to your grid never gets changed to its generated id in your database. Therefore, the entity in your grid is always "dirty" and keeps getting posted on subsequent POST/PUT actions.
It would be helpful if the Tutorial documentation presented a working Create action for the Kendo DataSource. I find it odd that all of the other actions are represented well (read, update, and delete), but not create.
The returned to Add is:
{"Data":[{"Id":1773740819...[ommited]...}],"Total":1,"AggregateResults":null,"Errors":{"FechaNacimiento":{"errors":["El valor \u002729/10/2012 09:14:44 a.m.\u0027 no es válido para FechaNacimiento."]}}}
So, for anybody who's experiencing this issue, check the returned data to the controller for errors
Hope I was clear with the explanation, my english is not so good
For instance if I create a record it will call the create method once, but the next time it will call the method twice: once with the new data and once to duplicate the first call. With each new method call all previous create and delete calls are duplicated,....
while reloading the page
As Brett wrote - the item with the updated ID needs to be returned from the server in order to avoid posting the item again the next time the DataSource is synchronized. The ID is used by the DataSource to determine if the item is new and the ID will not be updated without returning it with the response.
Regards,Daniel
the Telerik team
All prior CRUD operations are being repeated. In my case, first I create (POST) a new record without any problem. Then I update (PUT) an existing record without reloading the page. Once I click Update, gets POSTed twice. Now, I want delete an item, Once I click delete, gets POSTed third, and so on.
Seems the popup editor dialog does not close, And the post event repeated.
Can you share a sample project which reproduces the problem or the full code you are using?
Regards,Daniel
the Telerik team
function ajaxCall(url, success, type) { $.ajax({ url: url, success: function (html) { success(html); }, type: type }); } function wnd() { return $('#window').closest(".k-window-content").data("kendoWindow"); } function closeWindow() { var kendoWindow = $('#window').closest(".k-window-content").data("kendoWindow").close(); return false; } function openWindow(url, title, windowName) { ajaxCall(url, function (html) { wnd(windowName).content(html); wnd(windowName).center(); $('#' + windowName + '.k-window-content').height('auto').width('200px'); wnd(windowName).title(title); wnd(windowName).open(); }); }
@model KendoSample.Models.UserEntity <script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script> @{ Layout = null; } @using (Ajax.BeginForm("InsertUpdate","User",null,new AjaxOptions() { OnSuccess = "OperationComplete" ,HttpMethod= "POST"},new {id="frmInsert"})) { <div> @Html.ValidationSummary(true) @Html.Hidden("Identifier") @Html.Hidden("IsUpdate") <fieldset class="t-edit-form-container" > <legend>Content</legend> <div class="editor-label"> @Html.LabelFor(model => model.UserName) </div> <div class="editor-field"> @Html.EditorFor(model => model.UserName) @Html.ValidationMessageFor(model => model.UserName, "*") </div> <div class="editor-label"> @Html.LabelFor(model => model.Email) </div> <div class="editor-field"> @Html.EditorFor(model => model.Email) @Html.ValidationMessageFor(model => model.UserName, "*") </div> <div class="editor-label"> @Html.LabelFor(model => model.PostId) </div> <div class="editor-field"> @Html.EditorFor(model => model.PostId) </div> </fieldset> <div> @{Html.Kendo().Menu() .Name("footerMenu") .Items(item => { item.Add().Text("Save").ImageUrl("~/Content/images/Save.png").HtmlAttributes(new { onclick = "$('form').submit();" }); item.Add().Text("Cancel").ImageUrl("~/Content/images/Cancel.png").HtmlAttributes(new { onclick = "return closeWindow();" }); }) .Render(); } </div> </div> }
The code you provided does not seem to use the Kendo DataSource in any way which is the topic of this thread. Multiple requests made in your scenario indicates that there is an event bound multiple times. If the partial view is loaded each time after an update, this would be caused by adding jquery.unobtrusive-ajax.min.js in the partial view.
Regards,Daniel
the Telerik team
Thank you much, fixed it.
The problem associated with this:
<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
I need to know the code to post back my primaryID to the grid so I don't get duplications. When adding records.
Here is my current code:
public ActionResult Loading_Create([DataSourceRequest] DataSourceRequest request, Models.FacultyLoading facultyload)
{
if (facultyload != null && ModelState.IsValid)
{
FacultyLoading fl = new FacultyLoading();
fl.Responsibility = facultyload.Responsibility;
fl.YearTerm = facultyload.YearTerm;
fl.RouteID = facultyload.RouteID;
fl.Notes = facultyload.Notes;
fl.LoadFactor = facultyload.LoadFactor;
fl.LoadPrcnt = facultyload.LoadPrcnt;
fl.CreditHours = facultyload.CreditHours;
fl.ScholarshipPrcnt = facultyload.ScholarshipPrcnt;
fl.CitizenshipPrcnt = facultyload.CitizenshipPrcnt;
fl.TotalLoad = facultyload.TotalLoad;
db.FacultyLoadings.Add(fl); // How can I change this to return the primary key from the Server to the grid?
db.SaveChanges();
return RedirectToAction("Index");
}
return Json(new[] { facultyload }.ToDataSourceResult(request, ModelState));
}
I have seen this code with a possible fix on another thread. I tried assigning it to my facultyload.LID but got errors.
Steve
-----------------
I had the same issue. The resolution is to set the primary key after
the update. The demos use a repository class so its not that clear what
is going on. Here is the code I use, old (broken) and new (fixed):
Old: the entity model has an "Add" function that does its thing and
returns the new primarykey int. The entity is being updated in the
business model with the new primarykey, but isn't passing back for
whatever reason.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Customer_Create([DataSourceRequest] DataSourceRequest request, CustomerModel entity)
{
if (entity != null && ModelState.IsValid)
{
entity.Add();
}
return Json(new[] { entity }.ToDataSourceResult(request, ModelState));
}
New: Now, simply use the returned int and set the primarykey (id) to it. Pass back to Kendo. All good now.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Customer_Create([DataSourceRequest] DataSourceRequest request, CustomerModel entity)
{
if (entity != null && ModelState.IsValid)
{
entity.Id =entity.Add();
}
return Json(new[] { entity }.ToDataSourceResult(request, ModelState));
}
----------------
Actually the new ID should be assigned after saving the changes:
db.FacultyLoadings.Add(fl);
db.SaveChanges();
facultyload.LID = fl.LID;
Regards,
Daniel
Telerik
Here is a real-life demo from our documentation which shows how to use $http and its promises.
The relevant code is this:
transport: {
read: function (e) {
$http.jsonp('http://demos.telerik.com/kendo-ui/service/Products?callback=JSON_CALLBACK').
success(function(data, status, headers, config) {
e.success(data)
}).
error(function(data, status, headers, config) {
alert('something went wrong')
console.log(status);
});
}
Implementing the create, update and destroy methods is similar.
Regards,
Atanas Korchev
Telerik
Hopefully this helps someone.. using MVC and some version of Kendo UI from 2013.
If the ModelState has errors, Kendo thinks that something went wrong and will try to duplicate the request later. My "Add" functions were working correctly because I was doing a "ModelState.IsValid" check in the controller.. But, for my deletes, all I cared about was getting the ID.. So I wasn't doing a check on the ModelState before removing the item. And, it turned out that there were ModelState errors when I was performing my "Delete" action. This causes subsequent requests to attempt to remove those items again. So, I updated my controller "Delete" action so that upon successfully deleting the object server-side, I'd remove all model errors.. Like so..
if (mSuccessDelete)
{
// It was successful. Remove all model state errors so Kendo does not think something went wrong.
foreach (var modelValue in ModelState.Values)
{
modelValue.Errors.Clear();
}
return Json(ModelState.ToDataSourceResult());
}​
Regards,