Kendo UI网格插入/更新创建重复记录(再次)

时间:2013-05-04 11:07:14

标签: json kendo-ui duplicates kendo-grid

我和Daniel在本主题中遇到的问题相同,但他的解决方案并不适用于我:

http://www.kendoui.com/forums/ui/grid/kendo-ui-grid-inserts-updates-create-duplicate-records.aspx#-jhxqRrNAUGsTFJaC-Ojwg

所以用例。用户一个接一个地添加2条新记录:

  1. Presses"添加新记录"网格按钮
  2. 填写字段(姓名=" Alex",金额= 10,评论="第一个")。
  3. 记录一个准备就绪。按'保存'。 (数据转到控制器而不是数据库)
  4. 用户查看网格中的一条记录

  5. 按"添加新记录"再次按钮

  6. 填写字段(姓名=" Bob",金额= 20,评论="第二")。
  7. 记录一个准备就绪。按'保存'。数据转到控制器而不是数据库。 在这一刻发生了一些事情,网格再次发送Ajax请求,记录一个数据给控制器。

  8. 用户更新网格并查看三条记录

    " Alex | 10 |第一" (重复记录)ID = 1

    "鲍勃| 20 |第二" ID = 2

    " Alex | 10 |第一" ID = 1

  9. 他们建议返回一个ID以正确绑定\更新数据源与新记录。 我返回它(来自数据库的新ID与bouns实体一起响应)!这没有用。 只有当我用F5添加第一个记录和刷新页面之后再添加第二个记录一切正常。但如果添加另一个,第三个记录 - 问题再次出现

    控制器中的代码:

    [HttpPost]
        public JsonResult Create(BonusDto bonusDto)
        {
            BonusAggregate bonus;
    
            if (bonusDto.Amount <= 0)
                throw new ArgumentOutOfRangeException("Amount should be more than 0");
    
            if (bonusDto.EmployeeId <= 0)
                throw new ArgumentNullException("You should specify an existing employee");
    
            using (var dbContext = new DatabaseContext())
            {
                BonusesRepository = new BonusesRepository(dbContext);
                var employeeRepository = new EmployeesRepository(dbContext);
                bonus = new BonusFactory(employeeRepository).Create(bonusDto);
    
                BonusesRepository.Save(bonus);
            }
    
            HttpContext.Response.StatusCode = (int)HttpStatusCode.Created;
            return Json(bonus); // try to return ID after bonus was saved
        }
    

    UI代码

    // creates bonuses grid control
    $("#bonusesGrid").kendoGrid({
        dataSource: bonusesDataSource,
        toolbar: ["create"],
        editable: "inline",
        columns: [
            "BonusId",
            "EmployeeId",
            {
                field: "EmployeeLastName",
                editor: employeeAutocompletingEditor,
                template: "#=EmployeeLastName#"
            },
            "Amount",
            {
                field: "Comment",
                titel: "Comment",
                editor: textareaEditor,
                filterable: {
                    operators: {
                        number: {
                            contains: "Contains"
                        }
                    }
                }
            },
            {
                command: ["edit"],
                title: " "
            }
        ],
        save: function(e) {
            if (newValueEmployeeId !== undefined && 
                                newValueEmployeeLastName !== undefined && 
                                newValueEmployeeLastName !== "") {
                                  setNewValueEmployeeIdAndLastName(newValueEmployeeId, newValueEmployeeLastName);
                                  gridDataSource.model.EmployeeId = newValueEmployeeId; // it's a hack to bind model and autocomplete control
                                  gridDataSource.model.EmployeeLastName = newValueEmployeeLastName;
                            } else {
                                  gridDataSource.model.EmployeeId = currentValueEmployeeId;
                                  gridDataSource.model.EmployeeLastName = currentValueEmployeeLastName;
    
                            }
        },
        edit: function(e) {
            setCurrentValueEmployeeIdAndLastName(e.model.EmployeeId, e.model.EmployeeLastName);
        },
        cancel: function(e) {
            setCurrentValueEmployeeIdAndLastName(e.model.EmployeeId, e.model.EmployeeLastName);
        }
    });
    

    奖金数据来源:

    // bind json result from /Bonuses/GetPagedJsonBonuses
            var bonusesDataSource = new kendo.data.DataSource({
                    transport: {
    
                        read: {
                             url: "@Url.Action("GetPagedJsonBonuses", "Bonuses")",
                             type : "GET",
                             contentType: "application/json",
                             dataType: "json",
                             cache: false
                        },
                        create: {
                            url: "@Url.Action("Create", "Bonuses")",
                            dataType: "json",
                            type: "POST"
                        },
                        parameterMap: function(options, operation) {
                            if (operation === "update" || operation === "create") {
    
                                // correct format for conversion 
                                var d = new Date(options.Date);
                                options.Date = kendo.toString(d, dateFormat);
    
                                // updates the BonusDTO.EmployeeId with selected value
                                if (newValueEmployeeId !== undefined)
                                    options.EmployeeId = newValueEmployeeId;
                            }
                            if(operation === "read") {
                                options.filter = setFormattedFilterDate(options.filter);
                            }
                            return options;
                        }
                    },
                    pageSize: 15,
                    serverPaging: true,
                    serverSorting: true,
                    serverFiltering: true,
                    error: showErrorMessage,
                    schema: {
                        data: "Data", // PagedResponse.Data
                        total: "TotalCount", // PagedResponse.TotalCount
                        model: {
                            id: "BonusId",  // Data
                            fields: {
                                EmployeeId: { type: "number" },
                                EmployeeLastName: {
                                    type: "string",
                                    editable: true,
                                    nulable: false,
                                    validation: { required: {message: "Employee's last name is required"}}
                                },
                                Date: {
                                    type: "date",
                                    editable: true,
                                    nullable: false,
                                    validation: {
                                        required: { message: "Date is required to be set" }
                                    }
                                },
                                Amount: {
                                    type: "number",
                                    editable: true,
                                    nullable: false,
                                    defaultValue: 1,
                                    validation: {
                                        required: { message: "Amount is required to be set" }
                                    }
                                },
                                Comment: { type: "string", editable: true }
                            } // fields
                        } // model
                    }// schema 
                });
    

