I need to pass a List based on a Model from one Controller Method to another. MailList
is used to extract and filter data from a Model (Family), the other CreateMailingList
saves the outcome to another Model (Contributie).
The Model FilterListVM
is a ViewModel that includes the List<Familie>
. When Redirecting the List is empty, where it should contain three records.
As an alternative, I have tried to use TempData
to send the List, but than I got the Errormessage: InvalidOperationException: The 'Microsoft.AspNetCore.Mvc.ViewFeatures.Infrastructure.DefaultTempDataSerializer' cannot serialize an object of type 'System.Collections.Generic.List
1[DrieHamersV4.Models.Familie]'.
The -simplified- controllerMethod looks as follows:
public async Task<IActionResult> MailingList(FilterListVM contributieLijst)
{
(...) // several variables that filter the data
(...)
string flexDefault = contributieLijst.FlexDefault;
int? contributieJaar = contributieLijst.ContributieJaar;
bool save = contributieLijst.Save;
string message = contributieLijst.Message;
var fList = contributieLijst.Ffamilie;
//************** Getting the Data and Filters for Standard Lists
switch (flexDefault)
{
case "contributie":
fList = await _context.Familie
.OrderBy(f => f.Roepnaam).ToListAsync();
break;
case (...)
break;
default:
fList = contributieLijst.Ffamilie; //previous selection
break;
}
}
contributieLijst.Ffamilie = fList; //fList contains 3 records
//******* Redirects to the next Method
if (save == true)
{
TempData["mailList"] = fList.ToList(); //gives an ErrorMEssage
return RedirectToAction("CreateMailingList", contributieLijst);
}
return View(contributieLijst);
}
public async Task<IActionResult> CreateMailingList(FilterListVM contributielijst)
{
var contributieJaar = contributielijst.ContributieJaar; // This works fine
//var mailingList = (List<Familie>)TempData["mailList"];
var mailingList = contributielijst.Ffamilie; //This is now empty
(...)
The ViewModel FilterListVM
public class FilterListVM
{
public bool? Fovl { get; set; }
public string Fstaak { get; set; }
public string Fgeslacht { get; set; }
public bool? Fbloedverwant { get; set; }
public string Fland { get; set; }
public bool? Femail { get; set; }
public bool? Ftelefoon { get; set; }
public int? FleeftijdVan { get; set; }
public int? FleeftijdTot { get; set; }
public bool? Fcorrespondentie { get; set; }
public string SortColumn { get; set; }
public string SortOrder { get; set; }
public string FlexDefault { get; set; }
public bool ExportToggle { get; set; }
public string SearchString { get; set; }
public string CurrentFilter { get; set; }
public bool Reset { get; set; } = false;
public int? ContributieJaar { get; set; }
public bool Save { get; set; } = false;
public string Message { get; set; }
public List<Familie> Ffamilie { get; set; }
}
}
CodePudding user response:
You can serialize the list to json string before adding to TempData:
using System.Text.Json;
...
TempData["mailList"] = JsonSerializer.Serialize(fList);
And then in your other action:
var mailList = JsonSerializer.Deserialize<List<Familie>>(TempData["mailList"].ToString());
CodePudding user response:
I tried as you mentioned and repeated your error in my case,
Models:
public class FilterListVM
{
public FilterListVM()
{
Ffamilie = new List<Familie>();
}
public string Message { get; set; }
public List<Familie> Ffamilie { get; set; }
}
public class Familie
{
public int Id { get; set; }
public string Description { get; set; }
}
in Controller:
public IActionResult SomeAction()
{
var familie1 = new Familie() { Id = 1, Description = "D1" };
var familie2 = new Familie() { Id = 2, Description = "D2" };
var familielist = new List<Familie>() { familie1, familie2, familie1 };
var vm = new FilterListVM() { Message = "hi" };
vm.Ffamilie = familielist;
return RedirectToAction("AnotherAction", routedic1);
}
public IActionResult AnotherAction(FilterListVM vm)
{
return Ok();
}
The Result:
Then I tried to create a new RouteValueDictionary and add the codes:
var routedic = new RouteValueDictionary();
Type vmtype = typeof(FilterListVM);
foreach (var property in vmtype.GetProperties())
{
routedic.Add(property.Name, vmtype.GetProperty(property.Name).GetValue(vm));
}
return RedirectToAction("AnotherAction", vm)
it performed same as before,so in my opinion,the designer may not consider passing complex model contains a list to route value for the length of url is limited;
Then I tried hard coding as below:
var routedic1 = new RouteValueDictionary(vm);
routedic1.Remove("Ffamilie");
for (int i = 0; i < vm.Ffamilie.Count; i )
{
var key1 = string.Format("Ffamilie[{0}].Id", i.ToString());
routedic1.Add(key1, vm.Ffamilie[i].Id);
var key2 = string.Format("Ffamilie[{0}].Description", i.ToString());
routedic1.Add(key2, vm.Ffamilie[i].Description);
}
return RedirectToAction("AnotherAction", routedic1);
This time it bind the model successfully,