我正在做一个.Net6 razor页面项目,我正在使用会话来存储变量.我有一个页面,可以编辑XML"文档"(DispatchAdvise-供您参考),并将模型对象存储在会话中,以便管理此文档子列表上的CRUD操作.

这是我的创业计划.配置会话的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 });            
    }
}

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

现在我的问题是...

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

下面是将对象列表返回到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);
}

正如我在上面的 comments 中所写的,在OnPostSaveDriveDA中,我从会话中获得的对象是"旧对象".然后,新驱动程序将添加到列表中.但当我重新加载列表时,我会丢失所有项目,因为第一个项目显然是空的,所以列表会重置.

这让我大吃一惊,因为它并不是每次都发生.

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

谢谢所有能帮助我的人.

推荐答案

我终于找到了解决办法.

这个问题是由于异步ajax squence调用导致的,根据顺序,这些调用会覆盖我需要存储的会话值.

解决方案可以使用部分JSON片段,如here所示,并直接处理所需的属性,而不是整个对象.另一种解决方案可能是通过以下方式将ajax设置为同步:

$.ajaxSetup({
    async: false
});

Csharp相关问答推荐

如何定义所有项目的解决方案版本?

为什么使用DXGI输出复制和Direct 3D时捕获的图像数据全为零?

向类注入一个工厂来创建一些资源是一个好的实践吗?

数组被内部函数租用时,如何将数组返回给ArrayPool?

为什么Blazor值在更改后没有立即呈现?

如何注册实现同一接口的多个服务并注入到控制器构造函数中

如何将Kafka消息时间戳转换为C#中的日期和时间格式?

使用Audit.EntityFramework,我如何将外键的值设置为相关实体上的属性?

C#EF Core 8.0表现与预期不符

Appsettings.json未加载.Net 8 Blaazor Web程序集

在调整大小的控件上绘制

从依赖项容器在.NET 8中的Program.cs文件中添加IOC

取决于您的数据量的多个嵌套循环

在C#中反序列化/序列化具有混合元素顺序的XML时出现问题

有没有类似于扩展元素的合并元组的语法?

如何从另一个类的列表中按ID取值

当try 测试具有协变返回类型的抽象属性时,类似功能引发System.ArgumentException

Xamarin Forms应用程序中登录页面的用户名和密码编辑文本之间不需要的空格

使用postman 测试配置了身份的.NET 6应用程序

实体框架允许您具有筛选的属性吗?