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。
如果你们中的任何人可能知道为什么这会影响它,我会对解释非常感兴趣!
首先:我发现了几个与此相关的问题,到目前为止 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。
如果你们中的任何人可能知道为什么这会影响它,我会对解释非常感兴趣!