Telerik blogs
ExploreBlazorMobileBindings-870x220

It's time to probe the promise of Blazor Mobile Bindings enticing web developers to come build mobile apps.

Blazor is eating the world. Arguably, Blazor is one of the most exciting technologies for web developers on the .NET stack and allows for building client/server-side web apps entirely in C#. Blazor is inviting developers into an rich ecosystem and seeing continuous innovations with tooling/performance.

Blazor isn't just for web apps though and has clear implications for desktop/mobile. While experimental, Blazor Mobile Bindings is piquing the interest of many mobile developers. Experimental Mobile Blazor Bindings enable developers to build native or hybrid mobile apps using C#/.NET to target iOS, Android and other platforms. The lure is simple—use Razor syntax and the familiar Blazor component model towards building mobile apps.

Let's take a closer look at Blazor Mobile Bindings towards building native cross-platform mobile apps—we'll explore under the covers for some clarity and see a 'Hello World' app in action.

Debunking Myths

We start by trying to clear up some confusion with some honest developer talk.

Q: Are we re-inventing Xamarin.Forms through Blazor?
A: Nope. Blazor Mobile Bindings for making native apps is an abstraction sitting on top of the Mono/Xamarin stack. The project and UI rendering is pretty much Xamarin.Forms, but written with Blazor's web programming model.

Q: I'm happy writing C#/XAML as a Xamarin developer... what if I did not want to write Blazor code?
A: You don't have to. Blazor Mobile Bindings is meant to invite .NET web developers into the native mobile world—just another option to define your UI visual tree.

Q: Is this WebAssembly for native mobile apps?
A: No. There is no WASM here. Blazor Mobile Bindings are literally meant to render native UI on mobile platforms through the Xamarin.Forms abstraction, just with Blazor syntactical sugar.

Q: How is performance?
A: It is about the same as Xamarin.Forms on basic tests. This could improve with the use of universal UI renderers/handlers in .NET MAUI, which is slated to support C#/XAML, C# with MVU and Blazor Mobile Bindings.

Q: Does Blazor Mobile Bindings offer much UI components?
A: Much of Xamarin.Forms UI is already available as Blazor components, as seen in the list below. It is not difficult to build wrappers for custom controls and there are already more than a dozen Blazor Bindings for Telerik UI for Xamarin.

BlazorMobileUI 

Q: Doesn't Blazor syntax easily become spaghetti code?
A: Well, it can if developers aren't paying attention. Design patterns recommend against combining UI markup and code in the same file. Thankfully with Blazor, the Razor pages can be separated from 'code-behind' Razor.cs with convention and partial classes, as demonstrated below and further explained in code.

BlazorMobileNonSpaghetti

'Hello World' Usage

The majority of mobile apps often end up showing a list of things. So a 'Hello World' test for Blazor Mobile Bindings could be to show a list of items, perhaps pulled down from the cloud to resemble reality. Let's do that.

Developers are often looking for fake APIs to test their apps. One such wonderful RESTful service is {JSON} Placeholder—a full featured REST API for testing/prototyping. Say we wanted to fetch a list of Posts to display in our mobile app, as available from https://jsonplaceholder.typicode.com/posts—cookie points for the actual posts being in Latin.

To try things out with Blazor Mobile Bindings, we would get the .NET CLI project template and spin up a new project. The scaffolded project is pretty much a Xamarin.Forms project with an additional NuGet package for Blazor Mobile Bindings and a different way to bootstrap the app. The first order of business to create a simple C# class, so we could map the JSON feed coming down from the RESTful service into objects, like so:

using System;
using Newtonsoft.Json;

namespace BlazorMobile
{
    public class Post
    {
        [JsonProperty(PropertyName = "title")]
        public string Title { get; set; }

        [JsonProperty(PropertyName = "body")]
        public string Body { get; set; }

        [JsonProperty(PropertyName = "userId")]
        public string UserID { get; set; }

        [JsonProperty(PropertyName = "id")]
        public string ID { get; set; }

        public Post() { }
    }
}

As a good practice, we should keep project level constants in a single place—like the URL to our RESTful service:

using System;

namespace BlazorMobile
{
    public class Constants
    {
        public static string POSTRestfulAPIEndpoint = "https://jsonplaceholder.typicode.com/posts";

        public Constants() { }
    }
}

Next up, we need a little helper class called PostManager that knows how to hit the endpoint and fetch down a collection of Posts asynchronously. Notice how the GetPosts() method returns an ObservableCollection<Post>—this aids in easy data binding to our UI, if needed. The JSON PlaceHolder RESTful service returns a maximum of 100 Posts per request.

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Newtonsoft.Json;

namespace BlazorMobile
{
    public class PostManager
    {
        public ObservableCollection<Post> MyPosts = new ObservableCollection<Post>();
        HttpClient myClient = new HttpClient();

