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.
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.
| Felmeddelandet | Orsaken |
|---|---|
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}.
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.