【问题标题】:Blazor Cannot provide a value for property 'ScopeFactory' on type 'MyComponent' because the property has no setterBlazor 无法为类型 \'MyComponent\' 上的属性 \'ScopeFactory\' 提供值,因为该属性没有设置器
【发布时间】:2022-12-15 04:12:35
【问题描述】:

我正在 .NET 6 中编写 Blazor WASM 应用程序。

从 Visual Studio 2022 运行时,该应用程序在 Debug 中正常运行,但是当我使用 dotnet publish -c Release --nologo 将其部署为静态站点并访问 localhost 上的 bin/Release/net6.0/publish/wwwroot 文件夹时,我收到以下错误:

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

我的组件如下所示:

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

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

我像这样在Program.cs中添加服务

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>()));

Options.Create() 看起来像这样

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;
}

我已经做了很多测试和搜索,但找不到任何东西。我试图在我的组件中只请求 HttpClient 服务,但即使这样也会抛出同样的错误。

我看到这是 DI 中的一些问题,但我使用 OwningComponentBase 管理 DI 范围,如 ASP.NET Core Blazor dependency injection 中所述。

什么可能导致它?

先感谢您

【问题讨论】:

标签: c# dependency-injection blazor blazor-webassembly asp.net-blazor


【解决方案1】:

感谢您在 cmets 中发布真实代码。 看了一下,这好像是trimming的结果。

尝试将 &lt;PublishTrimmed&gt;false&lt;/PublishTrimmed&gt; 添加到您的项目文件中,我认为它会起作用。

基本上,当您运行命令 dotnet publish -c Release --nologo 时,它会优化程序集的大小(修剪)。 在您的情况下,它似乎正在更改 OwningComponentBase 中的以下代码:

[Inject] IServiceScopeFactory ScopeFactory { get; set; }

至:

[Inject] IServiceScopeFactory ScopeFactory { get; }

即它在修剪期间移除安装器。

我会认为这是实施中的一个错误

【讨论】:

    【解决方案2】:

    标记的答案只能在您不想在发布时修剪您的应用程序时使用,这并不总是可取的。 如果要发布带有修剪的内容,则必须将类型从修剪中排除。

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

    因为整个修剪的东西本身就是一个主题,所以我可以推荐这个页面来开始调整修剪过程:.Net Blog - Customizing Trimming 博客文章是为 .Net5 编写的,但我也将它用于 .Net6。

    【讨论】:

    • 我不知道排除。感谢您的回答和提供的博客
    【解决方案3】:

    我已经尝试了这篇文章中给出的两个当前答案,并想分享我的发现以防他们帮助某人。

    Jesse Good 的回答可以解决这个问题,但给了我其他与性能相关的问题。它还使构建的时间长度增加了一倍。

    Steffan Ossendorf 的回答对我也有用,尽管需要稍微修改和额外的文件,但绝对值得付出额外的努力。

    如果它对任何人有帮助,这正是我在阅读 Steffan 提到的关于修剪的文章后所做的。

    我在 Blazor 项目的路径中创建了一个名为“Trimmer.xml”的新 XML 文件,内容如下 -

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

    然后我将其添加到我的 Blazor 项目的 .csproj 文件中 -

    <ItemGroup>
        <TrimmerRootDescriptor Include="Trimmer.xml" />
    </ItemGroup>
    

    【讨论】:

      猜你喜欢
      • 2021-04-07
      • 2023-03-14
      • 1970-01-01
      • 2012-05-31
      • 2020-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-16
      相关资源
      最近更新 更多