Search code examples
c#.netblazor

Bizarre Blazor error: crit: blazor.webassembly.js:1Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]


When I build a blazor web app, which I'm publishing to a linux-64 environment, the web app launches, runs briefly (long enough for me to log in successfully) and then fails with the above error. I have pasted the entire stack trace below- it doesn't seem to shed any light on the situation according to the person responsible for the blazor code. I say bizarre because my colleagues can all build and publish and run the app without issue using the exact same code I am using. While this points me at the conclusion that there's something wrong with my machine, there is also a build server exhibiting the same problem, meaning two systems have suffered the same failure, which seems strange to say the least. We have debugged and found that the failure occurs somewhere outside of our code. I am using VS 2022 and VS 2019.

Things I have done to remediate the situation (in the order I did them):

  • Published in other modes (debug remote, release, etc)
  • Restarted VS
  • Built with VS 2022
  • Restarted computer
  • Repaired VS 2022, retried the above (except for 2019)
  • Repaired VS 2019, rebuilt with VS 2019
  • Uninstalled VS 2022, rebuilt with VS 2019
  • Uninstalled VS 2019
  • Reinstalled VS 2019, rebuilt
  • Reinstalled VS 2022, built with VS 2019
  • Uninstalled VS 2019
  • Reinstalled VS 2019, rebuilt
  • Repeated the above on our build environment.

Obviously, none of these made any difference or I wouldn't be here. I've completely stumped my entire team. What could I possibly be missing? Where else should I look for errors? I include the entire stack trace below.

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.ObjectWithParameterizedConstructorConverter`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]].OnTryRead(Utf8JsonReader& , Type , JsonSerializerOptions , ReadStack& , Tuple`2& )
    at System.Text.Json.Serialization.JsonConverter`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]].TryRead(Utf8JsonReader& , Type , JsonSerializerOptions , ReadStack& , Tuple`2& )
    at System.Text.Json.Serialization.JsonConverter`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]].ReadCore(Utf8JsonReader& , JsonSerializerOptions , ReadStack& )
    at System.Text.Json.JsonSerializer.ReadCore[Tuple`2](JsonConverter , Utf8JsonReader& , JsonSerializerOptions , ReadStack& )
    at System.Text.Json.JsonSerializer.ReadCore[Tuple`2](JsonReaderState& , Boolean , ReadOnlySpan`1 , JsonSerializerOptions , ReadStack& , JsonConverter )
    at System.Text.Json.JsonSerializer.<ReadAsync>d__20`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 System.Net.Http.Json.HttpContentJsonExtensions.<ReadFromJsonAsyncCore>d__3`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 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 )

The OnInitializedAsync method: (And be gentle- I didn't write this code and the guy who did was new to blazor when he did. That said, we're happy to receive constructive criticism.)

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


Solution

  • I discovered the problem. The commonality on the two systems was the VS 2022 install. Other build environments hadn't made the switch yet, so they were safe from what I can only assume is a bug. Ultimately, uninstalling VS 2022 wasn't sufficient, because the culprit was the .NET 6 SDK, which gets installed with VS 2022 but doesn't uninstall along with VS 2022's uninstall. Once I removed the SDK, everything went back to functioning as normal.

    Luckily, the presence of the SDK on a user's computer doesn't make a difference; just because they have .NET 6 installed doesn't change the execution of the binary. The binaries produced by .NET 5 and 6 seem to be slightly different. I confirmed this with vbindiff, though I confess I don't know what exactly the differences translate to.