日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

你注意到 .Net Framework 和 .Net Core 中使用 Session 的区别了吗?

發布時間:2023/12/4 asp.net 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 你注意到 .Net Framework 和 .Net Core 中使用 Session 的区别了吗? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在測試一個例子時發現的問題,這個示例實現的功能是刷新頁面也能保持表格鎖定列的狀態,先看下頁面的完成效果:

測試中發現,幾乎相同的代碼:

  • 在 FineUIMvc(Net Framework)下沒有問題:http://mvc.fineui.com/#/GridLockColumn/SaveToDB

  • 但是在 FineUICore(Net 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)
{
// 模擬操作數據庫中的數據
List<string> 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 List<string> GetLockedColumns()
{
if (Session[KEY_FOR_DATASOURCE_SESSION] == null)
{
Session[KEY_FOR_DATASOURCE_SESSION]
= new List<string>() { };
}
return (List<string>)Session[KEY_FOR_DATASOURCE_SESSION];
}

當然,上面對 Session 的操作是在 FineUIMvc(ASP.NET MVC) 中的代碼,也就是運行在 .Net? Framework 下的代碼。

FineUICore(ASP.NET Core)中的代碼稍微不同,如下所示:

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Grid1_ColumnLockUnlock(string type, string columnId)
{
// 模擬操作數據庫中的數據
List<string> 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 List<string> GetLockedColumns()
{
if (HttpContext.Session.GetObject<List<string>>(KEY_FOR_DATASOURCE_SESSION) == null)
{
HttpContext.Session.SetObject(KEY_FOR_DATASOURCE_SESSION,
new List<string>() { });
}
return HttpContext.Session.GetObject<List<string>>(KEY_FOR_DATASOURCE_SESSION);
}

上面是保存狀態的邏輯,而刷新頁面后,會從Session中讀取保存的列鎖定狀態:

// GET: GridLockColumn/SaveToDB
public ActionResult Index()
{
LoadData();

return View();
}

private void LoadData()
{
ViewBag.LockedColumns
= GetLockedColumns();
}

然后,在頁面視圖中,將保存的列鎖定狀態設置到表格上,如下所示:

@{
Grid grid1
= F.GetControl<Grid>("Grid1");

List
<string> lockedColumns = ViewBag.LockedColumns as List<string>;
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 中檢查卻不存在!

后來才發現,我們過于相信引用類型了,請看如下代碼:

// 模擬操作數據庫中的數據
List<string> 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.GetObject<List<string>>(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擴展
/// </summary>
public static class SessionExtension
{
/// <summary>
/// 設置Session對象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="session"></param>
/// <param name="key"></param>
/// <param name="obj"></param>
public static void SetObject<T>(this ISession session, string key, T obj)
{
session.SetString(key, JsonConvert.SerializeObject(obj));
}

/// <summary>
/// 獲取Session對象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="session"></param>
/// <param name="key"></param>
/// <returns></returns>
public static T GetObject<T>(this ISession session, string key)
{
T result
= default(T);
var value = session.GetString(key);
if(!String.IsNullOrEmpty(value))
{
result
= JsonConvert.DeserializeObject<T>(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 里面定義的擴展方法提供的:

知道了根本原因,再去修正 FineUICore(ASP.NET Core)下的這個問題就簡單多了。

在控制器方法中,修改完?lockedColumns 對象后,需要顯式的保存到 Session 中,如下所示:

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Grid1_ColumnLockUnlock(string type, string columnId)
{
// 模擬操作數據庫中的數據
List<string> 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


總結

以上是生活随笔為你收集整理的你注意到 .Net Framework 和 .Net Core 中使用 Session 的区别了吗?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。