Kendo 网格 - 数据源更新未命中控制器

Kendo Grid - Datasource Update not hitting controller

首先:我发现了几个与此相关的问题,到目前为止 none 的答案对我有用。事实上,我还没有找到 已接受 的答案!

我有一个 MVC 4 应用程序、一个 cshtml 页面和它下面的几层局部视图。

主视图(kendo 选项卡,无表单元素,向下钻取选项卡 #1):

<div class="container-fluid" style="margin-left: 10px; margin-right: 10px; padding-right: 30px;">
    @(Html.Kendo().TabStrip()
            .Name("tabStrip")
            .Events(e => e.Select("tabstrip_select"))
            .Items(items =>
            {
                items.Add()
                     .Text("Clone Assembly")
                     .Selected(true)
                     .Content(@<text>@Html.Partial("_Assembly", Model)</text>);
                items.Add()
                     .Text("Submit")
                     .Visible(@Model.Status == (int)SessionStatuses.Started)
                     .HtmlAttributes(new { userWorkSessionId = Model.UserWorkSessionId })
                     .LoadContentFrom("_AssemblyStarted", "ProductReuse", new { userWorkSessionId = Model.UserWorkSessionId });
                items.Add()
                     .Text("Session Results")
                     .Visible(@Model.Status >= (int)SessionStatuses.Submitted)
                     .HtmlAttributes(new { userWorkSessionId = Model.UserWorkSessionId })
                     .LoadContentFrom("_AssemblySubmitted", "ProductReuse", new { userWorkSessionId = Model.UserWorkSessionId });
            })
    )
</div>

_assembly 局部视图(kendo 网格):

@using (Html.BeginForm("Assembly", "ProductReuse", FormMethod.Post, new {id = "frmStartScreen"}))
{
    @Html.HiddenFor(m => m.Status)
    @Html.HiddenFor(m => m.UserWorkSessionId)

    <div class="row">
        <div class="panel panel-info">
            <div class="panel-heading">
                <div class="panel-heading text-center">
                    <h2 class="pr">@string.Format("{0} | {1} | {2}", Model.GlobalPartNum, Model.CloneScopeDisplay, Model.StatusDisplay)</h2>
                </div>
            </div>
            <div class="panel-body" style="margin-bottom: 10px; margin-top: 10px;">
                <div class="row">
                    @(Html.Kendo().Grid<BomViewModel>()
                          .Name("bom-prGrid-kendoGrid")
                          .HtmlAttributes(new {@class = "prGrid"})
                          .ClientRowTemplate("")
                          .Columns(columns =>
                          {
                              if (Model.StatusDisplay.Equals("Started"))
                              {
                                  columns.Command(cmd => cmd.Edit()).Width(80);
                              }
                              columns.Bound(g => g.BomId).Hidden();
                              columns.Bound(g => g.IsEditable).Hidden();
                              columns.Bound(g => g.Row).Width(75).Title("Row");
                              columns.Bound(g => g.PartNum).Width(125).Title("DWG/<br/>Part No");
                              columns.Bound(g => g.Qty).Width(80).HtmlAttributes(new {style = "text-align:center"}).Title("Qty");
                              columns.Bound(g => g.ItemDesc).Width(350).Title("Description");
                          })
                          .DataSource(dataSource => dataSource
                              .Ajax()
                              .Model(model =>
                              {
                                  model.Id(g => g.Row);
                                  model.Field(m => m.Row).Editable(false);
                              })
                              .PageSize(100)
                              .Read(r => r.Action("GetCloneAssembly", "AjaxProductReuse").Data("ProductReuseGridReadData"))
                              .Update(u => u.Action("UpdateBomItem", "AjaxProductReuse").Type(HttpVerbs.Post))
                              .Events(e => e.Error("ajax_error").Sync("dataSource_sync").Change("dataSource_change"))
                          )
                          .Events(e => e.DataBound("onDataBound").Edit("onEdit"))
                          .Pageable(pager => pager
                              .Input(true)
                              .Numeric(true)
                              .Info(true)
                              .PreviousNext(true)
                              .Refresh(true)
                              .PageSizes(new int[] {100, 250, 500, 1000})
                          )
                          .ToolBar(toolbar =>
                          {
                          toolbar.Template(
                                  @<text>
                                      <div class="container-fluid otherElements" style="padding-top: 5px; padding-bottom: 5px;">
                                          @Html.Partial("_CloneAssembly", Model)
                                      </div>
                                   </text>);
                          })
                          .Excel(excel => excel.FileName("ClonableBom.xlsx").Filterable(true).AllPages(true).ProxyURL(Url.Action("ExcelProxy", "AjaxProductReuse")))
                          .Sortable()
                          .Scrollable()
                          .Filterable()
                          //.Editable(editable => editable.Mode(GridEditMode.PopUp).TemplateName("BOMForm").Window(w => w.Title("Manage BOM Item").Name("BOMForm")))
                          .Editable(editable => editable.Mode(GridEditMode.PopUp).TemplateName("BOMForm"))
                          .Resizable(resizing => resizing.Columns(true)).Reorderable(reorder => reorder.Columns(true))
                          )
                </div>
            </div>
        </div>
    </div>
}

控制器(主页get/post):

[HttpGet]
public ActionResult Assembly(int userWorkSessionId = int.MinValue)
{
    var response = GetCachedCurrentWorkSession(userWorkSessionId);
    return View(response);
}

[HttpPost]
public ActionResult Assembly(AssemblyViewModel command)
{
    var saveServiceCommand = _mapper.Map<WorkSessionModel>(command);
    var serviceResponse = _productReuseService.ApplyGlobalSettingsCommand(saveServiceCommand);
    var response = SaveCachedCurrentWorkSession(serviceResponse);

    return View(response);
}

Ajax 控制器(处理数据源读取和更新):

[HttpPost]
public JsonResult UpdateBomItem([DataSourceRequest] DataSourceRequest request, [Bind(Prefix = "models")]BomViewModel bomViewModel)
{
    var command = _mapper.Map<BomModel>(bomViewModel);
    var commandResponse = _productReuseService.UpdateBomItem(command);
    var response = _mapper.Map<List<BomViewModel>>(commandResponse);
    return Json(ToDataSourceResult(response, request, modelState: ModelState));
}

与 Telerik 网站上的几个演示相比,一切看起来都不错。但是,当我提交更新的弹出表单时,我遇到了奇怪的行为:

在这两种情况下,Ajax 调用从未在我的代码中中断(即:没有证据表明它确实进入了方法!)当我在程序集 POST 方法中中断时,模型为空,已初始化但为空。

它在第二个实例中所做的似乎是将网格中的 每一 行发送到主要操作方法而不是 ajax 处理程序。而且,最重要的是,跟踪中的 401 错误行看起来像是在击中 GET 而不是 POST 并被拒绝,因为 GET 只需要一个 INT。

我们中的一些人现在已经看过这个,none 的人知道是什么导致了这种行为。

有什么想法吗?

我最终更改了数据源上的 id 绑定:

.Model(model =>
{
    model.Id(g => g.Row);
    model.Field(m => m.Row).Editable(false);
})

更改为:

.Model(model => 
{ 
    model.Id(g => g.BomId); 
})

这解决了它。虽然 Row 是集合中的唯一 int,但 BomId 是数据库中定义的 PK。我不知道为什么这会有所作为。然而,即使 Kendo(和支持模型)对 PK 一无所知,因为它是一个没有实体信息的 POCO。

如果你们中的任何人可能知道为什么这会影响它,我会对解释非常感兴趣!