Home > Software design >  Passing a List<> as a RouteValue in RedirectToAction() in Asp.Net Core
Passing a List<> as a RouteValue in RedirectToAction() in Asp.Net Core

Time:10-01

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.List1[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:

enter image description here

UrL: enter image description here

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,

enter image description here

  • Related