8 个答案:

答案 0 :(得分:11)

我的代码中没有看到这个问题。但是我在创建和更新事件上有一个“完整”的事件处理程序,它刷新了网格 - 它可能对你有帮助:

  dataSource: {

    type: "jsonp",
    transport: {
        read: UrlBase + "getAll",
        update: {
            url: UrlBase + "Update",
            dataType: "jsonp",
            complete: function (e) {
                $("#grid").data("kendoGrid").dataSource.read();

            }
        },
        create: {
            url: UrlBase + "create",
            dataType: "jsonp",
            complete: function (e) {
                $("#grid").data("kendoGrid").dataSource.read();
            }
        },
        destroy: {
            url: UrlBase + "destroy",
            dataType: "jsonp",
            complete: function (e) {
                $("#grid").data("kendoGrid").dataSource.read();
            }
        }
    },
   ...

答案 1 :(得分:3)

是的,侮辱是正确的。你的&#34;创造&#34;操作结果从您的模型传递要保存到数据库的对象。让数据访问层中的INSERT返回数据库中新创建的密钥(&#34; ID&#34;)。现在使用此键设置&#34; ID&#34;您的模型上的字段传入操作结果,然后作为JSON传递回视图。现在网格应该知道它刚刚创建了这条记录,并且不需要再用它做任何事情。否则,模型对象返回&#34; ID&#34;字段设置为0,因此网格认为它仍然需要添加此记录。

[AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Grid_Create([DataSourceRequest] DataSourceRequest request, MyObject obj)
    {
        if (obj != null && ModelState.IsValid)
        {
            obj.Id = _myService.Create(obj);
        }

        return Json(new[] { obj }.ToDataSourceResult(request, ModelState));
    }

答案 2 :(得分:2)

如果在读取操作中未传递主键进行查看,则会发生此错误。

此致

答案 3 :(得分:2)

Quinton Bernhardt的完整事件的替代方案:将dataSource.read()绑定到kendo同步事件。

我使用的是剑道的C#MVC的html帮助器,它们不会暴露同步事件,因此我必须在设置网格后对其进行修改。

在窗口加载时:

var grid = $("#GridName").data("kendoGrid");
grid.dataSource.bind("sync", function () {
     $("#GridName").data("kendoGrid").dataSource.read();
});

保存请求完成后,同步事件将触发。 dataSource.read()从服务器获取最新信息,包括设置服务器端的ID。

答案 4 :(得分:2)

我有一个类似的问题,进行了各种试验但是通过以下试验确定了

<强> Jquery的

   create: {
                type: "POST",
                dataType: "json",
                contentType: "application/json; charset=utf-8",
                url: "../../ajax/ajaxGv.aspx/addstaff"
            },

            parameterMap: function (options, operation) {
                if (operation == "create" && options.models) {  
                    return JSON.stringify({ "oStaff": options.models });
                }

<强> VB.Net

   'Adding Staff
   <System.Web.Services.WebMethod()> _
 Public Shared Sub addStaff(ByVal oStaff As Object)
    Dim strJson As String = JsonConvert.SerializeObject(oStaff)
    Dim lstStaff As List(Of Staff) = JsonConvert.DeserializeObject(Of List(Of Staff))(strJson)
    Dim db As New LiveB2cDataContext
    Try

            db.Staff.InsertAllOnSubmit(lstStaff)
        Next
        db.SubmitChanges()

      'Fix is that you need to return the objects you have added in the database back as json to kendo

        strJson = JsonConvert.SerializeObject(lstStaff, Formatting.None)
        WriteJson(strJson) ' Returning the objects added as json back to Kendo
    Catch ex As Exception
        ErrorLog(ex)
    End Try

End Sub

Public Shared Sub WriteJson(strJson As String)
    Try

        HttpContext.Current.Response.Write(strJson)
        HttpContext.Current.Response.Flush()
        HttpContext.Current.ApplicationInstance.CompleteRequest()
        HttpContext.Current.Response.SuppressContent = True

    Catch ex As Exception
        ErrorLog(ex)
    End Try
End Sub

<强> Fix is that you need to return the objects you have added in the database back as json to kendo

答案 5 :(得分:0)

我不确定这是否是您的问题的一部分,但是在您的DataSource的架构模型中,您指定ID是名为“BonusId”的字段,但该字段未在字段数组中指定。

答案 6 :(得分:0)

我遇到了类似的问题。

我修复了它,但确保模型中的id引用了一个字段: -

model: {
      id: "Id",
      fields: {
           Id: { editable: false, type: "number" },
           AnotherName: { editable: true, type: "string" },
           AnotherId: { editable: true, type: "number" }
           }
      }

答案 7 :(得分:0)

这可能无法解决提问者的问题,但希望可以帮助有同样问题的人。

对于我们来说,这个问题是由JSON中返回的错误引起的。某些必需属性没有值,但与我们在网格中显示的数据无关。在网格中为这些属性提供默认值可以解决问题。

您可以使用Fiddler Web Debugging Tools查看返回的JSON。