Search code examples
c#.net-coreasp.net-core-mvcrazor-pages

Capturing data of 1 page in another page using Razor view and ASP.NET Core


I am trying to build a mentorship software in ASP.NET Core and I have a problem.

What I intend to do is that, when a mentee wants to register on the platform they enter their name, email and choose from list of career (career being generated as a drop down from another table from the db or can also be generated as drop down from enum). So, when mentee clicks next, the system routes them to another page where they can choose mentor based on the career they have chosen and then when they choose a mentor, they should have a button to post the information from previous page (name and email) and the Id of the selected mentor in Page 2. 

The problem I have is that the data from the first page (the page where a new mentee inputs their email and name) is lost when it routes to the second page (the page to choose a mentor).

I want a way to capture the data in the first page so that I can post these data alongside the data in the second page to the database (Mentee table).

Mentor is a foreign key in the Mentee table because the schema is designed so that a mentee can only have one mentor, but any mentor can have multiple mentees.

I intend to have list of mentors in card, so that when a mentee navigates from the registration page, to the mentor_Selection page, I want to achieve the ability to post both the information on the first page and the information on the second together to the database


Solution

  • Well, based on your scenario and descriptions, you should first preserve your mentee's details in session object. Later on, while navigating to the second page, you just need to extract that object in order to display, it. It's better to have a complex model containing mentees and mentor definitions there.

    Finally, you can store your mentees and mentor's details in your database.

    Let's take a look at how we can achieve that in practice.

    Demo Model:

    public class Mentee
        {
            public int MenteeId { get; set; }
            public string? MenteeName { get; set; }
            public string? MenteeEmail { get; set; }
            public int? MentorId { get; set; }
        }
    
    
    public class Mentor
        {
            public int MentorId { get; set; }
            public string? MentorName { get; set; }
            public string? MentorEmail { get; set; }
        }
    

    Save Mentees View:

    @model CaptureDataAndNavigateFromSessionApp.Models.Mentee
    <div class="row">
        <div class="col-sm-3">
            <form method="post" asp-action="RegisterNewMentee">
                <div class="card" style="width: 18rem; margin-bottom:20px;box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;">
                    <div class="card-body">
                        <h5 class="card-title">Register Mentees</h5>
                        <input asp-for="@Model.MenteeName" placeholder="Enter mentees name" class="form-control"/><br />
                        <input asp-for="@Model.MenteeEmail" placeholder="Enter mentees email" class="form-control" /><br />
                        <input type="submit" value="Register" class="btn btn-primary" />
                    </div>
                </div>
            </form>
        </div>
    </div>
    

    enter image description here

    Save Mentees In Session:

    public static class SessionExtension
        {
            //setting session
            public static void SetComplexObjectSession(this ISession session, string key, object value)
            {
                session.SetString(key, JsonConvert.SerializeObject(value));
            }
    
            //getting session
            public static T? GetComplexObjectSession<T>(this ISession session, string key)
            {
                var value = session.GetString(key);
                return value == null ? default(T) : JsonConvert.DeserializeObject<T>(value);
            }
        }
    

    Note: This is the dynamic session extension method for handling any session object.

    Folder Structure:

    enter image description here

    Method which stores mentees object in session:

    private void KeepMenteeInformation(Mentee mentee)
            {
    
                var getMenteeObject = HttpContext.Session.GetComplexObjectSession<RegisterModelObject>("RegisterMentorMentees");
                if (getMenteeObject != null)
                {
                    getMenteeObject!.Mentees!.Add(mentee);
                    HttpContext.Session.SetComplexObjectSession("RegisterMentorMentees", getMenteeObject);
                }
                else
                {
                    getMenteeObject = new RegisterModelObject();
                    getMenteeObject!.Mentees!.Add(mentee);
                    HttpContext.Session.SetComplexObjectSession("RegisterMentorMentees", getMenteeObject);
                }
            }
    

    Controller:

    public IActionResult RegisterNewMentee(Mentee mentee)
            {
                KeepMenteeInformation(mentee);
    
                return RedirectToAction("MapMentor");
            }
    

    Note: If you use a razor page application, you can just put it inside your method. 

    Map Mentor and Mentees In Second Page:

    In order to select a mentor for a mentee from the dropdown, I am using the following model:

    public class MentorMenteeCustomModel
        {
            public Mentee? Mentee { get; set; }
            public int MentorId { get; set; }
            public IEnumerable<SelectListItem>? Mentors { get; set; }
           
        }
    

    Note: You can modify it as per your requirement.

    Mentor and mentee view page:

    @model CaptureDataAndNavigateFromSessionApp.Models.MentorMenteeCustomModel
    
    <div class="mainContainer">
    
        <form id="registerForm" method="post" asp-action="MapMentorAndMentee">
            <h1 class="span2">Map Mentor & Mentee</h1>
    
            <div class="form-group">
                <label class="control-label">Mentee Name</label>
                <input type="text" class="form-control" asp-for="@Model!.Mentee!.MenteeName" value="@Model!.Mentee!.MenteeName" />
                <span asp-validation-for="@Model!.Mentee!.MenteeName" class="text-danger"></span>
            </div>
    
            <div class="form-group">
                <label asp-for="@Model!.Mentee!.MenteeEmail" class="control-label">Email</label>
                <input type="text" class="form-control" asp-for="@Model!.Mentee!.MenteeEmail" value="@Model!.Mentee!.MenteeEmail" />
                <span asp-validation-for="@Model!.Mentee!.MenteeName" class="text-danger"></span>
            </div>
    
            <div class="form-group">
                <label asp-for="MentorId" class="col-md-2 form-label"> Select Mentor</label>
                <select asp-for="MentorId" asp-items="@Model.Mentors" class="form-control">
                    <option></option>
                </select>
                <span asp-validation-for="MentorId" class="form-span-error"></span>
            </div>
            <br />
            <div class="form-group">
                <input type="submit" value="Submit " class="btn btn-primary" />
            </div>
        </form>
    
    </div>
    

    Map Mentor and Mentee Controller:

    public IActionResult MapMentor()
            {
                var getMenteeObjectFromSession = HttpContext.Session.GetComplexObjectSession<RegisterModelObject>("RegisterMentorMentees");
    
              
    
                var mentorMenteeViewModel = new MentorMenteeCustomModel();
    
                if (getMenteeObjectFromSession != null)
                {
                    mentorMenteeViewModel.Mentee = getMenteeObjectFromSession!.Mentees!.FirstOrDefault();
                    mentorMenteeViewModel.Mentors = listOfMentor.Select(i => new SelectListItem
                    {
                        Text = i.MentorName,
                        Value = i.MentorId.ToString()
                    });
                }
                return View(mentorMenteeViewModel);
            }
    

    Note: This is a very crucial point to understand. As you can see, first I am getting the mentee information, which has been stored on the first page,and then fetching the mentor list from the database. Finally, binding the two objects in a complex view model.

    Program.cs File:

    var builder = WebApplication.CreateBuilder(args);
    
    // Add services to the container.
    builder.Services.AddControllersWithViews();
    
    builder.Services.AddHttpContextAccessor();
    
    builder.Services.AddSession(options =>
    {
        options.Cookie.Name = "RegisterMentorMentees";
        options.IdleTimeout = TimeSpan.FromMinutes(5);
        options.Cookie.IsEssential = true;
    });
    
    var app = builder.Build();
    
    // Configure the HTTP request pipeline.
    if (!app.Environment.IsDevelopment())
    {
        app.UseExceptionHandler("/Home/Error");
        // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
        app.UseHsts();
    }
    
    app.UseHttpsRedirection();
    app.UseStaticFiles();
    
    app.UseRouting();
    app.UseSession();
    
    app.UseAuthorization();
    
    app.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
    
    app.Run();
    

    Output:

    enter image description here

    enter image description here

    Note: If you need more details, you can check out the example here.