网站推广策划评估工具7,wordpress菜单新连接,下载网站所有网页,wordpress4.9.4 使用教程在测试一个例子时发现的问题#xff0c;这个示例实现的功能是刷新页面也能保持表格锁定列的状态#xff0c;先看下页面的完成效果#xff1a;测试中发现#xff0c;几乎相同的代码#xff1a;在 FineUIMvc#xff08;Net Framework#xff09;下没有问题#xff1a;htt… 在测试一个例子时发现的问题这个示例实现的功能是刷新页面也能保持表格锁定列的状态先看下页面的完成效果测试中发现几乎相同的代码在 FineUIMvcNet Framework下没有问题http://mvc.fineui.com/#/GridLockColumn/SaveToDB但是在 FineUICoreNet Core下就失效了刷新页面后锁定列状态丢失http://core.fineui.com/#/GridLockColumn/SaveToDB这个例子使用了 Session 来保存表格的锁定状态先来看下页面视图的定义(F.Grid().IsFluid(true).CssClass(blockpanel).Title(表格).ShowHeader(true).ShowBorder(true).ID(Grid1).DataIDField(Id).DataTextField(Name).AllowColumnLocking(true) .Columns( F.RowNumberField(), F.RenderField().HeaderText(姓名).DataField(Name).Width(100).EnableLock(true).Locked(true), F.RenderField().HeaderText(性别).DataField(Gender).FieldType(FieldType.Int).RendererFunction(renderGender).Width(80).EnableLock(true), F.RenderField().HeaderText(入学年份).DataField(EntranceYear).FieldType(FieldType.Int).Width(100).EnableLock(true), F.RenderCheckField().HeaderText(是否在校).DataField(AtSchool).RenderAsStaticField(true).Width(100).EnableLock(true), F.RenderField().HeaderText(所学专业).DataField(Major).RendererFunction(renderMajor).Width(300).EnableLock(true), F.RenderField().HeaderText(分组).DataField(Group).RendererFunction(renderGroup).Width(80).EnableLock(true), F.RenderField().HeaderText(注册日期).DataField(LogTime).FieldType(FieldType.Date).Renderer(Renderer.Date).RendererArgument(yyyy-MM-dd).Width(100).EnableLock(true) ).Listener(columnlock, onGridColumnLock).Listener(columnunlock, onGridColumnUnlock) .DataSource(DataSourceUtil.GetDataTable()))在客户端事件 columnlock 和 columnunlock 中会将锁定列的状态改变回发到后台function onGridColumnLock(event, columnId) {// 触发后台事件 F.doPostBack(Url.Action(Grid1_ColumnLockUnlock), { type: lock, columnId: columnId });}function onGridColumnUnlock(event, columnId) {// 触发后台事件 F.doPostBack(Url.Action(Grid1_ColumnLockUnlock), { type: unlock, columnId: columnId });}后台会将列状态信息保存到 Session 中实际项目中是要保存到数据库中的[HttpPost][ValidateAntiForgeryToken]public ActionResult Grid1_ColumnLockUnlock(string type, string columnId){// 模拟操作数据库中的数据 Liststring lockedColumns GetLockedColumns();if (type lock) {if (!lockedColumns.Contains(columnId)) { lockedColumns.Add(columnId); } }else if (type unlock) {if (lockedColumns.Contains(columnId)) { lockedColumns.Remove(columnId); } }return UIHelper.Result();}private static readonly string KEY_FOR_DATASOURCE_SESSION GridLockColumn.SaveToDB;// 模拟在服务器端保存数据// 特别注意在真实的开发环境中不要在Session放置大量数据否则会严重影响服务器性能private Liststring GetLockedColumns(){if (Session[KEY_FOR_DATASOURCE_SESSION] null) { Session[KEY_FOR_DATASOURCE_SESSION] new Liststring() { }; }return (Liststring)Session[KEY_FOR_DATASOURCE_SESSION];}当然上面对 Session 的操作是在 FineUIMvcASP.NET MVC 中的代码也就是运行在 .Net Framework 下的代码。FineUICoreASP.NET Core中的代码稍微不同如下所示[HttpPost][ValidateAntiForgeryToken]public IActionResult Grid1_ColumnLockUnlock(string type, string columnId){// 模拟操作数据库中的数据 Liststring lockedColumns GetLockedColumns();if (type lock) {if (!lockedColumns.Contains(columnId)) { lockedColumns.Add(columnId); } }else if (type unlock) {if (lockedColumns.Contains(columnId)) { lockedColumns.Remove(columnId); } }return UIHelper.Result();}private static readonly string KEY_FOR_DATASOURCE_SESSION GridLockColumn.SaveToDB;// 模拟在服务器端保存数据// 特别注意在真实的开发环境中不要在Session放置大量数据否则会严重影响服务器性能private Liststring GetLockedColumns(){if (HttpContext.Session.GetObjectListstring(KEY_FOR_DATASOURCE_SESSION) null) { HttpContext.Session.SetObject(KEY_FOR_DATASOURCE_SESSION, new Liststring() { }); }return HttpContext.Session.GetObjectListstring(KEY_FOR_DATASOURCE_SESSION);}上面是保存状态的逻辑而刷新页面后会从Session中读取保存的列锁定状态// GET: GridLockColumn/SaveToDBpublic ActionResult Index(){ LoadData();return View();}private void LoadData(){ ViewBag.LockedColumns GetLockedColumns();}然后在页面视图中将保存的列锁定状态设置到表格上如下所示{ Grid grid1 F.GetControlGrid(Grid1); Liststring lockedColumns ViewBag.LockedColumns as Liststring;if (lockedColumns.Count 0) {foreach (GridColumn column in grid1.Columns) { RenderBaseField field column as RenderBaseField;if (field null) {continue; }if (lockedColumns.Contains(field.ColumnID) || lockedColumns.Contains(field.DataField)) { field.Locked true; } } }}至此整个流程全部完成。问题是几乎一模一样的代码为什么在 .Net Framework 下一切正常而 .Net Core 下却出问题了经过代码调试我们发现在 .Net Core 下将状态保存到 Session 中后再去 Session 中检查却不存在后来才发现我们过于相信引用类型了请看如下代码// 模拟操作数据库中的数据Liststring lockedColumns GetLockedColumns();if (type lock){if (!lockedColumns.Contains(columnId)) { lockedColumns.Add(columnId); }}else if (type unlock){if (lockedColumns.Contains(columnId)) { lockedColumns.Remove(columnId); }}有过面向对象编程经验的同学都知道lockedColumns实际上是Session中的一个对象引用因此下面对此对象的 Add 和 Remove 操作会直接改变 Session 中的对象。为什么 .Net Core 下这个逻辑就失效了我第一个想到的是深拷贝莫非下面的代码返回了一个 Session 对象的深拷贝HttpContext.Session.GetObjectListstring(KEY_FOR_DATASOURCE_SESSION)转到 GetObject 方法的定义我却发现自己的忘性有多大却原来 GetObject 是自己很久之前定义的一个扩展方法.Net Core本身并没有定义这个方法我们来看一眼using Microsoft.AspNetCore.Http;using Newtonsoft.Json;using System;using System.Collections.Generic;using System.Text;namespace FineUICore{/// summary/// Session扩展/// /summarypublic static class SessionExtension {/// summary/// 设置Session对象/// /summary/// typeparam nameT/typeparam/// param namesession/param/// param namekey/param/// param nameobj/parampublic static void SetObjectT(this ISession session, string key, T obj) { session.SetString(key, JsonConvert.SerializeObject(obj)); }/// summary/// 获取Session对象/// /summary/// typeparam nameT/typeparam/// param namesession/param/// param namekey/param/// returns/returnspublic static T GetObjectT(this ISession session, string key) { T result default(T);var value session.GetString(key);if(!String.IsNullOrEmpty(value)) { result JsonConvert.DeserializeObjectT(value); }return result; } }}为什么 Session 中保存个对象还要通过JSON字符串中转原来 .Net Core 中原生只提供了在 Session 中保存字符串和 byte 数组的支持想要保存复杂类型只能自己写扩展方法了。而这个扩展方法 GetObject 返回的Session对象的确像是一个深度拷贝的对象因此对于它的 Add 和 Remove 并不会影响 Session 中实际存储的 JSON字符串。至此问题已经很明朗了我们再来复习下 ASP.NET Core 中使用 Session 的步骤1. 首先在 Startup.cs 中添加 Session 服务public void ConfigureServices(IServiceCollection services){ services.AddDistributedMemoryCache(); services.AddSession();// FineUI 和 MVC 服务 services.AddFineUI(Configuration); services.AddMvc(options {// 自定义模型绑定Newtonsoft.Json options.ModelBinderProviders.Insert(0, new JsonModelBinderProvider()); });}public void Configure(IApplicationBuilder app, IHostingEnvironment env){ app.UseStaticFiles(); app.UseSession();// FineUI 和 MVC 中间件确保 UseFineUI 位于 UseMvc 的前面 app.UseFineUI(); app.UseMvc();}2. 控制器中使用 HttpContext.Session.SetString 来保存字符串HttpContext.Session.SetString(StartedTime, Started time: DateTime.Now.ToString());var startedTime HttpContext.Session.GetString(StartedTime);如果我们看下 SetString 的定义会知道甚至这个方法也是通过 Microsoft.AspNetCore.Http 里面定义的扩展方法提供的知道了根本原因再去修正 FineUICoreASP.NET Core下的这个问题就简单多了。在控制器方法中修改完 lockedColumns 对象后需要显式的保存到 Session 中如下所示[HttpPost][ValidateAntiForgeryToken]public IActionResult Grid1_ColumnLockUnlock(string type, string columnId){// 模拟操作数据库中的数据 Liststring lockedColumns GetLockedColumns();if (type lock) {if (!lockedColumns.Contains(columnId)) { lockedColumns.Add(columnId); } }else if (type unlock) {if (lockedColumns.Contains(columnId)) { lockedColumns.Remove(columnId); } } HttpContext.Session.SetObject(KEY_FOR_DATASOURCE_SESSION, lockedColumns);return UIHelper.Result();}原文地址https://www.cnblogs.com/sanshi/p/10550977.html.NET社区新闻深度好文欢迎访问公众号文章汇总 http://www.csharpkit.com