Niezainicjowana zmienna, brak referencji do obiektu?

0

Cześć.
Mam problem z generowaniem strony. Visual Studio 2022, Blazor App. Po uruchomieniu dostaję w konsoli błąd o niezainicjowanej zmiennej.

blazor.webassembly.js:1 
 crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
      Unhandled exception rendering component: Object reference not set to an instance of an object.
System.NullReferenceException: Object reference not set to an instance of an object.
   at Firma1.Reservations.Client.Pages.SeasonCityPage.BuildRenderTree(RenderTreeBuilder __builder) in C:\code\firma1\firma1-my\src\Firma1.Reservations.Client\Pages\SeasonCityPage.razor:line 56
   at Microsoft.AspNetCore.Components.ComponentBase.<.ctor>b__6_0(RenderTreeBuilder builder)
   at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderInExistingBatch(RenderQueueEntry renderQueueEntry)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()
[NEW] Explain Console errors by using Copilot in Edge: click 
 to explain an error. Learn more
Don't show again
14
Unchecked runtime.lastError: A listener indicated an asynchronous response by returning true, but the message channel closed before a response was received
season-city1:1 
 Uncaught (in promise) 
Error: A listener indicated an asynchronous response by returning true, but the message channel closed before a response was received

Mój kod wygląda tak:

@{
    #nullable enable
}
@layout MainLayout
@page "/season-city1"
@using Firma1.Reservations.Client.Components
@using Firma1.Reservations.Client.Components.ReservationsPageComponents 
@using Firma1.Reservations.Client.Components.SeasonCityPageComponents
@using Firma1.Reservations.Shared.SeasonCityControllerModels
@using Firma1.Common.Database.Models
@using NodaTime
@using NodaTime.Extensions
@using NodaTime.Text
@using Firma1.Reservations.AuthorizationPolicies
@using Firma1.Reservations.Client.Services
@using ClaimTypes = Firma1.Reservations.Shared.ClaimTypes;
@inject JavaScriptInterop JavaScriptInterop
@inject AsyncTimerService FocusTimer
@inject AsyncTimerService ReservationsAreOpenCheckTimer
@inject ApiSeasonCityService ApiSeasonCityService
@inject AuthenticationStateProvider AuthenticationStateProvider
@inject IClock Clock
@inject NavigationManager Navigation
@attribute [Authorize(Policy = PolicyName.ClientLegalAccepted)]
@implements IDisposable

<div class="container">
    @if (_initialLoadInProgress)
    {
        <div class="text-center">
            <div class="spinner-border text-primary" role="status">
                <span class="visually-hidden">Ładowanie...</span>
            </div>
        </div>
    }
    else 
    {
        @if (_clientHasKids)
        {
            @if (_seasonCityOffersExists)
            {
                <select @ref="@_selectKidElement" class="form-select" aria-label="Wybierz dziecko">
                    <option selected="@(_selectedKidId is null)" value="">-- Proszę wskazać dziecko --</option>
                    @foreach (var kid in _clientKids)
                    {
                        <option selected="@(kid!.ClientFamilyId == _selectedKidId)" value="@kid!.ClientFamilyId">
                            <span>@kid!.ClientFullName</span>
                        </option>
                    }
                </select>
                @if (_ileOfert != 0)
                {
                    <select @ref="@_selectSeasonCityTripElement" class="form-select" aria-label="Wybór turnusu">
                        <option selected="@(_selectedSeasonCityTripId is null)" value="">-- Proszę wybrać turnus --</option>
                        @foreach (var trip in _seasonCityOffers)
                        {
                            <option selected="@(trip!.SeasonCityTrip!.Id == _selectedSeasonCityTripId)" value="@trip!.SeasonCityTrip!.Id">
                                <span>@trip!.SeasonCityTrip!.Name (@trip!.SeasonCityTrip!.DateFrom.ToString("dd.MM.yyyy") - @trip!.SeasonCityTrip!.DateTo.ToString("dd.MM.yyyy"))</span>
                            </option>
                        }
                    </select>
                }
                else
                {
                    <span>Nie ma ofert!!! WTF?</span>
                }
            }
            else
            {
                <div class="alert alert-success">Obecnie nie ma dostępnych ofert dla dzieci</div>
            }
        }    
        else
        {
            <div class="alert alert-success">Nie posiadasz dzieci w wieku uprawniającym do skorzystania z oferty</div>
        }
    }
</div>

