Blazor: 组件记录列表无效

8
使用 Blazor dotnet core 3.1 遇到以下错误:
The list of component records is not valid

发现一份于2019年12月关闭的关于这个问题的错误报告: https://github.com/dotnet/aspnetcore/issues/14966 enter image description here 没有看到任何出现这个错误的原因,希望有解决方法(每个页面调用都不能出现这个错误,只是很少发生...)。
有人有什么想法/提示可能是什么引起了这个错误吗?
谢谢!

6
我曾经遇到过同样的问题,我的情况是组件参数无法以 JSON 序列化方式表示。似乎 Blazor 的错误报告不够完善 - 你应该尝试逐步剥离组件功能,直到消除此错误。 - ghord
其实,现在我想起来了,我在VS中禁用了异常,这可能会吞噬初始化异常。 - ghord
8个回答

8

当我把我的应用程序从.NET Core 3.0升级到.NET Core 3.1并使用Blazor Client时,我遇到了同样的问题。我发现的第一个“解决办法”是在客户端(web浏览器)上进行强制刷新,也就是说,我按下了Ctrl+F5进行了刷新。

我认为有一些API调用被缓存在客户端上,由于从3.0到3.1的某些版本/格式更改,旧的缓存数据不再有效,从而导致错误。

我将联系在Blazor上工作的人,尝试获取更多信息(我在微软与他们一起工作)。


2020年6月1日更新

我在Azure App Services上运行我的应用程序时再次遇到了这个问题。这一次即使按下Ctrl+F5也没有起作用。但是我找到了https://dev59.com/Gbjna4cB1Zd3GeqP4x8T#59356356,并应用了那里的修复方法,似乎解决了我的问题。

我对代码进行了轻微的更改,因为在我的情况下,我只在暂存/生产中使用Azure SignalR服务而不是开发中。因此,我在应用程序的Startup.cs ConfigureServices方法中添加了这段代码:

if (!HostingEnvironment.IsDevelopment())
{
    services.AddSignalR().AddAzureSignalR(options =>
    {
        options.ServerStickyMode = Microsoft.Azure.SignalR.ServerStickyMode.Required;
    });
}

5

这个问题可能是由于浏览器的自动缓存控制引起的。

假设您有两个带有Blazor组件的MVC视图:页面A.cshtml和B.cshtml。

当请求页面A时,您会收到一个包含渲染的Blazor组件的HTML响应,并建立一个连接。然后,您导航到页面B。如果您返回到页面A(例如按下返回按钮),则浏览器将使用之前生成的缓存响应来获取页面A。

这应该会中断客户端和服务器之间的连接,因为组件描述符可能会被更改。(有时似乎是随机的。)

要解决此问题,请在您的_Host.cshtml上禁用此缓存行为,添加以下内容:

@{ 
    Context.Response.Headers["Cache-Control"] = "no-store";
}

这将防止浏览器缓存并使其请求具有正确组件描述符的新页面。
参考: https://github.com/dotnet/aspnetcore/issues/26174#issuecomment-705472525 https://github.com/dotnet/aspnetcore/issues/18143#issuecomment-585961784

1
第一个链接已经失效。 - Jordy
2
我不得不使用“HttpContext”而不是仅仅使用“Context”,但乍一看它并没有解决我的问题。只有在清除浏览器中的站点数据(缓存)后才解决了问题,这可能是添加到解决方案的好注意事项。 - Jordy

5
在我的情况下,我使用了一个类作为级联值,但它没有无参数的构造函数。
public class User 
{
            
    public User(ClaimsPrincipal principal) 
    {
       ....
    }
       ....
 }

 public class User 
 {
    //this fix
    public User(){}
    public User(ClaimsPrincipal principal) 
    {
       ....
    }
       ....
 }

[CascadingParameter]
private User User { get; set; }

点赞这个答案,因为在我的情况下这是正确的答案:Blazor 需要能够序列化/反序列化参数值,如果不能,则会出现此错误。 - Quango
非常感谢您发布这个,真的救了我的下午。 - Pavlos

1
在我的情况下,问题“组件记录列表无效”出现在 Blazor 需要序列化 _Host.cshtml 中组件的参数时。
<component type="typeof(App)" render-mode="Server" param-SessionData="@Model.SessionData" />
经过长时间寻找问题的原因,我发现问题是因为在 SessionData 中克隆了一个 NameValueCollection。我不知道为什么,但当我排除了 NameValueCollection 类型的变量后,问题得到解决。
SessionData 是一个类,其中包含类型为 NameValueCollection 的 Query 属性,其值是通过标准方式进行克隆的:
Query = (Query?.Count ?? 0) != 0 ? new NameValueCollection(Query) : new NameValueCollection()
我尝试使用 for 循环函数克隆集合中的每个项目,但并没有帮助。只有排除 Query 属性后,问题才得以解决。

谢谢兄弟,解释非常有用。 - j.stalin

0
在我的情况下,这归结于blazor.server.js文件的位置。我们使用部分作为捆绑文件来包含所有脚本位置。
@await Html.PartialAsync("_jsBundles")

尝试修复一个间歇性的定时问题,其中JS Interop函数未被找到,这个函数从body移到了head元素。这导致组件记录列表错误会被blazor.server.js间歇性地抛出,导致页面无法加载并阻止电路启动。
由于这不是sprint中唯一的更改,我花了几个小时来调试此问题。由于某种原因,在head元素中使用blazor.server.js会间歇性地导致电路以1而不是0的序列参数启动,从而引发描述符序列必须以0开头的错误,进而触发返回给blazor.server.js的组件记录列表错误。
长话短说,我们最终不得不将js捆绑包部分移回到body(特别是在@RenderBody()之后),以解决此问题。希望这能为遇到相同错误的其他人节省调试时间。

0

@Eilon 是正确的,如果你打算在 Azure 中使用 SignalR 服务,那么代码片段必须添加到启动配置方法中。

if (!HostingEnvironment.IsDevelopment())
{
    services.AddSignalR().AddAzureSignalR(options =>
    {
        options.ServerStickyMode = Microsoft.Azure.SignalR.ServerStickyMode.Required;
    });

}


我正在使用IIS而不是Azure - undefined

0
我所需要做的就是更新NuGet包。

0

我已经解决了这个问题(基本上是通过对比最后一个好的 git 复制品和第一个有问题的复制品进行差异处理)。要在 Blazor 中处理身份验证,您需要在 .cshtml 启动文件中获取 XREF 令牌并保存以在适当的 .razor 页面中使用。

如果您遵循任何示例,您将得到以下类来传递此信息:

public class TokenProvider
{
    public string? XsrfToken { get; set; }
    public string? Cookie { get; set; }

}

public class InitialApplicationState
{
    public string? XsrfToken { get; set; }
    public string? Cookie { get; set; }
}

以上工作良好。 如果您将InitialApplicationState中的属性标记为必需,则不良工作并且会出现此错误,如下所示:

public class TokenProvider
{
    public string? XsrfToken { get; set; }
    public string? Cookie { get; set; }

}

public class InitialApplicationState
{
    public required string XsrfToken { get; set; }
    public required string Cookie { get; set; }
}

为什么?我不知道。但这样可以解决问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接