这与我最近提出的另一个问题有关.我正在尝试将用户角色信息绑定到网格,我正在为用户分配角色.每个用户可以在数据库中担任多个角色,这些角色应使用Kendo UI MultiSelect进行编辑.
当我选择所需的角色并回发给控制器时,"RoleBasicModel"对象数组包含所需数量的角色,但它们的所有属性都是空的.
模型定义为:
public class UserInfo { public string UserId { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string UserName { get; set; } public string Roles { get; set; } public IEnumerableRoleList { get; set; } } public class RoleBasicModel { public string Id { get; set; } public string Text { get; set; } }
网格设置为:
@(Html.Kendo().Grid() .Name("userGrid") .Columns(columns => { columns.Bound(p => p.UserName); columns.Bound(p => p.FirstName); columns.Bound(p => p.LastName); columns.Bound(p => p.Roles).EditorTemplateName("RoleListEditor").Template(p => p.RoleList); columns.Command(command => { command.Edit(); command.Destroy(); }); }) .Filterable() .Sortable() .Resizable(r => r.Columns(true)) .Editable(editable => { editable.Mode(GridEditMode.InLine); editable.DisplayDeleteConfirmation("Are you sure you want to remove this user?"); }) .HtmlAttributes(new { style = "min-height:90px;max-height:450px;" }) .DataSource(dataSource => dataSource .Ajax() .Events(events => events.Error("error_handler")) .Model(model => { model.Id(p => p.UserId); model.Field(p => p.UserId).Editable(false); model.Field(p => p.FirstName).Editable(true); model.Field(p => p.LastName).Editable(true); model.Field(p => p.UserName).Editable(false); model.Field(p => p.RoleList).Editable(true); } ).Read(read => read.Action("GetAllUsers", "Admin").Type(HttpVerbs.Get)) .Update(update => update.Action("UpdateUser", "Admin").Type(HttpVerbs.Post)) .Destroy(update => update.Action("DeleteUser", "Admin").Type(HttpVerbs.Post)) ) )
我的编辑器模板使用了Kendo MultiSelect,定义如下:
@Html.Kendo().MultiSelect().Name("RoleList").DataTextField("Text").DataValueField("Id").BindTo((IEnumerable)ViewData["uroles"]).Placeholder("No role selected")
发送回服务器的数据是否为空是否有明显的原因?我怀疑我错过了MultiSelect控件中的某些内容,它将定义要使用的正确模型.我已经提到了经常被引用作为类似问题的答案的测试项目,但我对此也没有任何喜悦.
根据要求,我正在使用的控制器(简化版):
public ActionResult ManageUsers() { PopulateRoles(); return View(); } private void PopulateRoles() { ViewData["uroles"] = new ApplicationDbContext().Roles.Select(r => new RoleBasicModel { Text = r.Name, Id = r.Id }).ToList(); } [AcceptVerbs(HttpVerbs.Get)] public ActionResult GetAllUsers([DataSourceRequest]DataSourceRequest request) { using (var context = new ApplicationDbContext()) { var allUsers = context.Users.ToList().Select(x => new UserInfo { UserName = x.UserName, UserId = x.Id, FirstName = x.FirstName, LastName = x.LastName, RoleList = x.Roles.Select(p => new RoleBasicModel { Text = p.Role.Name, Id = p.RoleId }), Roles = string.Join(", ", x.Roles.Select(p => p.Role.Name).ToList()) }).ToList(); return Json(allUsers.ToDataSourceResult(request), JsonRequestBehavior.AllowGet); } } [AcceptVerbs(HttpVerbs.Post)] public ActionResult UpdateUser([DataSourceRequest] DataSourceRequest request, UserInfo user) { if (user != null && ModelState.IsValid) { using (var context = new ApplicationDbContext()) { // Do something with the user details } } return Json(new[] { user }.ToDataSourceResult(request, ModelState)); }
编辑:在查看发回服务器的数据时,看起来好像未正确解析所选对象的数组.格式应为RoleList [0] .Id:123456,而是RoleList [0] [Id]:123456.我认为这可能是MultiSelect控件的问题,而不是我编写的任何代码?
因此,我最终解决了问题所在。根据我的编辑,我注意到数据没有从MultiSelect控件正确序列化。
我花了一些时间使Kendo网站上的示例可用,我注意到他们将正确和错误地序列化的数据发布到了服务器上。他们使用的技巧(对我来说似乎很荒谬)是,在网格的Update函数上,他们为自己序列化了数组中的任何数据,即
.Update(update => update.Action("UpdateUser", "Admin").Type(HttpVerbs.Post).Data("serialize"))
其中“序列化”功能定义为:
function serialize(data) { for (var property in data) { if ($.isArray(data[property])) { serializeArray(property, data[property], data); } } } function serializeArray(prefix, array, result) { for (var i = 0; i < array.length; i++) { if ($.isPlainObject(array[i])) { for (var property in array[i]) { result[prefix + "[" + i + "]." + property] = array[i][property]; } } else { result[prefix + "[" + i + "]"] = array[i]; } } }
在广泛地寻找我的问题的解决方案之后,并且其他人被指出没有任何解释的可行解决方案,当您尝试在Kendo中使用Kendo MultiSelect时,我认为这可能对其他人了解问题是有用的网格,而不仅仅是说“看这个例子”。
tl; dr 在发布到服务器之前,请务必先序列化Kendo MultiSelect内部的数据(如果使用的是Kendo Grid)