2

I have the following controller with a view model as follows -

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Initiate(IFormCollection formCollection)
{
    var studentId = formCollection["studentid"].ToString();

    if (string.IsNullOrEmpty(studentId))
    {
        return NotFound(new { msg = "Unknown student" });
    }

    Student student = await _context.Students.Include(s=>s.Parents).FirstOrDefaultAsync(s=>s.Id==studentId).ConfigureAwait(false);

    var dashboard = User.FindFirstValue(ClaimTypes.Role).ToLower();

    if (formCollection["bill"].Count > 0)
    {
        //Calculate the total bills and present a payment confirmation page
        List<int> billIds = new List<int>();
        foreach (var id in formCollection["bill"])
        {
            billIds.Add(Convert.ToInt32(id));
        }

        if (billIds.Count > 0)
        {
            List<Fee> fees = await _context.Fees.Where(f => billIds.Contains(f.Id)).ToListAsync().ConfigureAwait(false);

            string CustomerEmail = null;
            string CustomerPhone = null;
            string CustomerFirstName = null;
            string CustomerLastName = null;

            if (student.Parents.Any())
            {
                var parent = student.Parents.FirstOrDefault();

                CustomerEmail = parent?.Email;
                CustomerPhone = parent?.PhoneNumber;
                CustomerFirstName = parent?.OtherNames;
                CustomerLastName = parent?.Surname;
            }
            string TrxnRef = RandomStringGenerator.UpperAlphaNumeric(5) + student.Id.Substring(0,8);

            BillsPayViewModel model = new BillsPayViewModel
            {
                StudentId=student.Id,
                StudentName=student.FullName,
                PaymentItems=fees,
                TransactionRef= TrxnRef,
                CustomerPhone = CustomerPhone ?? student.PhoneNumber,
                CustomerEmail = CustomerEmail ?? student.Email,
                CustomerFirstname = CustomerFirstName ?? student.OtherNames,
                CustomerLastname = CustomerLastName ?? student.Surname,
                CustomerFullname=$"{CustomerFirstName} {CustomerLastName}", 
                Currency = "NGN",
                AmountToPay=fees.Sum(a=>a.Amount),
                Callbackurl=$"/Payments/Status/{TrxnRef}"
            };

            TempData["PaymentDetails"] = model;
            return View("BillsPayConfirmation", model);
        }
    }
    else
    {
        TempData["msg"] = "<div class='alert alert-success'><i class='fa fa-check'></i> No outstanding bills found for student</div>";

        return RedirectToAction(dashboard, "dashboard");
    }
    return RedirectToAction();
}

I realize that the moment I add the part that adds the model to Temp Data

TempData["PaymentDetails"] = model;

I get the following

enter image description here

Is there a way to add the entire model to TempData so I do not need to repeat the process of generating the ViewModel on the next page?

Josh
  • 1,660
  • 5
  • 33
  • 55
  • Can you show the whole controller action pls? – Serge Mar 16 '21 at 16:57
  • @Sergey I have done that – Josh Mar 16 '21 at 17:00
  • You have a lot of unusual code. Maybe you will have to use a debuger to find the line that gives the exception. Error 500 it is just a common name for any kind of exceptions. – Serge Mar 16 '21 at 17:09
  • @Sergey but the error occurs only when I add that line of code. When I remove it, everything else works – Josh Mar 16 '21 at 17:19
  • did you try to comment TempData["PaymentDetails"] = model; but keep BillsPayViewModel model = new BillsPayViewModel .... – Serge Mar 16 '21 at 17:38
  • @Sergey Yes I did and it did not return error 500 – Josh Mar 16 '21 at 18:10

2 Answers2

1

After much struggle, I came across this SO question that gave me a clue to what the issue is and it turns out that the problem is that TempData in ASP.NET Core (probably from version 5, because I have not tried this in other versions) does not have the capability to contain an object.

I was trying to add an object to TempData and that was the source of the problem. And the solution is to first serialize the model before adding it to TempData and then deserialize it back to the object where I need to use it as follows

  TempData["PaymentDetails"] = JsonConvert.SerializeObject(model);

and at the point where I need it, deserialize it back as follows

BillsPayViewModel paymentDetails = JsonConvert.DeserializeObject<BillsPayViewModel>((string)TempData["PaymentDetails"]);

I guess this will save someone lots of time.

Josh
  • 1,660
  • 5
  • 33
  • 55
0

you have to fix your code:

 Student student = await _context.Students.Include(s=>s.Parents).FirstOrDefaultAsync(s=>s.Id==studentId).ConfigureAwait(false);
if (student==null) ....return error
....
.....

if (student.Parents!=null &&  student.Parents.Count() > 0)
{
.....
}

 BillsPayViewModel model = new BillsPayViewModel
            {
                StudentId=student.Id,
                StudentName=student.FullName,
                PaymentItems=fees,
                TransactionRef= TrxnRef,
                CustomerPhone = CustomerPhone ?? student.PhoneNumber,
                CustomerEmail = CustomerEmail ?? student.Email,
                CustomerFirstname = CustomerFirstName ?? student.OtherNames,
                CustomerLastname = CustomerLastName ?? student.Surname,
                Currency = "NGN",
                AmountToPay=fees.Sum(a=>a.Amount),
                Callbackurl=$"/Payments/Status/{TrxnRef}"
            };

          model.CustomerFullname=  model.CustomerFirstName==null || model.CustomerLastName==null?
     string.Empty: $"{model.CustomerFirstName} {model.CustomerLastName}";

}
 
Serge
  • 40,935
  • 4
  • 18
  • 45
  • I actually don't encounter any error generating the model. It is just that when I try adding it to TempData["PaymentDetails"] the error happens – Josh Mar 16 '21 at 18:12
  • Do you use this TemData inside of your view? – Serge Mar 16 '21 at 18:20
  • I removed the instance where I use it when I started encountering the error but it still happens. So, the error occurs regardless of whether I use TempData in my view or not – Josh Mar 17 '21 at 06:42