Forum Discussion

KevonH's avatar
KevonH
Copper Contributor
Dec 28, 2023

Blazor InteractiveAuto and Blazor InteractiveWebAssembly templates question

With the new render modes, and their respective default templates, it seems that there is no longer the simple example of how to make an API call.

 

With the old .Net 7 templates, there was the weather service component on the client which uses an HttpClient to call to the API to get the WeatherForecast array.

 

I've been struggling to find ANY kind of example on how this is supposed to work in the new Render Modes.

 

The new template has all of the logic to build the WeatherForecast array embedded in the client for both the InteractiveAuto and InteractiveWebAssembly.

What am I missing?  Is there an example of how to make a request that simulates a server call which would normally be a database call?

1 Reply

  • KevonH's avatar
    KevonH
    Copper Contributor

    I managed to find AN example in a YouTube channel.  The answer was essentially that the server rendering and client rendering are tied together via an interface registration in program CS.

     

    For Example:
    On the "server" side, you would add

    builder.Services.AddScoped<IWeatherService, WeatherRepository>()

    where the WeatherRepository is where the simulated database or external api call would live.

     

    In the "client", you would add

    builder.Services.AddScoped<IWeatherService, WeatherService>()

    where the WeatherService was a wrapper to the API call to your server side controller.

     

    Now, there are a LOT of things you have to add to the default template in order to get this to work!

     

    In the server, you also have to add a Controller for your API endpoints.  And, because you need the controller, you had to alter your program.cs file:

    builder.Services.AddController();

    and later

    app.MapController();

     

    In the client, you need to register an HttpClient, or IHttpClientFactory (what's best practice here??)

    builder.Services.AddScoped(http => new HttpClient
    { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });

     

    It doesn't stop there though...  If you implement it just like this, you'll notice an odd reload effect as the normal page cycle goes through it's routine.  First it's rendered on the server, then it's re-rendered after the wasm file is downloaded.  Now, you could turn off server rendering, but why would you do that when the whole purpose is to have this work automatically?

     

    So, the next thing you need to do is alter your Weather.razor.cs file like this:

    using BlazorAutoMode.Client.Features.WeatherService;
    using Microsoft.AspNetCore.Components;
    
    namespace BlazorAutoMode.Client.Pages;
    
    public partial class Weather : ComponentBase, IDisposable
    {
        private WeatherForecast[]? forecasts;
        [Inject] IWeatherService WeatherService { get; set; } = null!;
        [Inject] PersistentComponentState ComponentState { get; set; } = null!;
    
        private PersistingComponentStateSubscription _subscription;
    
        protected override async Task OnInitializedAsync()
        {
            _subscription = ComponentState.RegisterOnPersisting(Persist);
    
            var foundInState = ComponentState
            .TryTakeFromJson<WeatherForecast[]>("weatherList", out var weatherArray);
    
            forecasts = foundInState 
                ? weatherArray 
                : await WeatherService.GetForecastAsync();        
        }
    
        private Task Persist()
        {
            ComponentState.PersistAsJson("weatherList", forecasts);
            return Task.CompletedTask;
        }
        public void Dispose()
        {
            _subscription.Dispose();
        }
    
    }

     

    So, now that I've figured it out.... it SURE would be nice if Microsoft altered the templates so that when you choose InteractiveAuto, it provided an actual implementation as a sample like the above, correcting it (of course) for where my limited understanding has provided a poor solution.