将对象(和子对象)从一个 Razor 页面发送到另一个
Sending objects(And Child Objects) from a Razor page to another
我正在尝试将 ResumeInfo(自定义对象)类型的对象从一个 razor 页面发送到另一个 razor 页面,它工作正常......但我注意到该对象中的所有子对象都是空的,它们不应该是因为他们有价值观。
这是我制作对象的 Class,它有一个其他对象列表(经验、语言、技能)当我将对象从一个 Razor 页面发送到另一个时,列表返回空,即使对象有值,因为我在将对象发送到另一个页面之前测试了它们。
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;
}
}
这是我发送对象的方式:
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);
}
}
请注意,对象 (ResumeInfo) 的其他属性(全名、专业、AboutMe)工作正常并且它们具有值,只是列表和子对象。
这就是我接收对象的方式。
public class GenerateResumeModel : PageModel
{
[BindProperty(SupportsGet = true)]
public ResumeInfo Info { get; set; }
public void OnGet()
{
//Console.WriteLine(Info.GetExperiences()[0].Name);
}
}
为什么不填充子对象?还有其他发送对象的方法吗?
查看PageBase.RedirectToPage Method,可以看到Object就是路由Values。
在 Asp.net 核心 Razor 页面中,我们无法将复杂对象作为路由数据传递。路由数据功能仅支持简单对象,如 int
和 string
。如果你想跨请求保留更复杂的对象,你需要使用Sessions
或TempData
(由会话状态支持)。
因此,您可以参考以下步骤来启用会话并在跨请求之间传输复杂对象。
在Startup.cs中启用会话中间件:在ConfigureServices
中调用AddSession
,在Configure
中调用UseSession
。
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();
});
}
添加 Session 或 TempData 扩展来存储对象。
//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);
}
}
或
//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);
}
}
使用session或TempData存储复杂对象:
ResumeForm Post 方法:
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);
}
然后,GenerateResume页面Get方法中的代码:
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);
}
}
测试结果是这样的:
我正在尝试将 ResumeInfo(自定义对象)类型的对象从一个 razor 页面发送到另一个 razor 页面,它工作正常......但我注意到该对象中的所有子对象都是空的,它们不应该是因为他们有价值观。
这是我制作对象的 Class,它有一个其他对象列表(经验、语言、技能)当我将对象从一个 Razor 页面发送到另一个时,列表返回空,即使对象有值,因为我在将对象发送到另一个页面之前测试了它们。
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;
}
}
这是我发送对象的方式:
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);
}
}
请注意,对象 (ResumeInfo) 的其他属性(全名、专业、AboutMe)工作正常并且它们具有值,只是列表和子对象。
这就是我接收对象的方式。
public class GenerateResumeModel : PageModel
{
[BindProperty(SupportsGet = true)]
public ResumeInfo Info { get; set; }
public void OnGet()
{
//Console.WriteLine(Info.GetExperiences()[0].Name);
}
}
为什么不填充子对象?还有其他发送对象的方法吗?
查看PageBase.RedirectToPage Method,可以看到Object就是路由Values。
在 Asp.net 核心 Razor 页面中,我们无法将复杂对象作为路由数据传递。路由数据功能仅支持简单对象,如 int
和 string
。如果你想跨请求保留更复杂的对象,你需要使用Sessions
或TempData
(由会话状态支持)。
因此,您可以参考以下步骤来启用会话并在跨请求之间传输复杂对象。
在Startup.cs中启用会话中间件:在
ConfigureServices
中调用AddSession
,在Configure
中调用UseSession
。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(); }); }
添加 Session 或 TempData 扩展来存储对象。
//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); } }
或
//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); } }
使用session或TempData存储复杂对象:
ResumeForm Post 方法:
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); }
然后,GenerateResume页面Get方法中的代码:
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); } }
测试结果是这样的: