Reputation: 33
I am trying to send an Object of type ResumeInfo(Custom Object) from a razor page to another razor page and it's working fine.....but I noticed that all child objects within that object are null, they are not supposed to be because they have values.
This is the Class that I made the object from, it has a List of other objects (Experience, Language, Skill) the lists are returning empty when I send the object from one Razor page to another, even though the Objects have values because I tested them before I sent the object to the another Page.
public class ResumeInfo
{
public string FullName { get; set; }
public string Profession { get; set; }
public List<string> Socials { get; set; }
public List<Skill> Skills { get; set; }
public List<Language> Languages { get; set; }
public List<Experience> Experiences { get; set; }
public string AboutMe { get; set; }
public List<Language> GetLanguages()
{
if (Languages == null)
Languages = new List<Language>();
return Languages;
}
public List<Skill> GetSkills()
{
if (Skills == null)
Skills = new List<Skill>();
return Skills;
}
public List<Experience> GetExperiences()
{
if (Experiences == null)
Experiences = new List<Experience>();
return Experiences;
}
}
This is how I am sending the object:
public class ResumeFormModel : PageModel
{
[BindProperty]
public ResumeInfo Info { get; set; }
public IActionResult OnPost()
{
int counter = 0;
var socials = Request.Form["Socials"];
var languagesName = Request.Form["LanguagesName"];
var languageValue = Request.Form["LanguagesValue"];
var skillsName = Request.Form["SkillsName"];
var skillsValue = Request.Form["SkillsValue"];
var expTitle = Request.Form["ExperienceTitle"];
var expText = Request.Form["ExperienceText"];
foreach(string str in socials)
{
Info.Socials.Add(str);
Console.WriteLine(str);
}
counter = 0;
foreach(string str in languagesName)
Info.GetLanguages().Add(new Language(str, Int32.Parse(languageValue[counter++])));
counter = 0;
foreach (string str in skillsName)
Info.GetSkills().Add(new Skill(str, Int32.Parse(skillsValue[counter++])));
counter = 0;
foreach (string str in expTitle)
{
Info.GetExperiences().Add(new Experience(str, expText[counter++]));
Console.WriteLine(str);
}
return RedirectToPage("GenerateResume", Info);
}
}
Please note that other properties from the Object(ResumeInfo) like (FullName, Profession, AboutMe) are working fine and they have values, it's jus the Lists and the Child Objects.
And this is how I am receiving the object.
public class GenerateResumeModel : PageModel
{
[BindProperty(SupportsGet = true)]
public ResumeInfo Info { get; set; }
public void OnGet()
{
//Console.WriteLine(Info.GetExperiences()[0].Name);
}
}
Why aren't the Child Objects being populated? is there any other way to send the object?
Upvotes: 0
Views: 649
Reputation: 21408
Check the PageBase.RedirectToPage Method, we can see that the Object is the route Values.
In the Asp.net Core Razor Page, we can't pass the complex objects as route data. The route data feature only supports simple objects like int
and string
. If you want to retain more complex objects across requests, you need to use Sessions
or TempData
(backed by session state).
So, you could refer the following steps to enable session and transfer complex objects between across requests.
Enable the session middleware in the Startup.cs: call AddSession
in ConfigureServices
, and call the UseSession
in Configure
.
public void ConfigureServices(IServiceCollection services)
{
services.AddDistributedMemoryCache();
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(10); //session expired time
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
});
services.AddRazorPages();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
app.UseAuthentication();
app.UseAuthorization();
app.UseSession();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
Add Session or TempData extension to store objects.
//required
//using Microsoft.AspNetCore.Http;
//using Newtonsoft.Json;
public static class SessionExtensions
{
public static void Set<T>(this ISession session, string key, T value)
{
session.SetString(key, JsonConvert.SerializeObject(value));
}
public static T Get<T>(this ISession session, string key)
{
var value = session.GetString(key);
return value == null ? default : JsonConvert.DeserializeObject<T>(value);
}
}
Or
//Required
//using Microsoft.AspNetCore.Mvc.ViewFeatures;
//using Newtonsoft.Json;
public static class TempDataExtensions
{
public static void Set<T>(this ITempDataDictionary tempData, string key, T value) where T : class
{
tempData[key] = JsonConvert.SerializeObject(value);
}
public static T Get<T>(this ITempDataDictionary tempData, string key) where T : class
{
object o;
tempData.TryGetValue(key, out o);
return o == null ? null : JsonConvert.DeserializeObject<T>((string)o);
}
}
Use session or TempData to store the complex objects:
ResumeForm Post method:
public IActionResult OnPost()
{
//set value for Info.
...
//store value in session
HttpContext.Session.Set<ResumeInfo>("Resume", Info);
// use TempData store the object
TempData.Set("Resume", Info);
return RedirectToPage("GenerateResume", Info);
}
Then, code in the GenerateResume page Get method:
public class GenerateResumeModel : PageModel
{
[BindProperty(SupportsGet = true)]
public ResumeInfo Info { get; set; }
public void OnGet()
{
var resume = HttpContext.Session.Get<ResumeInfo>("Resume");
var data = TempData.Get<ResumeInfo>("Resume");
//Console.WriteLine(Info.GetExperiences()[0].Name);
}
}
The test result like this:
Upvotes: 2