0

I'm using a Blazor web assembly project with .NET 8 "Blazor Web App" project, which supports both client (only WASM) and server rendering (SSR pages for authorization) content.

I'm a bit confused by how IoC work. That's something that the doc does not mention, but clearly reproduced on brand new "Blazor Web App" project: for pages defined as @rendermode InteractiveWebAssembly (for example Counter.razor with injected services like @inject HttpClient), I have to define service HttpClient in 2 places: Program.cs of the client project, and Program.cs of the server project, even if it's only used inside wasm. If I miss one place, it throws exception that HttpClient service is not defined.

What probably happens it renders the InteractiveWebAssembly page on the server side first, and then all further interactions carrying via wasm. So WebAssembly in "Blazor Web App" seems to be treated differently from what it used to be in a regular WebAssembly project. I know there is another type of WebAssembly type of project, that supports wasm only, but I want to have server side at my disposal too. So I wonder if there is any way around it, if I want for some pages having wasm-only rendering, no server rendering at all?

Also I tried the option to be

@(new InteractiveWebAssemblyRenderMode(false))

It is working with WASM but SSR pages cannot work for authorization, any advice ?

I tried to change the render mode WASM was working, but SSR pages are not working

2
  • What are you using HttpClient for? How you solve your issue is dependant on how you are using it? More generally this commentary of mine provides more detail on building a mixed mode site - github.com/ShaunCurtis/Blazor.ExploreRendering/blob/master/… Commented Jan 31, 2024 at 9:21
  • I want to use HttpClient on all WASM application, Server will be API and authorization pages and client is WASM using HttpClient Commented Feb 1, 2024 at 10:27

1 Answer 1

0

You don't need to define HttpClient where you don't use it.

Consider the WeatherForcast List page.

You can define the data provider for the page like this as an interface.

public interface IWeatherForecastProvider
{
    public Task<ListResult<WeatherForecast>> GetWeatherForecastsAsync(ListRequest request, CancellationToken? cancellationToken = null);
}

The Server version goes straight to the database and gets the data:

public class ServerWeatherForecastProvider : IWeatherForecastProvider
{
    public Task<ListResult<WeatherForecast>> GetWeatherForecastsAsync(ListRequest request, CancellationToken? cancellationToken = null)
    {
        // Dummy singleton provider
        var _provider = WeatherDataProvider.GetInstance();

        var query = _provider.WeatherForecasts
            .Skip(request.StartIndex)
            .Take(request.PageSize);

        var totalCount = query.Count();

        return Task.FromResult(ListResult<WeatherForecast>.Success(query, totalCount));
    }
}

The server API also uses this implementation:

public static void AddAppEndPoints(this WebApplication app)
{
    app.MapPost("/API/Weather/GetWeatherForecasts", async ([FromBody] ListRequest listRequest, IWeatherForecastProvider provider) =>
    {
        var result = await provider.GetWeatherForecastsAsync(listRequest);
        return result;
    });
}

The WASM API version is the only one that uses an HttpContext:

public class APIWeatherForecastProvider : IWeatherForecastProvider
{
    private IHttpClientFactory _httpClientFactory;
    private List<WeatherForecast>? _forecasts;

    public APIWeatherForecastProvider(IHttpClientFactory httpClientFactory)
    {
        _httpClientFactory = httpClientFactory;
    }

    public async Task<ListResult<WeatherForecast>> GetWeatherForecastsAsync(ListRequest request, CancellationToken? cancellationToken = null)
    {
        using var httpClient = _httpClientFactory.CreateClient("ServerAPI");

        var httpResult = await httpClient.PostAsJsonAsync<ListRequest>("/API/Weather/GetWeatherForecasts", request, cancellationToken ?? new());

        if (httpResult.IsSuccessStatusCode)
        {
            var listResult = await httpResult.Content.ReadFromJsonAsync<ListResult<WeatherForecast>>();
            return listResult;
        }
        return ListResult<WeatherForecast>.Failure($"Request failed.  Error Code: {httpResult.StatusCode.ToString()}");
    }
}

The Server Program:

services.AddScoped<IWeatherForecastProvider, ServerWeatherForecastProvider>();

And the WASM Program:

services.AddScoped<IWeatherForecastProvider, APIWeatherForecastProvider>();
services.AddHttpClient("ServerAPI", client => client.BaseAddress = new Uri(baseUrl));

So WebAssembly in "Blazor Web App" seems to be treated differently from what it used to be in a regular WebAssembly project.

What you get is the old WebAssembly NetCore Hosted solution as long as you set Interactivity to Global.

You can see the full solution that this code came from here - https://github.com/ShaunCurtis/Blazr.Auto.Demo

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.