← Område 3 Lektion 21 · Sex komponenter som går sönder Poängen

Webbserverprogrammering 1 · område 3 · lektion 21

Sex komponenter som går sönder

Sex fel, tio filer. Alla sex kompilerar utan varning. Alla sex ger 500 när sidan öppnas. Det är hela poängen: i område 2 var felen röd text i editorn innan du hunnit köra. Här kopplas komponentparametrar ihop när sidan renderas, och då är kompilatorn för länge sedan klar.

Svara innan du läser vidare

Klassen fick de sex meddelandena projicerade utan koden och arbetade i par i tre minuter. Ge dig själv lika lång tid. Orsakerna i tabellen nedan ligger dolda tills du klickar på raden – de är inte värda mycket förrän du har ett eget svar att jämföra med.

Vill du köra koden: lägg filerna i ditt projekts Components/Pages/ och gå till /fel/1 och så vidare. Fel6.razor och Fel6Igen.razor har med flit samma @page-adress – projektet bygger ändå.

1. De sex meddelandena

Klicka på en rad för att se orsaken. Meddelandena är avskrivna ur terminalen, inte ur minnet.

FelmeddelandetOrsaken
Object of type '…Stjarnor' does not have a property matching the name 'Etikett'. Sidan sätter en parameter som komponenten inte har. Stavfel, eller ett attribut som aldrig lades till.
Object of type '…Panel' does not have a property matching the name 'ChildContent'. Komponenten kallar sin RenderFragment för Innehall. Markup mellan taggarna hamnar alltid i ChildContent, och det namnet är inte fritt valt.
…has a property matching the name 'Text', but it does not have [Parameter], [CascadingParameter], or any other parameter-supplying attribute. Egenskapen finns, men [Parameter] saknas. Utan attributet är den privat för komponenten hur public den än är.
Object of type '…Fel4' does not have a property matching the name 'id'. Rutten heter {id:int}, egenskapen heter Nummer. Namnen måste stämma – stor eller liten bokstav spelar ingen roll, stavningen gör det.
Unable to set property 'id' … Unable to cast object of type 'System.String' to type 'System.Int32'. Rutten saknar :int. Allt som står i en adress är text tills du säger annat.
AmbiguousMatchException: The request matched multiple endpoints. Två komponenter har samma @page. Routern vet inte vilken som menas, och säger till först när någon besöker adressen.

2. Fel 1 – parametern som inte finns

Sidan på /fel/1:

@page "/fel/1"

<h1>Fel 1</h1>

<p>Betyget som stjärnor: <Stjarnor Varde="4" Etikett="fyra av fem" /></p>

Och komponenten den använder:

@* Hör till Fel1.razor. *@

<span>@Text()</span>

@code {
    [Parameter]
    public int Varde { get; set; }

    private string Text() => new string('*', Varde);
}

Rättningen: ta bort Etikett ur taggen, eller lägg till parametern i komponenten. Vilket som är rätt beror på vad du menade – och det är poängen: felmeddelandet talar om vad som saknas, inte vad du ville.

3. Fel 2 – ChildContent med fel namn

Sidan på /fel/2:

@page "/fel/2"

<h1>Fel 2</h1>

<Panel Rubrik="Om arkivet">
    <p>Sex filmer, alla utvalda för hand.</p>
</Panel>

Komponenten:

@* Hör till Fel2.razor. *@

<section class="ruta">
    <h2>@Rubrik</h2>
    @Innehall
</section>

@code {
    [Parameter]
    public string Rubrik { get; set; } = "";

    [Parameter]
    public RenderFragment? Innehall { get; set; }
}

Rättningen: döp om Innehall till ChildContent. Vill du behålla namnet måste den som använder komponenten skriva ut det som en tagg: <Innehall>…</Innehall>.

4. Fel 3 – egenskapen utan attribut

Sidan på /fel/3:

@page "/fel/3"

<h1>Fel 3</h1>

<p>Status: <Etikett Text="Tillgänglig" /></p>

Komponenten:

@* Hör till Fel3.razor. *@

<span class="etikett">@Text</span>

@code {
    public string Text { get; set; } = "";
}

Rättningen: [Parameter] på raden ovanför egenskapen. Det här är områdets vanligaste fel, och meddelandet är ovanligt hjälpsamt – det säger rakt ut att egenskapen finns men saknar attributet.

5. Fel 4 – ruttens namn

Sidan på /fel/4/7:

@page "/fel/4/{id:int}"

<h1>Fel 4</h1>

<p>Numret ur adressen: @Nummer</p>

@code {
    [Parameter]
    public int Nummer { get; set; }
}

Rättningen: döp egenskapen till Id, eller döp om rutten till {nummer:int}. Det ena eller det andra – namnen ska stämma.

6. Fel 5 – ruttens typ

Sidan på /fel/5/7. Lägg märke till att adressen innehåller ett tal och ändå kraschar:

@page "/fel/5/{id}"

<h1>Fel 5</h1>

<p>Numret ur adressen: @Id</p>

@code {
    [Parameter]
    public int Id { get; set; }
}

Rättningen: {id:int} i stället för {id}.

Talet är ett tal – varför kraschar det ändå?

För att adressen inte vet det. En URL är text, hela vägen. Utan :int lämnar routern över strängen "7", och Blazor försöker stoppa den i en int. Med :int gör routern omvandlingen åt dig – och matchar inte alls om det inte går.

7. Fel 6 – två sidor på samma adress

Två filer, båda med @page "/fel/6":

@page "/fel/6"

<h1>Fel 6</h1>

<p>Den här sidan visar arkivet.</p>
@page "/fel/6"

<h1>Fel 6, en gång till</h1>

<p>Den här sidan visar också arkivet.</p>

Rättningen: ta bort den ena, eller ge den en annan adress. Sök i projektet efter adressen – i verkliga projekt är det oftast en gammal sida som skulle ha tagits bort.

8. Poängen

Ordningen är avsiktlig. 1–3 handlar om parametrar: fel namn, fel namn på fel ställe, rätt namn utan attribut. 4–5 handlar om adressen: namnet och typen. 6 handlar om att två filer kan göra anspråk på samma sak utan att någon säger till förrän någon besöker sidan.

Frågan att landa i:

Varför säger inte kompilatorn något? Vad är det egentligen som händer när jag skriver <Betygsstjarnor Varde="4" />?

Svaret är att det inte är ett metodanrop. Det är en beskrivning som slås upp på namn när sidan byggs. Kompilatorn kontrollerar att koden går att översätta, inte att namnen finns – den kopplingen görs först i körtid.

Det är samma insikt som gör [Parameter] begriplig, och det är därför regeln i det här området lyder:

Ändrat en komponent? Öppna sidan. Inte bara dotnet build.