'Blazor Cannot provide a value for property 'ScopeFactory' on type 'MyComponent' because the property has no setter

I'm writing Blazor WASM app in .NET 6.

The app works as it should in Debug when running from Visual Studio 2022, but when I deploy it as a static site using dotnet publish -c Release --nologo and access the bin/Release/net6.0/publish/wwwroot folder on localhost I get the following error:

Unhandled exception rendering component: Cannot provide a value for property 'ScopeFactory' on type 'MySolution.Pages.MyComponent' because the property has no setter.

My component looks like this:

public class MyComponent : OwningComponentBase
{
    public IOptions Option { get; set; } = Options.Default;

    protected override async Task OnInitializedAsync()
    {
        Options = await ScopedServices.GetRequiredService<Task<IOptions>>();
    }
}

I add the service in Program.cs like this

builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.Services.AddScoped<Task<IOptions>>(async op => await Options.Create(op.GetRequiredService<HttpClient>()));

and the Options.Create() looks like this

public static async Task<IGameOptions> Create(HttpClient client)
{
    var json = await client.GetStringAsync("/gameOptions.json");

    var options = JsonConvert.DeserializeObject<Options>(json);

    if (options is null)
    {
        throw new InvalidDataException("Given path contains invalid JSON object.");
    }

    return options;
}

I've already done a lot of testing and searching, but I couln't find anything. I tried to only request the HttpClient service in my component, but even that throws the same error.

I see that it is some problem in DI, but I manage the DI scope using the OwningComponentBase, as it is stated in the ASP.NET Core Blazor dependency injection.

What could cause it?

Thank you in advance



Solution 1:[1]

Thanks for posting the real code in the comments. After looking at it, this looks to be a result of trimming.

Try adding <PublishTrimmed>false</PublishTrimmed> to your project file and I think it will work.

Basically when you run the command dotnet publish -c Release --nologo, it is optimizing the assemblies for size (trimming). In your case, it appears to be changing the following code in OwningComponentBase from:

[Inject] IServiceScopeFactory ScopeFactory { get; set; }

to:

[Inject] IServiceScopeFactory ScopeFactory { get; }

i.e. its removing the setter during trimming.

I would consider this a bug with the implementation

Solution 2:[2]

The marked answer can only be used as long as you don't want to trim your app on publish which is not always desirable. If you want to publish with trimming you have to exclude the type from trimming.

<assembly fullname="Microsoft.AspNetCore.Components">
    <type fullname="Microsoft.AspNetCore.Components.OwningComponentBase" preserve="all" />
</assembly>

Because the whole trimming stuff is a topic of itself I can recommend this page for starting with adjusting the trimming process: .Net Blog - Customizing Trimming The blog post was written for .Net5 but I'm using it for .Net6 as well.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Stefan Ossendorf