The Experimental Framework Everyone is Talking About
Blog Barista: Anthony Wolf | April 10, 2019 | Web Development | Brew time: 6 min
By this time, I had already gotten familiar with other web development stacks, such as ASP.NET Web API + Angular, and had that particular mindset going in. I went into the talk hoping to see Angular, but with C# instead of Typescript. I left the talk convinced that it was exactly as I hoped and became very excited about the possibilities on the horizon for web development; I wanted more than just the brief exposure I had gotten to Blazor during the conference. The goal here is to provide a developer’s-eye perspective of the framework. What does it feel like to code in Blazor?
This post is absolutely all about the following:
- Diving into Blazor head-first from the perspective of an Angular / Web API developer.
- A warning to the future that the code demonstrated here may not be correct for future versions of Blazor.
- A warning to the present (April 2019) that Blazor is not production-ready, and therefore shouldn’t be used in commercial software development at this time.
Off We Go!
Alright, let’s get started…
- Step 1: Install Visual Studio Preview 2019
- Step 2: Install .NET Core SDK 3.0 Preview
- Step 3: Do NOT install the Blazor Language Services Extension from the Visual Studio marketplace like the published directions state. Instead, open Visual Studio 2019 Preview, open the “Extensions” menu, and click “Extensions and Updates.” From the left-hand panel, make sure to select “Online,” and then in the search bar on the right, search for “Blazor.” “ASP.NET Core Blazor Language Services” is the one you want, so install it.
- Step 4: Create a new ASP.NET web application in VS2019 Preview, and during project configuration select “Blazor (ASP.NET Core Hosted).” You will now have the basic demo project that I started with.
A Brief Look at the Demo Solution
In your newly created solution, you will see 3 projects. Let’s assume you’ve named your solution “WebApplication.” WebApplication.Client, as you’ve probably guessed, contains the client-side code, and WebApplication.Server contains ASP.NET core server code as expected. WebApplication.Shared contains shared code across the front and back end. In this case, all that’s there is a single business model: WeatherForecast.cs. Don’t you hate having to re-write the same class over again from your server code in Typescript? Even having a tool auto-generate that same code for the client seems redundant and wasteful. This isn’t limited to simple model POCOs either; with Blazor, any conceivably useful piece of code you’ve written can be reused across both server and client. Before proceeding, you may find it useful to take a moment to run and play with the stock demo, and take a look around at the various pages and how the starting code looks.
Adding Sorting to the Fetch Data Page
Fetch Data is a page in the stock demo that gets a table of random weather forecasts from the server. The first thing that occurred to me to do was to add sorting.
Now we have sortable column header buttons.
This isn’t really anything special. In fact, it is kind of clunky. We have a pattern of bulky code which is repeated for every column in the table. Let’s put our Angular hat on for a moment, and see if we can refactor this into something resembling an Angular component. Here is the solution I came up with:
There are some really interesting things happening here. First of all, you may have noticed that this new sortable column header component makes use of C# Generics – not just in the code-behind component file, but also in the template using the @typeparam declarations in lines 1 and 2, as well as the @inherits declaration. The @inherits declaration is what gives us the neat separation of the .cshtml and .cs files for the component. What about those [Parameter] attributes on the component’s properties? These are similar to Angular @Input() decorators, as you’ll see in the usage for the Fetch Data page.
At this point, you’re probably wondering “What is the deal with the ‘bind-’ for the CurrentSortColumn parameter?” The difference is that “bind-” is currently the prefix that makes two way binding magic work. In this case, it allows the SortableColumnHeaderComponent instances to tell the FetchDataCode that the sort column has changed, and in turn pass that change on down to the other SortableColumnHeaderComponents. In the version of Blazor available at the time of writing (0.8.0), this functionality is limited to simple types and strings. I am hopeful that this will be expanded on in the future to allow a simpler means of updating other types, such as our sorted collection. Now that we’ve scratched the surface of what is possible in terms of sortable tables, a common feature in web applications, let’s take a look at another common feature in web applications: model validation.
To demonstrate model validation, I’ve chosen to stick to just model validation and its presentation. This section will not cover submitting a form to the server. Consider it an exercise left to the reader which can easily be derived from the code available in the github repository linked at the end of the article. To demonstrate model validation, a logical starting point is to have a model.
For my model, I’ve chosen for the sake of blog-post conciseness to implement its validation logic directly in the model itself using the IValidatableObject interface from the System.ComponentModel.DataAnnotations namespace. This is certainly not the only way to do this; .NET has plenty of viable classes, interfaces, and patterns for implementing validation. When coming up with an example for model validation, I had two goals in mind:
- Demonstrate individual property validation rules
- Demonstrate cross-property validation rules
With those two goals in mind, I have combined the use of both property attribute validators as well as custom code written directly in the validation logic itself. The validation logic can be run as a whole by not providing a MemberName value for the ValidationContext, or it can run just for an individual property when it is provided. Now that we have a model with self-contained validation logic, the next step is to implement the component that will deliver the validation errors to the user.
This component is designed to retrieve validation errors for an individual control, and does so by setting the MemberName of the ValidationContext to the value provided by the Property parameter. Now that we have a model and a means for delivering the errors, it’s time to show these pieces in action with a new page.
Normally, I would hope to not have to provide those bulky oninput update lambdas. Without them though, changes to the input are only detected when the control loses focus. I wanted to demonstrate real-time validation occurring as the user types into the control, and this was the best way I could find to make that happen. I’d love to see a better implementation for this, and hope that if there isn’t one that is currently possible that there will be one in the future.
Where Do We Go From Here?
Other recent posts:
Interviewing with Company Culture in Mind Is Better for Business
Blog Barista: Jessica Carnacchi | June 19, 2019 | Business Practices | Brew time: 5 min
Company culture can make or break a business; it has the power to attract and retain top talent or the power to drive it away. (No pressure.) While this isn’t necessarily breaking news, building and maintaining a healthy company culture…
Blog Barista: Jim Rasche | June 12, 2019 | Developer Tools | Brew time: 9 min
Jenkins Pipeline is a powerful, expressive tool to describe your Continuous Integration process, unshackling you from the limitations of the “freestyle” GUI. This post will walk you through creating a simple Jenkins Pipeline that messages you through Slack…