簡體   English   中英

.Net 6 - Razor 頁面 - HttpContext.Session 的問題

[英].Net 6 - Razor Pages - Problems with HttpContext.Session

我正在開發一個 .Net6 剃須刀頁面項目,我正在使用會話來存儲變量。 我有一個可以編輯 XML“文檔”(DespatchAdvise - 供您參考)的頁面,並且我將模型對象存儲在會話中,以便管理此文檔子列表上的 CRUD 操作。

這是我配置會話的 Startup.cs

 public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<CookiePolicyOptions>(options =>
        {
            // This lambda determines whether user consent for non-essential cookies is needed for a given request.
            options.CheckConsentNeeded = context => false;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });

        //*** Other settings omitted ***

        services.AddDistributedMemoryCache();
        services.AddSession(options =>
        {
            options.IdleTimeout = TimeSpan.FromMinutes(Configuration.GetValue<int>("SessionTimeoutInMinutes"));
            options.Cookie.HttpOnly = true;
            options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
            options.Cookie.IsEssential = true;
            options.Cookie.Name = "_aspnetCoreSession";
        });
        services.AddHttpContextAccessor();

        //*** Other settings omitted ***
    }

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment() || env.IsStaging())
        {
            app.UseDeveloperExceptionPage();
            RegisteredServicesPage(app); //create a custom page with every service registered
        }
        else
        {
            app.UseExceptionHandler("/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }

        app.UseHttpsRedirection();           
        app.UseStaticFiles();
        app.UseCookiePolicy();
        app.UseRouting();           
        app.UseAuthentication();            
        app.UseSession();             
        app.UseAuthorization();                       
        app.UseMvc();
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapRazorPages();
        });
    }

我有一個為會話創建擴展方法的類

public static class SessionUtils
{
    public static void SetObjectAsJson(this ISession session, string key, object value)
    {
        session.SetString(key, JsonConvert.SerializeObject(value));
        session.CommitAsync().Wait(); //added to see if something changed (no success)
    }

    public static T GetObjectFromJson<T>(this ISession session, string key)
    {
        session.LoadAsync().Wait();//added to see if something changed (no success)

        var value = session.GetString(key);
        return value == null ? default(T) : JsonConvert.DeserializeObject<T>(value, new JsonSerializerSettings() { ObjectCreationHandling = ObjectCreationHandling.Replace });            
    }
}

CommitAsync 和 LoadAsync 這兩種方法對我沒有多大幫助:(

現在這是我的問題...在我的頁面中,我可以編輯有關“IdentityDocumentReference”的數據,並將這些數據保存在會話中,但有時數據沒有保存。 這很奇怪,因為它不是確定性的(在我看來)。 有時會保存數據,有時不會。

注意:加載和保存方法使用 AJAX 處理。 通過 DataTables ajax 調用加載並使用普通 AJAX 調用保存

這是將對象列表返回到數據表的代碼以及保存在會話中的方法。

public JsonResult OnPostLoadDriversDA()
{
    Utils_CommonResponse resp = new Utils_CommonResponse();
    List<DespatchAdviceAdditionaDocumentReference> ListIdDocumentRefDriver = new List<DespatchAdviceAdditionaDocumentReference>();

    try
    {
        DespatchAdviceDettaglio = HttpContext.Session.GetObjectFromJson<DespatchAdviceDettaglio>("DespatchAdviceDettaglio");
        List<DocumentReferenceType> IdDriver = DespatchAdviceDettaglio.DespatchAdvice.Shipment.Consignment[0].CarrierParty.Person[0].IdentityDocumentReference;

        if (IdDriver.Count > 0 && String.IsNullOrEmpty(IdDriver.First().ID.Value))
        { 
            //Here I reset the list because I have an empty object to create the interface but for datatables must be an empty list
            IdDriver = new List<DocumentReferenceType>();       
            DespatchAdviceDettaglio.DespatchAdvice.Shipment.Consignment[0].CarrierParty.Person[0].IdentityDocumentReference = IdDriver;
            
            //Here the object IdentityDocumentReference has 0 items (IdDriver is a new List - the problem is on save method)
            HttpContext.Session.SetObjectAsJson("DespatchAdviceDettaglio", DespatchAdviceDettaglio);            
        }

        foreach (DocumentReferenceType drf in IdDriver)
        {
            ListIdDocumentRefDriver.Add(new DespatchAdviceAdditionaDocumentReference()
            {
                ID = drf.ID.Value,
                TipoDocumento = drf.DocumentType.Value
            });
        }

        return new JsonResult(new
        {
            DataTablesRequest.Draw,
            recordsFiltered = ListIdDocumentRefDriver.Count,
            data = ListIdDocumentRefDriver
        });
    }
    catch (Exception exc)
    {
        _logger.LogError($"{exc.Message} - {exc.StackTrace}");
        resp.Esito = false;
        resp.Messaggio = exc.Message;
        return new JsonResult(resp);
    }
}

在會話中保存數據的方法

    public JsonResult OnPostSaveDriveDA([FromBody] SaveDriver IncomingData)
{
    Utils_CommonResponse resp = new Utils_CommonResponse();
    try
    {
        DespatchAdviceDettaglio = HttpContext.Session.GetObjectFromJson<DespatchAdviceDettaglio>("DespatchAdviceDettaglio");
        if (IncomingData.IdDriver == -1)
        {     
            //Here, after loading "DespatchAdviceDettaglio" from session, SOMETIMES the list IdentityDocumentReference has 1 element (the empty one)                              
            DespatchAdviceDettaglio.DespatchAdvice.Shipment.Consignment[0].CarrierParty.Person[0].IdentityDocumentReference.Add(IncomingData.DocRefDriver);
            
        }
        else
        { //edit
            DespatchAdviceDettaglio.DespatchAdvice.Shipment.Consignment[0].CarrierParty.Person[0].IdentityDocumentReference[IncomingData.IdDriver] = IncomingData.DocRefDriver;
        }
        HttpContext.Session.SetObjectAsJson("DespatchAdviceDettaglio", DespatchAdviceDettaglio);

        resp.Esito = true;
        resp.Messaggio = "";
    }
    catch (Exception exc)
    {
        resp.Esito = false;
        resp.Messaggio = exc.Message;
    }
    return new JsonResult(resp);
}

正如我在上面的評論中所寫,看起來在 OnPostSaveDriveDA 中我從會話中獲得的對象是“舊對象”。 然后,將新驅動程序添加到列表中。 但是當我重新加載列表時,我會丟失所有項目,因為第一個顯然是空的,所以列表被重置。

這讓我大吃一驚,因為它不會每次都發生。 看起來有時會話在我的“SetObjectAsJson”之后不存儲數據。

有人有同樣的問題或知道如何解決它並告訴我為什么會發生這種情況嗎?

感謝所有可以幫助我的人。

嘗試檢查會話 ID,所有請求的哈希碼都相同

我終於找到了解決方案。

問題是由於異步 ajax squence 調用,根據順序,覆蓋我需要存儲的會話值。 如果一個調用與我需要的調用並行,它會寫入一個錯誤的值(因為我從/到會話獲取並設置整個對象 - 在這種情況下為 DespatchAdvice)。

一個解決方案可能是使用部分 JSON 片段,如此處所示並直接處理您需要的屬性而不是整個對象。 另一種解決方案可能是以這種方式將 ajax 設置為同步:

$.ajaxSetup({
    async: false
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM