Exploring Blazor Changes in .NET 8 - Capture User Input with Forms
So far in this series we’ve seen how to render Blazor components using Server Side Rendering, and make certain components interactive using Blazor Server or Blazor WASM.
This works very nicely for presenting information via your .NET web app, but what about capturing data from users?
For example, continuing with our product store, sooner or later the customer will want to go ahead and checkout…
How can we capture details like their address and enable them to place an order?
At this point in the web’s evolution you’d be forgiven for thinking this is a JavaScript thing, that you’ve got to take the user’s input and submit it to an API endpoint as JSON.
But there’s another option…
Enter stage left, the humble form.
NOTE
You can download the latest preview version of .NET 8 direct from Microsoft
Bear in mind .NET 8 is in preview, and any specific implementation details are subject to change.
Forms, the smart choice for capturing data input#
The web ran on forms long before JavaScript and SPAs came along to take the limelight, and they’re still a crucial part of most web apps.
With .NET 8 and server side rendering, your components are rendered once on the server, and plain old HTML sent back to the browser.
HTML forms give you a mechanism to go the other way, to take user input and submit it back to your component (where Blazor/ASP.NET can process it and figure out what to do next).
There are two ways to implement this using .NET 8: either using Blazor’s EditForm
or sticking to plain old HTML forms.
In this post we’ll explore the EditForm
option.
EditForms in Blazor are pretty useful, they provide a straightforward way to bind a form to a model, then interact with that model when the user submits the form.
For example, here’s a form for adding a new post to a blog:
This title
and slug
fields are bound to the underlying Command
model.
As the user interacts with the form this binding ensures Command
is kept in sync with the entered values.
When the user submits the form the HandleValidSubmit
method is invoked.
This takes the data from Command
and processes it accordingly (in this case, posting it as JSON to an endpoint).
Using EditForm with Blazor SSR#
So how do we implement checkout using EditForm?
and Blazor SSR?
The first step is to define a model for the form, to capture the entered data.
Here’s a simple model for capturing key checkout details.
Nothing too complicated. We’re essentially defining a Data Transfer Object (DTO).
Now for the form itself:
Checkout.razor
Here we’ve bound the form to Model
which is an instance of PlaceOrderModel
.
Remember, when we’re rendering components using Server Side Rendering the component is rendered on the server, and the resulting HTML returned to be displayed in the browser.
At this point we have no direct connection between the browser and the server (unlike Blazor Server).
Here’s how it looks in the browser.
When the form is submitted, a standard HTTP POST
request will be made, including the submitted form details
Blazor needs to find a way to take that submitted form data and map it to the relevant component.
Notice how we specified a form name when we defined the EditForm
:
This helps Blazor direct the incoming POST
to the correct component where it will then use model binding to bind the incoming data to the Model
property.
To make that model binding work we just need to decorate the relevant property with the [SupplyParameterFromForm]
attribute.
Now when the form is submitted the SubmitOrder
method will be invoked and the the incoming form values will be available via the Model
parameter.
NOTE
What’s in a name?
Every form in your application (which will be handled on the server like this) needs to have a unique name (as specified using FormName
).
If you want to avoid collisions (so you can use the same name more than once) you can use the new FormMappingScope
component.
For example, say you end up with two different forms both trying to use the name checkout
.
You could wrap one of them in an instance of FormMappingScope
Here I’ve renamed the original razor component to CheckoutForm
and removed its @page
attribute (so it can’t be navigated to directly).
Now when a visitor heads to /checkout
they’ll get to this new component which renders the form, wrapped in a FormMappingScope
component.
The resulting html looks like this in the browser:
The _handler
field’s value of [store-checkout]checkout
will be included in the submitted form data, and ASP.NET will use it to route the data to the correct form.
Pre-populate the form with existing data#
In reality we probably want to pre-populate our checkout form with existing data (items added to the customer’s basket, saved addresses etc.)
Let’s update our component to fetch this data from our backend service/database and use it to populate the form.
With this we’ll fetch an instance of the PlaceOrderCommand
from our IProductStore
implementation, but only if Command
is null,
Here’s the flow:
- On first load
Command
is null so… - Fetch the data from the backend
- User submits the form (thereby posting the submitted values)
- The posted form data is routed to the
SubmitOrder
handler in our component, which… - Maps the incoming data to the
Command
field - Because
Command
field is no longer null, the check inOnInitialized
will leave it alone
To wrap this up, here’s a version of the form complete with pre-populated data plus a handy little summary which the customer will see when the form is submitted.
In Summary#
With Server Side Rendering of Razor components in .NET 8 you have a simpler way to render HTML and make it show up in the browser.
With forms you can go the other way and take user input to be processed on the server.
Blazor’s existing EditForm
component works with SSR to route posted form data to your Razor components.
Just remember to name each form (the name must be unique), and use the [SupplyParameterFromForm]
to bind incoming form data to your model.
All posts in NET 8 Blazor Evolved
- Exploring Blazor Changes in .NET 8 - Auto Render Mode
- Exploring Blazor Changes in .NET 8 - Capture User Input with Forms
- Exploring Blazor Changes in .NET 8 - Interactive Components using Blazor WASM
- Exploring Blazor Changes in .NET 8 - Interactive Components using Blazor Server
- Exploring Blazor Changes in .NET 8 - Server Side Rendering (SSR)