In this lesson, we will explore how to create multi-step forms in Razor Pages and manage state between steps. Multi-step forms are useful for splitting complex forms into smaller, more manageable sections, enhancing the user experience by not overwhelming users with too much information at once.
State management is critical in multi-step forms because it allows us to remember the information entered by the user across different steps. This lesson will guide you through building a simple two-step form using Razor Pages in ASP.NET Core and managing the form state using a singleton service.
Let's get started by creating a state management class and configuring the service in our project.
To manage form state across steps, we will use a singleton service. This ensures that the form data persists as the user navigates between steps. First, define the FormState
class to store form data:
C#1namespace MultiStep.Data 2{ 3 public class FormState 4 { 5 public string Step1Data { get; set; } 6 public string Step2Data { get; set; } 7 } 8}
Next, ensure that the FormState
service is added to the dependency injection container in your Program.cs
file:
C#1// Add a simple in-memory object to store form state 2builder.Services.AddSingleton<FormState>();
We'll start by creating the first step of our multi-step form. We create a Step1.cshtml
file and add the following code:
HTML, XML1@page 2@model Step1Model 3<form method="post"> 4 <div class="form-group"> 5 <label asp-for="Step1Data" class="control-label">Input Step 1 Data:</label> 6 <input asp-for="Step1Data" name="Step1Data" class="form-control" /> 7 <span asp-validation-for="Step1Data" class="text-danger"></span> 8 </div> 9 <button type="submit" class="btn btn-primary">Next</button> 10</form> 11<a href="/">Back to Home</a>
In this code, we have created a form with an input field for the first step data. The asp-for
tag helpers are used to bind the input field to the Step1Data
property in the model. The asp-validation-for
tag helper displays validation errors, if any.
Next, we will add validation to the Step1Model
. We create the Step1.cshtml.cs
file and modify it as follows:
C#1using Microsoft.AspNetCore.Mvc; 2using Microsoft.AspNetCore.Mvc.RazorPages; 3using MultiStep.Data; 4using System.ComponentModel.DataAnnotations; 5 6public class Step1Model : PageModel 7{ 8 private readonly FormState _formState; 9 10 public Step1Model(FormState formState) 11 { 12 _formState = formState; 13 } 14 15 [BindProperty] 16 [Required] 17 public string Step1Data { get; set; } 18 19 public IActionResult OnPost() 20 { 21 if (!ModelState.IsValid) 22 { 23 return Page(); 24 } 25 26 _formState.Step1Data = Step1Data; 27 return RedirectToPage("Step2"); 28 } 29}
In this model, we use the [Required]
data annotation to ensure that Step1Data
is not left empty. The BindProperty
attribute binds form data to the Step1Data
property.
The form submission is managed by the OnPost
method. When the form is submitted, this method validates the input data. If the data is valid, it updates the _formState.Step1Data
with the form data and redirects to the second step.
For the second step, we create the Step2.cshtml
file and include the following code:
HTML, XML1@page 2@model Step2Model 3 4@if (Model.ShowResult) 5{ 6 <h2>Form Submission Complete</h2> 7 <p><strong>Step 1 Data:</strong> @Model.Step1Data</p> 8 <p><strong>Step 2 Data:</strong> @Model.Step2Data</p> 9} 10else 11{ 12 <form method="post"> 13 <div class="form-group"> 14 <label asp-for="Step2Data" class="control-label">Input Step 2 Data:</label> 15 <input asp-for="Step2Data" name="Step2Data" class="form-control" /> 16 <span asp-validation-for="Step2Data" class="text-danger"></span> 17 </div> 18 <button type="submit" class="btn btn-primary">Submit</button> 19 </form> 20} 21<a href="/">Back to Home</a>
In this file, we created a form with an input field for the second step data and display the results after form submission if ShowResult
is true.
Now, let's create the Step2.cshtml.cs
file and modify it as follows:
C#1using Microsoft.AspNetCore.Mvc; 2using Microsoft.AspNetCore.Mvc.RazorPages; 3using MultiStep.Data; 4using System.ComponentModel.DataAnnotations; 5 6public class Step2Model : PageModel 7{ 8 private readonly FormState _formState; 9 10 public Step2Model(FormState formState) 11 { 12 _formState = formState; 13 } 14 15 [BindProperty] 16 [Required] 17 public string Step2Data { get; set; } 18 19 public string Step1Data => _formState.Step1Data; 20 21 [BindProperty(SupportsGet = true)] 22 public bool ShowResult { get; set; } 23 24 public void OnGet() 25 { 26 Step2Data = _formState.Step2Data; 27 } 28 29 public IActionResult OnPost() 30 { 31 if (!ModelState.IsValid) 32 { 33 return Page(); 34 } 35 36 _formState.Step2Data = Step2Data; 37 return RedirectToPage(new { ShowResult = true }); 38 } 39}
In this model, we access the state data from the first step using the _formState
object and display it in the view.
The OnPost
method validates the second step data and updates the _formState.Step2Data
property. If validation passes, it sets ShowResult
to true and reloads the page to display the results.
And that's it! We now have a 2-step form that manages the intermediate steps and displays the data entered through both steps at the end. Adding more steps to this pipeline, if needed, is also fairly simple.
In this lesson, you learned how to create a multi-step form in Razor Pages and manage state across steps. We covered:
- Writing HTML and Razor code for multi-step forms.
- Adding validation using data annotations.
- Managing state between form steps using a singleton service.
- Handling form submissions and displaying results.
Managing state in multi-step forms improves user experience by preserving data entered by users across different steps. Congratulations on reaching the end of the course! To reinforce your learning, proceed to the practice exercises, and continue building on these foundational skills. Happy coding!