.NET 6-剃刀页 - httpcontext的问题。

发布于 2025-02-05 08:50:08 字数 6620 浏览 4 评论 0原文

我正在从事一个.NET6 Razor页面项目,并且正在使用用于存储变量的usign Session。我有一个可以编辑XML“文档”(用于您的信息)的页面,并且我将模型对象存储在会话中,以便在本文档的订阅者上管理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 });            
    }
}

commansync和loadAsync的两个方法对我有很大帮助:(

现在这是我的问题... 在我的页面中,我可以编辑有关“ IdentityDocumentReference”的数据,并且可以在会话中保存这些数据,但是有时无法保存数据。这很奇怪,因为我认为不是确定性的(我认为)。有时可以保存数据,有时不能保存。

注意:使用AJAX处理加载和保存方法。通过DataTables Ajax调用加载,并使用普通的AJAX调用保存

这是将对象列表返回到DataTables的代码以及保存在会话中的方法。

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);
}

,看起来我从会话中获得的对象是“旧的”。然后,将新驱动程序添加到列表中。但是当我重新加载列表时,我会丢失所有项目,因为第一个显然是空的,因此列表已重置。

这让我震惊,因为它并非每次都会发生。 看来有时会话不会在我的“ setObjectAsjson”之后存储数据。

有人有同样的问题还是知道如何解决问题并告诉我为什么会发生这种情况?

感谢所有可以帮助我的人。

I'm working on a .Net6 razor pages project and I'm usign session to store variables. I have a page which can edit an XML "document" (a DespatchAdvise - for your info) and I store the model object in session, in order to manage CRUD operations on sublists of this document.

Here's my Startup.cs where I configure session

 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();
        });
    }

I have a class that creates extensions methods for session

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 });            
    }
}

The two methods CommitAsync and LoadAsync doesn't helped me a lot :(

Now here's my problem...
In my page I can edit data about "IdentityDocumentReference", and I save these data in session, but sometimes data is not saved. It is very strange because is not deterministic (in my opinion). Sometimes data is saved, sometimes not.

Note: Load and Save methods are handled using AJAX. Load by DataTables ajax call and Save with a normal AJAX call

Here's the code that returns the object list to datatables and the method that saves in session.

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(
quot;{exc.Message} - {exc.StackTrace}");
        resp.Esito = false;
        resp.Messaggio = exc.Message;
        return new JsonResult(resp);
    }
}

Method that save data in session

    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);
}

As I wrote in the comment above, looks like in OnPostSaveDriveDA the object I get from session is the "old one". Then, the new driver is added to the list. But when I reload the list, I lose every items because the first is obviously the empty one so the list is reset.

This is blowing my mind because it doesn't happens every time.
It looks like sometimes session doesn't store data after my "SetObjectAsJson".

Did someone have the same problem or knows how to solve it and tell me why this happens?

Thanks to everyone who can help me.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

留一抹残留的笑 2025-02-12 08:50:09

尝试检查会话ID,所有请求的哈希代码均相同

Try to check the session Id and the hash code is the same for all requests

暮年 2025-02-12 08:50:09

我终于找到了解决方案。

问题是由于异步Ajax squence调用,根据顺序,我需要存储的会话值。
如果呼叫与我需要的呼叫并行,则写入错误的值(因为我从/到会话将整个对象设置为 - 在这种情况下为DespatchAdvice)。

可以看到的解决方案可以使用部分JSON片段在这里并直接在所需的属性上工作,而不是整个对象。另一个解决方案可能是以这种方式将AJAX设置为同步:

$.ajaxSetup({
    async: false
});

I finally found the solution.

The problem was due to async ajax squence calls that, depending on the order, overwrite the session value I need to store.
If a call comes in parallel with the one I need, it write a wrong value (because I get and set the entire object from/to session - DespatchAdvice in this case).

A solution could be working with Partial JSON fragments as can be seen here and working directly on the property you need instead of the whole object. Another solution may be to set ajax as synchronous in this way:

$.ajaxSetup({
    async: false
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文