Maui Hybrid application and a Blazor



Since Java first came out, I have been trying to use the same code for both a desktop client and a web client. It was easy to do this for the backend. Getting a shared UI across a desktop and a web client that provided the same experience, was not possible.  Add in the support for Android and iOS and you end up with 4 UI code bases, 4 UI teams, 4 QA teams, etc. Maui Blazor Hybrid to the rescued.

With Maui Blaozr I can finally achieve that goal. In my last post, "Let’s Make a Blazor Hybrid Application!" I showed how to create a simple Maui Blazor hybrid application.  I now took the next step, added a Blazor Web Assembly application, and using the Shared library, I created a hosted web client and a desktop client, with the same UI. Here is how I did it.


Desktop Application

  1. Create a Share UI library project
    1. Move the Pages Folder into the new library
    2. Move the Shared Folder into the new library
    3. Move the CSS folder into the new library
  2. Create a new Shared Service Library
    1. Move the WeatherForecast data class into the new library
    2. Move the WeatherForecast Service class into the new library
  3. In the Maui Project
    1. Create a project reference to the new Shared UI library
    2. Create a project reference to the new Shared Service Library
    3. Add the shared UI values to the router initialization.
      1. This is the tricky part.  In order for the Maui application to see the shared UI, it needs a reference to it in the router.
      2. To achieve this, add the following to the <Router AppAssembly> tag

  • <Router AppAssembly="@typeof(Main).Assembly"       AdditionalAssemblies="new[] { typeof(BlazorHybridSharedUI.Pages.Index).Assembly, typeof(BlazorHybridSharedUI.Shared.MainLayout).Assembly }">
  •         4.  Build, run, and test



    Both Web Client

    1. Add a new Web Client 
      1. I added a Blazor Server and a Blazor web assembly.  The steps are similar except for the WeatherForecast Service.
    2. Remove the Page folder
    3. Remove the Shared Folder
    4. Add a project reference to the Share UI Lib project
    5. Add a project reference to the Shared Service Lib project
    6. Add the shared UI values to the router initialization.
    7. This is the tricky part.  In order for the Maui application to see the shared UI, it needs a reference to it in the router.
    8. To achieve this, add the following to the <Router AppAssembly> tag
      • <Router AppAssembly="@typeof(Main).Assembly"       AdditionalAssemblies="new[] { typeof(BlazorHybridSharedUI.Pages.Index).Assembly, typeof(BlazorHybridSharedUI.Shared.MainLayout).Assembly }">
           10. Build, run, and test

    Web Assembly Client

    The web assembly client added a different twist than the Desktop. The WetherForecast Page gets its data from locally in the Desktop Application while the Balzor web assembly application gets its data from an API.

    To solve this, I simply added a flag, "Hosted", that I set to true when the web assembly client called the weather service.  Based on that flag, it would either use the local method to return the weather forecast data or use the API.

            public async Task<WeatherForecast[]> GetForecastAsync(DateTime startDate)
            {
                if (hosted)
                {
                    return await APIManager();
                }
                else
                {
                    return await GetLocalData(startDate);
                }
            }
            private async Task<WeatherForecast[]> GetLocalData(DateTime startDate)
            {
                return await Task.FromResult(Enumerable.Range(1, 5).Select(index => new WeatherForecast
                {
                    Date = DateOnly.FromDateTime(startDate.AddDays(index)),
                    TemperatureC = Random.Shared.Next(-20, 55),
                    Summary = Summaries[Random.Shared.Next(Summaries.Length)]
                }).ToArray());
            }
            private async Task<WeatherForecast[]> APIManager()
            {
                HttpClient httpClient = new();
                var result = await httpClient.GetFromJsonAsync<WeatherForecast[]>("https://localhost:7198/WeatherForecast");
                if (result == null)
                {
                    result = Array.Empty<WeatherForecast>();
                }
                return result;
            }

    With this change, we can control where the clients are getting the data from, local or an API.


    Summary

    You have to admit, this is pretty cool. Having a single UI codebase can save a lot of time and money. By using the Maui Blazor hybrid technology, you are leveraging your C#, XMAL, HTML, and CSS skills.

    If you want to separate your Desktop UI from the Blazor UI can do that as well, even though it seems to defeat what we are trying to do.  One thing you could do is to make the Home page different between the desktop and the web client but keep the rest of the UX the same.  The options are limitless.


    Comments

    Popular posts from this blog

    Yes, Blazor Server can scale!

    Blazor new and improved Search Box

    Blazor Wizard Step Component