1.1. Ignite Grid展示数据
Ignite UI提供了基于HTML5与CSS3的控件,需要添加程序集引用Infragistics.Web.Mvc,相应的CSS与JS,该框架需要JQuery UI、Bootstrap和modernizr。
1.1.1. 修改BundleConfig
Ignite所需的css与js引用,统一放在BundleConfig中配置。
//jquery-ui bundles.Add(new ScriptBundle("~/bundles/jqueryui").Include( "~/Scripts/jquery-ui-{version}.js" )); //<!-- Ignite UI Required Combined CSS Files --> bundles.Add(new StyleBundle("~/IgniteUI/css").Include( "~/igniteui/css/themes/infragistics/infragistics.theme.css", "~/igniteui/css/structure/infragistics.css" )); //<!-- Ignite UI Required Combined JavaScript Files --> bundles.Add(new ScriptBundle("~/IgniteUI/js").Include( "~/igniteui/js/infragistics.core.js", "~/igniteui/js/infragistics.dv.js", "~/igniteui/js/infragistics.loader.js", "~/igniteui/js/infragistics.lob.js" )); |
1.1.2. 修改cshtml
为提高效率,应先加载css,后加载js,所以js添加到文件底部。
@Styles.Render("~/IgniteUI/css") 省略页面代码… @Scripts.Render("~/bundles/jqueryui") @Scripts.Render("~/IgniteUI/js") |
1.1.3. Action添加特性
Action添加特性GridDataSourceAction,返回类型为IQueryable,
[GridDataSourceAction] public async Task<ActionResult> Create(string roleId) { if (string.IsNullOrWhiteSpace(roleId)) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } var roles = _roleManager.Roles.ToList(); ViewBag.RoleID = new SelectList(roles, "ID", "Description", roleId); //取角色权限ID var rolePermissions = await _roleManager.GetRolePermissionsAsync(roleId); //取全部权限与角色权限的差集 var allPermission = _db.Permissions.ToList(); var permissions = allPermission.Except(rolePermissions); //创建ViewModel var permissionViews = new List<PermissionViewModel>(); var map = Mapper.CreateMap<ApplicationPermission, PermissionViewModel>(); permissions.Each(t => { var view = Mapper.Map<PermissionViewModel>(t); permissionViews.Add(view); }); //排序 permissionViews.Sort(new PermissionViewModelComparer()); return View(permissionViews.AsQueryable()); } |
1.1.4. 修改视图
Ignite UI提供两种方式JS与HTML Helper,model需要声明为IQueryable,示例代码为后者。
@using Infragistics.Web.Mvc @Styles.Render("~/IgniteUI/css") @model IQueryable<AspNetIdentity2Permission.Mvc.Models.PermissionViewModel> <div class="form-group"> <div class="col-md-10"> @(Html.Infragistics() .Grid(Model) .ID("Grid") .Height("500px") .Width("100%") .AutoGenerateColumns(false) .AutoGenerateLayouts(false) .RenderCheckboxes(true) .PrimaryKey("Id") .Columns(column => { column.For(x => x.Id).Hidden(true); column.For(x => x.Action).HeaderText("Action名称"); column.For(x => x.Controller).HeaderText("Controller名称"); column.For(x => x.Description).HeaderText("功能说明"); }) .Features(feature => { feature.Selection().Mode(SelectionMode.Row).MultipleSelection(true); feature.RowSelectors().EnableRowNumbering(true).EnableCheckBoxes(true); feature.Sorting(); feature.Paging().PageSize(10) .FirstPageLabelText("第一页") .LastPageLabelText("最后一页") .NextPageLabelText("下一页") .PageSizeDropDownLabel("每页记录数") .PrevPageLabelText("前一页"); }) //.DataSourceUrl(Url.Action("GetPermissions")) .DataBind() .Render() ) </div> </div> |
1.1.5. 运行效果
1.2. JQuery与Action交互
取IgGrid选中的数据项,封装后用Post发送给Action。
1.2.1. JQuery操作数据
JQuery使用$("#Grid")取Id名为Grid的DOM,$("#RoleID").val()取Id值为RoleID的DOM元素值,$.post(url, data, callback)发起Ajax请求提交数据,callback方法处理回调数据。
<script> function getRowsInfo() { var selectedRows = $("#Grid").igGridSelection("selectedRows"), data = [], cellVal; if (selectedRows.length == 0) { alert("请选择记录"); return false; } //取roleID var roleId = $("#RoleID").val(); //取token var token = $("input[name=‘__RequestVerificationToken‘]").val(); //取列数据 gridColumns = $("#Grid").igGrid("option", "columns"); for (j = 0; j < selectedRows.length; j++) { var row = selectedRows[j]; var rowData = {}; //取单元格 for (i = 0; i < gridColumns.length; i++) { cellVal = $("#Grid").igGrid("getCellValue", row.id, gridColumns[i].key); rowData[gridColumns[i].key] = cellVal; } data[j] = rowData; } //提交服务端保存 $.post("/RolePermissions/Create", { "__RequestVerificationToken": token, "roleId": roleId, "data": data }, function (result) { if (result.Success) { //跳转到Index window.location = "/RolePermissions/Index?roleId=" + roleId; } else { //刷新当前 location.reload(); } }); } </script> |
1.2.2. Action处理
MVC将对Post数据自动完成模型绑定。
[HttpPost] [ValidateAntiForgeryToken] public async Task<ActionResult> Create(string roleId, IEnumerable<PermissionViewModel> data) |
Action采用JsonResult返回JSON格式数据给客户端,代码见/RolePermissions/Create。
//方法1,用JsonResult类封装,格式为Json,客户端直接使用 var response = new Dictionary<string, bool>(); response.Add("Success", true); return new JsonResult { Data = response }; |
也可返回Json字符串,由客户端自行解析处理,代码见/PermissionsAdmin/Create。
//方法2,使用Newtonsoft.Json序列化结果对象 //格式为json字符串,客户端需要解析,即反序列化 var result = JsonConvert.SerializeObject(new { Success = true }); return new JsonResult { Data = result }; |
1.2.3. Client解析JSON
此时Client拿到的已经是JSON数据,直接使用即可。
function (result) { if (result.Success) { //跳转到Index window.location = "/RolePermissions/Index?roleId=" + roleId; } else { //刷新当前 location.reload(); } } |
如果Action的返回格式为Json字符串,需要转换为JSON对象。
function (jsonStr) { //数据为Json字符串,需要解析 var result = eval("(" + jsonStr + ")"); if (result.Success) { //跳转到Index window.location = "/PermissionsAdmin/Index"; } else { //刷新当前 location.reload(); } } |
1.3. 跨站点攻击
ASP.NET MVC通过验证表单填写前后的Token来实现防御,在View中添加@Html.AntiForgeryToken()会生成名为__RequestVerificationToken的隐藏Input元素,服务端使用特性ValidateAntiForgeryToken验证该Token即可,通常该Token会随表单提交无需其它处理。
View
@Html.AntiForgeryToken(); |
Action
[Description("新建角色,提交")] [HttpPost] [ValidateAntiForgeryToken] public async Task<ActionResult> Create(RoleViewModel roleViewModel) |
也可用JS自行处理。
JS取Token
//取token var token = $("input[name=‘__RequestVerificationToken‘]").val(); |
JQuery发送Token
//提交服务端保存 $.post("/RolePermissions/Create", { "__RequestVerificationToken": token, "roleId": roleId, "data": data }, |