Home > Net >  How to call a list of objects from a session?
How to call a list of objects from a session?

Time:01-09

I am creating an invoice like this: For signed in users, I save the invoices and the invoice units to database (one invoice has many invoice units) and for users that are not signed in, I am trying to save the data into sessions

    [HttpPost]
    public ActionResult Create(Invoice invoice)
    {
        var userId = User.Claims.FirstOrDefault(c => c.Type == "UserId")?.Value;
        if (userId is not null)
        {
            invoice.UserId = Guid.Parse(userId.ToString());
            DateTime dateTime = DateTime.Now;
            invoice.DateCreated = dateTime;
            foreach (var invoiceUnit in invoice.InvoiceUnits)
            {
                db.InvoiceUnits.Add(invoiceUnit);
            }
            db.Add(invoice);
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        else
        {
            invoice.Id = Guid.NewGuid();
            var invoicesFromSession = GetInvoicesFromSession();
            var invoiceUnitsFromSession = GetInvoiceUnitsFromSession();

            DateTime dateTime = DateTime.Now;
            invoice.DateCreated = dateTime;

            if (invoice is not null)
            {
                invoicesFromSession.Add(invoice);

                HttpContext.Session.SetString("invoice", JsonSerializer.Serialize(invoicesFromSession));

                foreach(var invoiceUnit in invoice.InvoiceUnits)
                {
                    invoiceUnit.Id = new Guid();
                    invoiceUnit.InvoiceId = invoice.Id;
                    HttpContext.Session.SetString("invoiceUnit", JsonSerializer.Serialize(invoiceUnitsFromSession));
                    invoiceUnitsFromSession.Add(invoiceUnit);
                }

            }

            return RedirectToAction("Index");
        }

    }

I am getting the invoice units from session like this:

    private List<InvoiceUnit> GetInvoiceUnitsFromSession()
    {
        HttpContext.Session.LoadAsync();
        var sessionString = HttpContext.Session.GetString("invoiceUnit");
        if (sessionString is not null)
        {
            return JsonSerializer.Deserialize<List<InvoiceUnit>>(sessionString);
        }

        return Enumerable.Empty<InvoiceUnit>().ToList();
    }

And then I am trying to call the function in the Edit controller

            var sessionInvoices = GetInvoicesFromSession();
            var sessionInvoiceUnits = GetInvoiceUnitsFromSession();
            var invoiceFromDbSession = sessionInvoices.FirstOrDefault(i => i.Id == id);
            List<InvoiceUnit> invoiceUnitsForInvoiceSession = new List<InvoiceUnit>();

            foreach (var invoiceUnit in sessionInvoiceUnits)
            {
                if (invoiceUnit.InvoiceId == id)
                {
                    invoiceUnitsForInvoiceSession.Add(invoiceUnit);
                }
            }
            GenericModel sessionData = new GenericModel(invoiceUnitsForInvoiceSession, invoiceFromDbSession);
            return View(sessionData);

From some reason tho, when I call the GetInvoiceUnitsFromSession(); in the Edit controller to retrieve the wanted invoice unit for the specific invoice, I only receive one invoice unit for each invoice (the first one I have entered). When I debug the invoiceUnitsFromSession variable in the create function, the number of units fits just fine for the specific invoice so I think there must be some problem in the way I am trying to retreive the session. Any idea what changes to make in order to retreive all of the invoice units I recieve for all invoices so I can get them in Edit controller?

CodePudding user response:

call a list of objects from a session

Do you want the below way?

Configure your SessionExtension like below:

public static class SessionExtensions
{
    public static void Set<T>(this ISession session, string key, T value)
    {
        session.SetString(key, JsonSerializer.Serialize(value));
    }

    public static T? Get<T>(this ISession session, string key)
    {
        var value = session.GetString(key);
        return value == null ? default : JsonSerializer.Deserialize<T>(value);
    }
}

Then use methods like below:

////  your list object
List<MyClass> classCollection = new List<MyClass>();

//// To set value in session
HttpContext.Session.Set<List<MyClass>>("someKey", classCollection);

//// To Get Value from Session
List<MyClass> classCollection = HttpContext.Session.Get<List<MyClass>>("someKey");

Read Set and get Session values to know more.

CodePudding user response:

The issue you see comes from this block:

                foreach(var invoiceUnit in invoice.InvoiceUnits)
                {
                    invoiceUnit.Id = new Guid();
                    invoiceUnit.InvoiceId = invoice.Id;
                    HttpContext.Session.SetString("invoiceUnit", JsonSerializer.Serialize(invoiceUnitsFromSession)); // Specifically this line
                    invoiceUnitsFromSession.Add(invoiceUnit);
                }

Here you're writing the value for the key invoiceUnit on each repetition of the loop before you actually update the value, so at least the last line will always be missing. You would want to either change the order:

                foreach(var invoiceUnit in invoice.InvoiceUnits)
                {
                    invoiceUnit.Id = new Guid();
                    invoiceUnit.InvoiceId = invoice.Id;
                    invoiceUnitsFromSession.Add(invoiceUnit);
                    HttpContext.Session.SetString(
                       "invoiceUnit", 
                       JsonSerializer.Serialize(invoiceUnitsFromSession));
                }

or move the line that stores invoice units into the session out of the loop completely to avoid unnecessary repetition:

                foreach(var invoiceUnit in invoice.InvoiceUnits)
                {
                    invoiceUnit.Id = new Guid();
                    invoiceUnit.InvoiceId = invoice.Id;
                    invoiceUnitsFromSession.Add(invoiceUnit);
                }
                HttpContext.Session.SetString(
                   "invoiceUnit", 
                   JsonSerializer.Serialize(invoiceUnitsFromSession));
  • Related