@code {
    private ElementReference _selectKidElement;
    private ElementReference _selectSeasonCityTripElement;
    private int? _selectedKidId;
    private int? _selectedSeasonCityTripId;
    private bool _initialLoadInProgress = false;
    private string _currentSeason = "";
    private int _clientId;
    private int _ileOfert = 0;
    private bool _reservationPossibilitiesExists = false;
    private bool _seasonCityOffersExists = false;
    private bool _sesonCityAreOpen = false;
    private bool _clientHasKids = false;
    private List<ReservationSeasonCityData> _seasonCityOffers = new(); 
    private List<ClientBeneficiaryFamilyMember> _clientKids = new();

    protected override async Task OnInitializedAsync()
    {
        try
        {
            _initialLoadInProgress = true;
            //_seasonCityReservationList = await ApiSeasonCityService.GetSeasonCityReservations();
            //_currentSeason = "2024";
            _clientHasKids = await ApiSeasonCityService.CheckIfClientHasKids();

            if (_clientHasKids)
            {
                _seasonCityOffersExists = await ApiSeasonCityService.CheckIfRegistrationIsOpened();
                if (_seasonCityOffersExists)
                {
                    _seasonCityOffers = await ApiSeasonCityService.GetSeasonCityTripOpenedForRegistration();
                    _clientKids = await ApiSeasonCityService.GetClientKids();
                    _ileOfert = _seasonCityOffers.Count;
                }
            }
        }
        finally
        {
            _initialLoadInProgress = false;
        }
    }
    public void Dispose()
    {
        ReservationsAreOpenCheckTimer.Stop();
    }

}

Wiersz 56 z instrukcjami @foreach (var trip in _seasonCityOffers)
{

Nie mogę się dopatrzeć czego nie inicjuję. Skąd ten brak referencji do obiektu? Czy ktoś jest w stanie mnie naprowadzić na właściwą ścieżkę?
Zastanawia mnie też to:

Unchecked runtime.lastError: A listener indicated an asynchronous response by returning true, but the message channel closed before a response was received
3
@foreach (var kid in _clientKids)
{
    <option selected="@(kid!.ClientFamilyId == _selectedKidId)" value="@kid!.ClientFamilyId">
        <span>@kid!.ClientFullName</span>
    </option>
}

 @foreach (var trip in _seasonCityOffers)
{
    <option selected="@(trip!.SeasonCityTrip!.Id == _selectedSeasonCityTripId)" value="@trip!.SeasonCityTrip!.Id">
        <span>@trip!.SeasonCityTrip!.Name (@trip!.SeasonCityTrip!.DateFrom.ToString("dd.MM.yyyy") - @trip!.SeasonCityTrip!.DateTo.ToString("dd.MM.yyyy"))</span>
    </option>
}

Widzę tu dużo wykrzykników nastawiane. Jesteś pewien, że w tych polach nie ma nulla? Najlepiej postawić breakpoint'a po załadowaniu danych i przejrzeć czy wszystkie pola w każdym wierszu są uzupełnione.

A najprościej to zakomentuj najpierw jeden fragment i zobacz czy działa bez niego a potem drugi fragment. Wtedy chociaż będziesz wiedzieć czy to to miejsce.

0

Dane są, sprawdziłem na endpointach. Są dane JSON wyciągniete z bazy dokładnie w takiej formie jakiej się spodziewałem. Nie wiem tylko czy w czasie ewaluacji zmiennej. Te komunikaty o spóźnionej odpowiedzi mnie zastanawiają.

2

Zakładam, że w momencie renderowania nie wszystkie zmienne mają wartość, bo jeszcze nie dostały zwrotki z API.
Z dokumentacji Microsoftu

Asynchronous actions performed in lifecycle events might not have completed before a component is rendered.

Rozwiązanie to obsługa nulli, np:
https://learn.microsoft.com/en-us/aspnet/core/blazor/components/lifecycle?view=aspnetcore-8.0#handle-incomplete-async-actions-at-render

0
AbcDefGhi napisał(a):

...[CIACH!]

Widzę tu dużo wykrzykników nastawiane. Jesteś pewien, że w tych polach nie ma nulla? Najlepiej postawić breakpoint'a po załadowaniu danych i przejrzeć czy wszystkie pola w każdym wierszu są uzupełnione.

A najprościej to zakomentuj najpierw jeden fragment i zobacz czy działa bez niego a potem drugi fragment. Wtedy chociaż będziesz wiedzieć czy to to miejsce.

Miałeś rację. Problem jest w wyrażeniach z wykrzyknikami, odwołaniami przez klucz obcy np, @trip!.SeasonCityTrip!.Id . To kolejny problem ale przynajmniej wiem gdzie szukać. Dzięki.

5

Po co używasz

#nullable enable

Skoro później zamiast skorzystać z ułatwienia jakie Ci to daje, wyciszasz wszystkie błędy związane z nullami i masz wyjątki w runtime?
To trochę tak, jakbyś przed startem w wyścigu kolarskim kupił sobie najlepszy na świecie rower i jednocześnie uciął nogi.

1

Miałem podobny problem co ty gdy zaczynałem używać nullable. Nie chodzi o to żeby zbić warring do zera, na pałe. Chodzi o to zeby wychwycić nulle porawnie. Najlepiej próbuj nigdy nie uzywać tego operatora. Jedynym wyjątkiem jest systuacja gdy np. framework sie inicjalizuje, i nulla nie bedzie nigdy po inicjalizacja(w blazorze jest taki case) tylko w tym przypdaku mozna dać !. w zadnym innym

0

ApiSeasonCityService.GetSeasonCityTripOpenedForRegistration może zwrócić null.

1 użytkowników online, w tym zalogowanych: 0, gości: 1