This is a migrated thread and some comments may be shown as answers.

Grid, extra entry if I enter two items in a row

2 Answers 35 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Jon Smith
Top achievements
Rank 1
Jon Smith asked on 25 Apr 2013, 07:13 PM
I have an MVC4 application with a MVC defined Grid with CRUD operation. I am using inline Create and get a strange phenomena when I enter two entries in a row. The scenario is as follows:
  1.  I click 'Add New Item' button and an empty row appears at the top of the grid with the two editable items open for input.
  2. I enter the date new entry and click the 'Update' button.
  3. I see a single POST go back to the MVC application and the create works correctly.
  4. As the next immediate step I then press 'Add New Item' button again and enter  a new entry.
  5. On pressing the 'Update' button I see TWO Posts go back to the MVC application.
           - The first is the new entry
           - The second is the data for the entry entered in steps 1 to 3.

That is rather strange, and my database, which does not allow entries with the same name fails the second (duplicate) entry. If I press F5 or next page on the grid after step 3 then I do not have this problem.

My .razor view is:

@{
    ViewBag.Title = "Services";
}
 
<h2>Services</h2>
 
@*<div id="message" class="Message"></div>*@
@Html.AntiForgeryToken()
 
@(Html.Kendo().Grid<ServiceLayer.Models.DTOs.SmServiceDto>()
      .Name("Services")
      .Columns(columns =>
                   {
                       columns.Bound(p => p.SmServiceId).Hidden();
                       columns.Bound(p => p.ShortName);
                       columns.Bound(p => p.FullName);
                       columns.Bound(p => p.Locked);
                       columns.Command(command => { command.Edit(); command.Destroy(); }).Width(172);
                   })
      .ToolBar(toolbar => toolbar.Create())
      .Editable(editable => editable.Mode(GridEditMode.InLine))
      .Pageable()
      .Sortable()
      //.Scrollable()
      //.HtmlAttributes(new {style = "height:430px;"})
      .DataSource(dataSource => dataSource
                                    .Ajax()                               
                                    .PageSize(10)
                                    .Events(events => events.Error("error_handler"))
                                    .Model(model =>
                                               {
                                                   model.Id(p => p.SmServiceId);
                                                   model.Field(x => x.SmServiceId).Editable(false);
                                                   model.Field(x => x.Locked).Editable(false);
                                               })
                                    .Create(x => x.Action("AjaxServiceCreate", "Model").Data("sendAntiForgery").Type( HttpVerbs.Post))
                                    .Read(read => read.Action("AjaxServiceRead", "Model"))
                                    .Update(x => x.Action("AjaxServiceUpdate", "Model").Type( HttpVerbs.Post).Data("sendAntiForgery"))
                                    .Destroy(x => x.Action("AjaxServiceDelete", "Model").Type( HttpVerbs.Post).Data("sendAntiForgery"))
      ))
       
@section scripts {
<script type="text/javascript">
    function error_handler(e) {
        if (e.errors) {
            var message = "Errors:\n";
            $.each(e.errors, function (key, value) {
                if ('errors' in value) {
                    $.each(value.errors, function () {
                        message += this + "\n";
                    });
                }
            });
            alert(message);
        }
    
 
    function sendAntiForgery() {
        return { "__RequestVerificationToken": $('input[name=__RequestVerificationToken]').val() };
    }
 
</script>
}

The MVC actions are pretty standard copies of the format on your examples site, but with ValidateAntiForgeryToken added.

[AllowAnonymous]
        public ActionResult Services(IListSmService service)
        {
            return View();
        }
 
        [AllowAnonymous]
        public ActionResult AjaxServiceRead([DataSourceRequest]DataSourceRequest request, IListSmService service)
        {
            return Json(service.GetList().ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
        }
 
        [AllowAnonymous]
        [AcceptVerbs(HttpVerbs.Post)]
        [ValidateAntiForgeryToken]
        public ActionResult AjaxServiceCreate([DataSourceRequest] DataSourceRequest request, ISmServiceDto newItem, ICreateSmService service)
        {
            if (newItem != null && ModelState.IsValid)
            {
                var response = service.Create(newItem);
                if (!response.IsValid)
                    //errors, so copy the errors over to the ModelState
                    response.CopyErrorsToModelState(ModelState);
            }
 
            return Json(new[] { newItem }.ToDataSourceResult(request, ModelState));
        }
 
        [AllowAnonymous]
        [AcceptVerbs(HttpVerbs.Post)]
        [ValidateAntiForgeryToken]
        public ActionResult AjaxServiceDelete([DataSourceRequest] DataSourceRequest request, ISmServiceDto itemToDelete, IDeleteSmService service)
        {
            if (itemToDelete != null)
            {
                var response = service.Delete(itemToDelete.SmServiceId);
                if (!response.IsValid)
                    //errors, so copy the errors over to the ModelState
                    response.CopyErrorsToModelState(ModelState);
            }
 
            return Json(ModelState.ToDataSourceResult());
        }

I must be doing wrong but I can't see it. Your help would be appreciated.

2 Answers, 1 is accepted

Sort by
0
Daniel
Telerik team
answered on 29 Apr 2013, 03:28 PM
Hello,

Does the service.Create method assign the ID to the new item? The dataSource uses the item ID to determine if the item is new so a request will be sent again to create the item if the ID is not assigned.

Regards,
Daniel
the Telerik team
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Jon Smith
Top achievements
Rank 1
answered on 29 Apr 2013, 06:15 PM
Hi Daniel,

Thank you. That was the problem and I marked this as fixed. I had to change my ICreateSmService service to set the Key in the dto class and that fixed it.

Would you be so kind as to provide a link to the documentation where this specific issue is described as there may be other things I have missed too. It was a nasty bug to find.

Thanks.
Tags
Grid
Asked by
Jon Smith
Top achievements
Rank 1
Answers by
Daniel
Telerik team
Jon Smith
Top achievements
Rank 1
Share this question
or