        public async Task<ObservableCollection<Post>> GetPosts()
        {
            var response = await myClient.GetAsync(Constants.POSTRestfulAPIEndpoint);

            if (response.IsSuccessStatusCode)
            {
                var content = await response.Content.ReadAsStringAsync();
                MyPosts = JsonConvert.DeserializeObject<ObservableCollection<Post>>(content);
            }

            return MyPosts;
        }

        public PostManager()
        {
        }
    }
}

Let us take a closer look at App.cs, which houses some code that bootstraps our app and provides access to lifecycle events. Xamarin.Forms developers will note the difference here—this borrows from ASP.NET land and adds services through Dependency Injection. Our app's MainPage is a content placeholder and the one component being added is HelloWorld, like so:

using System;
using Microsoft.MobileBlazorBindings;
using Microsoft.Extensions.Hosting;
using Xamarin.Essentials;
using Xamarin.Forms;

namespace BlazorMobile
{
    public class App : Application
    {
        public App()
        {
            var host = MobileBlazorBindingsHost.CreateDefaultBuilder()
                .ConfigureServices((hostContext, services) =>
                {
                    // Register any app-specific services.
                })
                .Build();

            MainPage = new ContentPage();
            host.AddComponent<HelloWorld>(parent: MainPage);
        }

        protected override void OnStart()
        {
        }

        protected override void OnSleep()
        {
        }

        protected override void OnResume()
        {
        }
    }
}

Next up, we define a new Blazor component called PostList, to display just the Title of each Post coming down from the JSON Restful feed. We're essentially describing the Xamarin.Forms visual tree, but with familiar Razor syntax and some code mixed in, to expose parameters or build functions:

<StackLayout Margin="new Thickness(20)" Orientation="StackOrientation.Horizontal">

<Label Text="@PostToDisplay.Title"
       HorizontalOptions="LayoutOptions.FillAndExpand" />
</StackLayout>

@code
{
    [Parameter] public Post PostToDisplay { get; set; }
}

Now, let us turn our attention back to our main HelloWorld component. While Blazor Mobile Bindings allows for markup and code to be in the same file, this would not be a recommended practice as complexity adds up. A much cleaner way would be to separate code in two files—this would be HelloWorld.razor and HelloWorld.razor.cs, just by convention. All we have to do is define a Partial class and we use the 'code-behind' class to fetch data from the RESTful service, like so:

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Newtonsoft.Json;

namespace BlazorMobile
{
    public partial class HelloWorld
    {
        public ObservableCollection<Post> PostsToBind = new ObservableCollection<Post>();

        protected override async Task OnInitializedAsync()
        {
            await FetchData();
            await base.OnInitializedAsync();
        }

        public HelloWorld()
        {

        }

        public async Task FetchData()
        {
            PostManager VM = new PostManager();
            PostsToBind = await VM.GetPosts();
        }
    }
}

With JSON data pulled down from RESTful service and available as a .NET collection object, we can now turn to the visual tree markup in the HelloWorld Blazor component. We print the obligatory 'Hello World!' and then iterate over the collection of Posts—rendering the PostList component as many times as the number of Posts. This is akin to a DataTemplate inside a ListView/GridView for Xamarin.Forms developers—the template or the component is responsible for rendering the visual markup for each item in the collection. For each individual Post, we make sure to set the PostToDisplay property on the PostList component, so that corresponding Post is available to the component as a parameter.

<ContentView>

    <StackLayout Margin="new Thickness(40)">

        <Label Text="Hello, World!"
               FontSize="30" />

        <ScrollView>
            <StackLayout>
                @foreach (Post eachPost in PostsToBind)
                {
                    <PostList PostToDisplay=@eachPost />
                }
            </StackLayout>
        </ScrollView>

    </StackLayout>
</ContentView>

The child Blazor component can now handle the individual Post item sent down as a parameter and uses the markup to render the Title of each Post. The final result is a simple mobile UI showing a list of Posts with infinite scrolling, as fetched down from the RESTful service, as shown below.

BlazorMobileHW

Conclusion

Blazor Mobile Bindings is experimental, but holds a lot of promise. While the rendered mobile app UI may look the same, Blazor Mobile Bindings brings a complete departure from the traditional C#/XAML used to paint the visual tree in Xamarin.Forms. Everything is a Blazor component and all UI is native. Blazor Mobile Bindings simply provides an abstraction over Xamarin.Forms, but with a strong lure for web developers to come build native cross-platform mobile apps. Blazor Mobile Bindings is rumored to be production-ready with .NET MAUI, providing additional options towards building native mobile apps. Until then, Blazor developers can experiment and rejoice in the possibilities.

PS: This article is a part of the awesome 2020 C# Advent Calendar.


SamBasu
About the Author

Sam Basu

Sam Basu is a technologist, author, speaker, Microsoft MVP, gadget-lover and Progress Developer Advocate for Telerik products. With a long developer background, he now spends much of his time advocating modern web/mobile/cloud development platforms on Microsoft/Telerik technology stacks. His spare times call for travel, fast cars, cricket and culinary adventures with the family. You can find him on the internet.

Related Posts

Comments

Comments are disabled in preview mode.