Bizarre Blazor error: crit: blazor.webassembly.js:1Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
Bizarre Blazor error: crit: blazor.webassembly.js:1Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
当我构建一个发布到 linux-64 环境的 blazor web 应用程序时,web 应用程序启动, 运行s 短暂(足够长的时间让我成功登录) 然后因上述错误而失败。我在下面粘贴了整个堆栈跟踪 - 根据负责 blazor 代码的人的说法,它似乎没有说明任何情况。我说奇怪是因为我的同事们都可以使用我正在使用的完全相同的代码构建和发布应用程序,并且运行应用程序没有问题。虽然这让我得出了我的机器有问题的结论,但也有一个构建服务器出现了同样的问题,这意味着两个系统遇到了同样的故障,至少可以说这看起来很奇怪。我们已经调试,发现故障发生在我们代码之外的某个地方。我正在使用 VS 2022 和 VS 2019。
我为纠正这种情况所做的事情(按照我做的顺序):
- 以其他模式发布(远程调试、发布等)
- 重启VS
- 使用 VS 2022 构建
- 重新启动计算机
- 已修复 VS 2022,重试上述(2019 除外)
- 已修复 VS 2019,使用 VS 2019 重建
- 卸载 VS 2022,用 VS 2019 重建
- 已卸载 VS 2019
- 重新安装 VS 2019,重建
- 重新安装 VS 2022,使用 VS 2019 构建
- 已卸载 VS 2019
- 重新安装 VS 2019,重建
- 在我们的构建环境中重复上述内容。
显然,其中 none 产生了任何影响,否则我不会在这里。我完全难住了我的整个团队。我可能会遗漏什么?我还应该在哪里寻找错误?我在下面包含了整个堆栈跟踪。
blazor.webassembly.js:1
crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
Unhandled exception rendering component: ConstructorParamIncompleteBinding, Void .ctor(System.String, System.String), System.Tuple2[System.String,System.String] System.InvalidOperationException: ConstructorParamIncompleteBinding, Void .ctor(System.String, System.String), System.Tuple
2[System.String,System.String]
at System.Text.Json.ThrowHelper.ThrowInvalidOperationException_ConstructorParameterIncompleteBinding(ConstructorInfo , Type )
at System.Text.Json.Serialization.Converters.ObjectWithParameterizedConstructorConverter1[[System.Tuple
2[[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].OnTryRead(Utf8JsonReader& , Type , JsonSerializerOptions , ReadStack& , Tuple2& ) at System.Text.Json.Serialization.JsonConverter
1[[System.Tuple2[[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].TryRead(Utf8JsonReader& , Type , JsonSerializerOptions , ReadStack& , Tuple
2& )
at System.Text.Json.Serialization.JsonConverter1[[System.Tuple
2[[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].ReadCore(Utf8JsonReader& , JsonSerializerOptions , ReadStack& )
at System.Text.Json.JsonSerializer.ReadCore[Tuple2](JsonConverter , Utf8JsonReader& , JsonSerializerOptions , ReadStack& ) at System.Text.Json.JsonSerializer.ReadCore[Tuple
2](JsonReaderState& , Boolean , ReadOnlySpan1 , JsonSerializerOptions , ReadStack& , JsonConverter ) at System.Text.Json.JsonSerializer.<ReadAsync>d__20
1[[System.Tuple2[[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext() at System.Net.Http.Json.HttpContentJsonExtensions.<ReadFromJsonAsyncCore>d__3
1[[System.Tuple2[[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext() at System.Net.Http.Json.HttpClientJsonExtensions.<GetFromJsonAsyncCore>d__9
1[[System.Tuple`2[[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
at BlazorWebApp.Client.Pages.Alarms.OnInitializedAsync()
at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task )
OnInitializedAsync 方法:(请注意 - 我没有编写此代码,编写此代码的人在他编写时是 blazor 的新手。也就是说,我们很高兴收到建设性的批评。)
protected override async Task OnInitializedAsync()
{
_token = await sessionStorage.GetItemAsStringAsync("token");
if(_token == null)
{
cts = new CancellationTokenSource();
NavMgr.NavigateTo("?redirect=alarms");
return;
}
_token = _token.Replace("\"", "");
if (!(await Http.GetFromJsonAsync<bool>($"User/IsAuthenticated token={_token}")))
{
cts = new CancellationTokenSource();
NavMgr.NavigateTo("?redirect=alarms");
return;
}
_permissions = await Http.GetFromJsonAsync<Dictionary<UserMgr.eAction, bool>
($"User/Permissions?token={_token}");
//throws on the next line
_userInfo = await Http.GetFromJsonAsync<Tuple<string, string>>
($"User/UserInfo?token={_token}");
_username = _userInfo.Item1;
_password = _userInfo.Item2;
_userInfo = new(_username, _password);
if (_permissions[UserMgr.eAction.ViewAlerts])
{
_alarms = await Http.GetFromJsonAsync<List<WebAppAlarm>>
($"Alarms/GetAlarms?numAlarms={10}&offset={0}");
totalAlarms = await Http.GetFromJsonAsync<int>
("Alarms/GetNumberOfAlarms");
_dates = new List<string>();
_speedBands = new List<Tuple<int, int>>();
_conditionStates = new List<string>();
foreach (WebAppAlarm a in _alarms)
{
if (!_dates.Exists(x => x == a.Date.ToShortDateString()))
_dates.Add(a.Date.ToShortDateString());
if (!_speedBands.Exists(x =>
x.Item1 == a.SpeedBand.Item1 &&
x.Item2 == a.SpeedBand.Item2))
_speedBands.Add(a.SpeedBand);
if (!_conditionStates.Exists(x => x == a.ConditionStateName))
_conditionStates.Add(a.ConditionStateName);
if (a.AlarmLevel == AlarmLevel.OK
&& a.AckIgn == AckIgnoreState.None)
{
await AlarmAckClicked(a);
}
}
_showRaptorBusy = true;
while (_showRaptorBusy)
{
try
{
var response = await Http.PostAsJsonAsync<Tuple<string, string>>
("Machines/GetMachines", _userInfo);
_machines = await response.Content.
ReadFromJsonAsync<List<WebAppMachine>>();
_showRaptorBusy = false;
}
catch (SystemException e)
{
Console.WriteLine("Exception: " + e.Message);
_retryCount++;
_showRaptorBusy = true;
await Task.Delay(1000);
StateHasChanged();
}
}
if (_alarms.Count > 0)
await AlarmRowClicked(_alarms[_alarms.Count - 1]);
if (CompId != null && _alarms.Exists(a =>
(a.CompID.ToString() == CompId &&
a.FaultType.ToString() == FaultType &&
a.AlarmLevel.ToString() == Level &&
a.Date.ToShortTimeString().Replace(" ", "") == Time)))
{
CompId = HttpUtility.UrlDecode(CompId);
FaultType = HttpUtility.UrlDecode(FaultType);
Level = HttpUtility.UrlDecode(Level);
Time = HttpUtility.UrlDecode(Time);
WebAppAlarm a = _alarms.Find(a =>
(a.CompID.ToString() == CompId &&
a.FaultType.ToString() == FaultType &&
a.AlarmLevel.ToString() == Level &&
a.Date.ToShortTimeString().Replace(" ", "") == Time));
await AlarmRowDblClick(a);
}
string blink;
if ((blink = await JSR.InvokeAsync<string>("getCookie", "blinkingEnabled")) != "")
{
_showBlinking = bool.Parse(blink);
}
await Http.PostAsJsonAsync<List<WebAppAlarm>>
("Alarms/ExportAlarms", _alarms);
toggleGetAlarms();
}
_isReady = true;
}
我发现了问题。这两个系统的共同点是 VS 2022 安装。其他构建环境还没有进行切换,所以它们是安全的,我只能假设是一个错误。最终,卸载 VS 2022 是不够的,因为罪魁祸首是 .NET 6 SDK,它随 VS 2022 一起安装,但不会随 VS 2022 的卸载一起卸载。删除 SDK 后,一切恢复正常。
幸运的是,用户计算机上是否存在 SDK 并没有什么不同;仅仅因为他们安装了 .NET 6 不会改变二进制文件的执行。 .NET 5 和 6 生成的二进制文件似乎略有不同。我用 vbindiff 确认了这一点,但我承认我不知道这些差异究竟意味着什么。
当我构建一个发布到 linux-64 环境的 blazor web 应用程序时,web 应用程序启动, 运行s 短暂(足够长的时间让我成功登录) 然后因上述错误而失败。我在下面粘贴了整个堆栈跟踪 - 根据负责 blazor 代码的人的说法,它似乎没有说明任何情况。我说奇怪是因为我的同事们都可以使用我正在使用的完全相同的代码构建和发布应用程序,并且运行应用程序没有问题。虽然这让我得出了我的机器有问题的结论,但也有一个构建服务器出现了同样的问题,这意味着两个系统遇到了同样的故障,至少可以说这看起来很奇怪。我们已经调试,发现故障发生在我们代码之外的某个地方。我正在使用 VS 2022 和 VS 2019。
我为纠正这种情况所做的事情(按照我做的顺序):
- 以其他模式发布(远程调试、发布等)
- 重启VS
- 使用 VS 2022 构建
- 重新启动计算机
- 已修复 VS 2022,重试上述(2019 除外)
- 已修复 VS 2019,使用 VS 2019 重建
- 卸载 VS 2022,用 VS 2019 重建
- 已卸载 VS 2019
- 重新安装 VS 2019,重建
- 重新安装 VS 2022,使用 VS 2019 构建
- 已卸载 VS 2019
- 重新安装 VS 2019,重建
- 在我们的构建环境中重复上述内容。
显然,其中 none 产生了任何影响,否则我不会在这里。我完全难住了我的整个团队。我可能会遗漏什么?我还应该在哪里寻找错误?我在下面包含了整个堆栈跟踪。
blazor.webassembly.js:1 crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100] Unhandled exception rendering component: ConstructorParamIncompleteBinding, Void .ctor(System.String, System.String), System.Tuple
2[System.String,System.String] System.InvalidOperationException: ConstructorParamIncompleteBinding, Void .ctor(System.String, System.String), System.Tuple
2[System.String,System.String] at System.Text.Json.ThrowHelper.ThrowInvalidOperationException_ConstructorParameterIncompleteBinding(ConstructorInfo , Type ) at System.Text.Json.Serialization.Converters.ObjectWithParameterizedConstructorConverter1[[System.Tuple
2[[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].OnTryRead(Utf8JsonReader& , Type , JsonSerializerOptions , ReadStack& , Tuple2& ) at System.Text.Json.Serialization.JsonConverter
1[[System.Tuple2[[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].TryRead(Utf8JsonReader& , Type , JsonSerializerOptions , ReadStack& , Tuple
2& ) at System.Text.Json.Serialization.JsonConverter1[[System.Tuple
2[[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].ReadCore(Utf8JsonReader& , JsonSerializerOptions , ReadStack& ) at System.Text.Json.JsonSerializer.ReadCore[Tuple2](JsonConverter , Utf8JsonReader& , JsonSerializerOptions , ReadStack& ) at System.Text.Json.JsonSerializer.ReadCore[Tuple
2](JsonReaderState& , Boolean , ReadOnlySpan1 , JsonSerializerOptions , ReadStack& , JsonConverter ) at System.Text.Json.JsonSerializer.<ReadAsync>d__20
1[[System.Tuple2[[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext() at System.Net.Http.Json.HttpContentJsonExtensions.<ReadFromJsonAsyncCore>d__3
1[[System.Tuple2[[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext() at System.Net.Http.Json.HttpClientJsonExtensions.<GetFromJsonAsyncCore>d__9
1[[System.Tuple`2[[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext() at BlazorWebApp.Client.Pages.Alarms.OnInitializedAsync() at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync() at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task )
OnInitializedAsync 方法:(请注意 - 我没有编写此代码,编写此代码的人在他编写时是 blazor 的新手。也就是说,我们很高兴收到建设性的批评。)
protected override async Task OnInitializedAsync()
{
_token = await sessionStorage.GetItemAsStringAsync("token");
if(_token == null)
{
cts = new CancellationTokenSource();
NavMgr.NavigateTo("?redirect=alarms");
return;
}
_token = _token.Replace("\"", "");
if (!(await Http.GetFromJsonAsync<bool>($"User/IsAuthenticated token={_token}")))
{
cts = new CancellationTokenSource();
NavMgr.NavigateTo("?redirect=alarms");
return;
}
_permissions = await Http.GetFromJsonAsync<Dictionary<UserMgr.eAction, bool>
($"User/Permissions?token={_token}");
//throws on the next line
_userInfo = await Http.GetFromJsonAsync<Tuple<string, string>>
($"User/UserInfo?token={_token}");
_username = _userInfo.Item1;
_password = _userInfo.Item2;
_userInfo = new(_username, _password);
if (_permissions[UserMgr.eAction.ViewAlerts])
{
_alarms = await Http.GetFromJsonAsync<List<WebAppAlarm>>
($"Alarms/GetAlarms?numAlarms={10}&offset={0}");
totalAlarms = await Http.GetFromJsonAsync<int>
("Alarms/GetNumberOfAlarms");
_dates = new List<string>();
_speedBands = new List<Tuple<int, int>>();
_conditionStates = new List<string>();
foreach (WebAppAlarm a in _alarms)
{
if (!_dates.Exists(x => x == a.Date.ToShortDateString()))
_dates.Add(a.Date.ToShortDateString());
if (!_speedBands.Exists(x =>
x.Item1 == a.SpeedBand.Item1 &&
x.Item2 == a.SpeedBand.Item2))
_speedBands.Add(a.SpeedBand);
if (!_conditionStates.Exists(x => x == a.ConditionStateName))
_conditionStates.Add(a.ConditionStateName);
if (a.AlarmLevel == AlarmLevel.OK
&& a.AckIgn == AckIgnoreState.None)
{
await AlarmAckClicked(a);
}
}
_showRaptorBusy = true;
while (_showRaptorBusy)
{
try
{
var response = await Http.PostAsJsonAsync<Tuple<string, string>>
("Machines/GetMachines", _userInfo);
_machines = await response.Content.
ReadFromJsonAsync<List<WebAppMachine>>();
_showRaptorBusy = false;
}
catch (SystemException e)
{
Console.WriteLine("Exception: " + e.Message);
_retryCount++;
_showRaptorBusy = true;
await Task.Delay(1000);
StateHasChanged();
}
}
if (_alarms.Count > 0)
await AlarmRowClicked(_alarms[_alarms.Count - 1]);
if (CompId != null && _alarms.Exists(a =>
(a.CompID.ToString() == CompId &&
a.FaultType.ToString() == FaultType &&
a.AlarmLevel.ToString() == Level &&
a.Date.ToShortTimeString().Replace(" ", "") == Time)))
{
CompId = HttpUtility.UrlDecode(CompId);
FaultType = HttpUtility.UrlDecode(FaultType);
Level = HttpUtility.UrlDecode(Level);
Time = HttpUtility.UrlDecode(Time);
WebAppAlarm a = _alarms.Find(a =>
(a.CompID.ToString() == CompId &&
a.FaultType.ToString() == FaultType &&
a.AlarmLevel.ToString() == Level &&
a.Date.ToShortTimeString().Replace(" ", "") == Time));
await AlarmRowDblClick(a);
}
string blink;
if ((blink = await JSR.InvokeAsync<string>("getCookie", "blinkingEnabled")) != "")
{
_showBlinking = bool.Parse(blink);
}
await Http.PostAsJsonAsync<List<WebAppAlarm>>
("Alarms/ExportAlarms", _alarms);
toggleGetAlarms();
}
_isReady = true;
}
我发现了问题。这两个系统的共同点是 VS 2022 安装。其他构建环境还没有进行切换,所以它们是安全的,我只能假设是一个错误。最终,卸载 VS 2022 是不够的,因为罪魁祸首是 .NET 6 SDK,它随 VS 2022 一起安装,但不会随 VS 2022 的卸载一起卸载。删除 SDK 后,一切恢复正常。
幸运的是,用户计算机上是否存在 SDK 并没有什么不同;仅仅因为他们安装了 .NET 6 不会改变二进制文件的执行。 .NET 5 和 6 生成的二进制文件似乎略有不同。我用 vbindiff 确认了这一点,但我承认我不知道这些差异究竟意味着什么。