← Område 1 Referens · Projektets arkitektur Felsökning

Webbserverprogrammering 1 · område 1 · lektion 4

Projektets arkitektur: vilken fil gör vad

Sex filer gör om en förfrågan till en sida. Det här är den enda gång under kursen som hela kedjan gås igenom samlat — allt senare bygger på att den här bilden sitter.

Missade du lektionen?

Du kan ta igen passet på egen hand. Gör i den här ordningen, och räkna med ungefär två timmar:

  1. Läs kedjan och de sex filerna här. Ha ditt eget projekt öppet bredvid och leta upp varje fil medan du läser. Att bara läsa texten räcker inte — hela poängen är att du öppnar filerna.
  2. Gör avsnitt 3 och 4: lägg till en sida och en menypost. Prova att ta bort @page och se 404:an. Klassen gjorde exakt det tillsammans.
  3. Gör guiden steg 3 till 8. Det är samma arbete som klassen hade 30 minuter på sig att påbörja.
  4. Stäm av mot uppgiftens krav.

Fastnar du på vägen: skriv i itslearning samma dag i stället för att vänta till nästa pass. Inlämningen ligger onsdag 2 september.

1. Renderingskedjan

En förfrågan kommer in. Servern går genom filerna i den här ordningen och skickar tillbaka färdig HTML.

OrdningFilAnsvarNär den körs
1Program.cs Startar webbservern och bestämmer vad den kan svara på En gång, vid uppstart
2Components/App.razor Själva HTML-dokumentet: html, head och body Vid varje förfrågan
3Components/Routes.razor Matchar adressen mot rätt sida. Ingen träff ger NotFound Vid varje förfrågan
4Components/Layout/MainLayout.razor Ramen alla sidor delar: meny och innehållsyta Vid varje förfrågan
5Components/Pages/… Sidan själv. Fyller @Body i layouten Vid varje förfrågan
6wwwroot/app.css Utseendet Eget anrop, efter att HTML:en kommit fram
Den sista raden är den som förvånar

Stilmallen skickas inte som en del av HTML-sidan. Webbläsaren läser <link> i <head> och gör ett helt eget anrop efteråt. Öppna nätverksfliken (F12) och ladda om: två rader, en för sidan och en för app.css, med varsin statuskod. Samma resa som du lärde dig på lektion 2 — en gång per fil.

2. De sex filerna

Här är filerna ur referensprojektet, som de faktiskt ser ut. Leta upp motsvarigheten i ditt eget projekt medan du läser.

1. Program.cs — startar servern

using Webbresan.Components;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorComponents(); //.AddInteractiveServerComponents();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error", createScopeForErrors: true);
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}
app.UseStatusCodePagesWithReExecute("/not-found", createScopeForStatusCodePages: true);
app.UseHttpsRedirection();

app.UseAntiforgery();

app.MapStaticAssets();
app.MapRazorComponents<App>(); //.AddInteractiveServerRenderMode();

app.Run();

Körs en gång, när servern startar. Inte per förfrågan. Tre rader att känna igen:

Raderna däremellan är pipelinen: varje förfrågan passerar dem i tur och ordning. UseHttpsRedirection skickar http till https, MapStaticAssets levererar filer ur wwwroot. UseAntiforgery och UseStatusCodePagesWithReExecute kommer i område 5 och 7 — känn bara igen namnen nu.

De två raderna som slutar med //

Två rader har något bortkommenterat sist: //.AddInteractiveServerComponents(); och //.AddInteractiveServerRenderMode();. Allt efter // är en kommentar — C# läser det aldrig, och raderna gör alltså ingenting.

De står där för att visa vad som skulle behöva läggas till för att slå på interaktiv server: den första anmäler tjänsterna, den andra slår på renderingsläget. Ta bort snedstrecken och projektet skulle kunna köra interaktiva komponenter — och då går det inte längre att svara på frågan var körs den här raden? utan att titta efter. Det är precis den otydligheten kursen valt bort. Se renderingslägen.

Leta inte efter dem i ditt eget projekt. Där finns de inte alls. Skapade du projektet med -int None utelämnas raderna helt, och kommentaren här är tillagd med flit för att du ska se skillnaden. Ett projekt skapat med -int Server har dem på riktigt, utan snedstreck.

Ordningen är beteendet

Ordningen i den här filen är ordningen sakerna sker i. Flyttar du en rad ändras vad som händer. Det är inte en lista med inställningar, det är ett schema.

2. Components/App.razor — HTML-dokumentet

<!DOCTYPE html>
<html lang="sv">

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <base href="/" />
    <ResourcePreloader />
    <link rel="stylesheet" href="@Assets["lib/bootstrap/dist/css/bootstrap.min.css"]" />
    <link rel="stylesheet" href="@Assets["app.css"]" />
    <link rel="stylesheet" href="@Assets["Webbresan.styles.css"]" />
    <ImportMap />
    <link rel="icon" type="image/png" href="favicon.png" />
    <HeadOutlet />
</head>

<body>
    <Routes />
    <script src="@Assets["_framework/blazor.web.js"]"></script>
</body>

</html>

Här finns <html>, <head> och <body> — en enda gång i hela projektet. Enskilda sidor innehåller aldrig <html>.

charset och lang är inte samma sak

charset handlar om tecken: hur bytes tolkas, och det är den raden som gör att ö inte blir ö. lang handlar om språk. En sida kan visa Å Ä Ö helt rätt och ändå läsas upp på engelska. Mallen skriver lang="en" — kontrollera din egen fil.

3. Components/Routes.razor — väljer sida

<Router AppAssembly="typeof(Program).Assembly" NotFoundPage="typeof(Pages.NotFound)">
    <Found Context="routeData">
        <RouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)" />
        <FocusOnNavigate RouteData="routeData" Selector="h1" />
    </Found>
</Router>

Routern letar igenom projektet efter komponenter med @page och matchar adressen mot dem.

4. Components/Layout/MainLayout.razor — ramen

@inherits LayoutComponentBase

<div class="page">
    <div class="sidebar">
        <NavMenu />
    </div>

    <main>
        <div class="top-row px-4">
            <a href="https://learn.microsoft.com/aspnet/core/" target="_blank">About</a>
        </div>

        <article class="content px-4">
            @Body
        </article>
    </main>
</div>

@Body är hålet där sidan hamnar. Allt annat är samma på alla sidor — det är därför menyn bara skrivs en gång.

5. Components/Pages/Home.razor — sidan

Sidan bidrar bara med sitt eget innehåll. Den innehåller inte <html>, <head> eller menyn — de kommer från App.razor och MainLayout. Komponentens tre delar står på referenssidan för lektion 3, och hela startsidans kod finns i guiden steg 3.

6. wwwroot/app.css — utseendet

Skickas som en egen fil, efter HTML:en, på webbläsarens eget initiativ. Se notisen om nätverksfliken ovan. Koden du lägger till här finns i guiden steg 8.

Prova själv

Kan du säga kedjan utan att titta? Program.cs → App.razor → Routes.razor → MainLayout.razor → sidan, och app.css vid sidan om. Går det utan hjälp har du passets viktigaste mål i hamn.

3. Lägga till en egen sida

Skapa en fil i Components/Pages/. Namnet på filen spelar ingen roll för adressen — det är @page som bestämmer den.

@page "/adressen"

<PageTitle>Adressen – Webbresan</PageTitle>

<h1>Steg 1 och 2: adressen och DNS</h1>

<p>Här kommer förklaringen.</p>

Spara, starta om servern och gå till /adressen.

Gör det här en gång, med flit

Ta bort @page-raden och ladda om. Sidan ger 404. Utan @page är filen en byggsten, inte en sida — routern hittar den inte. Lägg tillbaka raden. Det här är den vanligaste felkällan i uppgiften, och den sitter bättre om du framkallat den själv en gång.

4. Menyn

Öppna Components/Layout/NavMenu.razor och lägg till posten:

<div class="nav-item px-3">
    <NavLink class="nav-link" href="adressen">Adressen</NavLink>
</div>

Startsidans länk behöver ett tillägg till:

<div class="nav-item px-3">
    <NavLink class="nav-link" href="" Match="NavLinkMatch.All">Start</NavLink>
</div>

Match="NavLinkMatch.All" behövs bara där. Utan den skulle länken till "" räknas som aktiv på alla sidor, eftersom varje adress börjar med /. Ta bort den och ladda om, så ser du det.

5. Felsökning

Felen från det här momentet. Slå upp symptomet innan du fastnar.

7 rader

SymptomOrsakÅtgärd
Ny sida ger 404@page saknas eller är felstavad Första raden ska vara @page "/adressen"
Sidan finns men saknar menyFilen ligger utanför Components/Pages/ Flytta filen dit
Menylänken går till fel adressSnedstreck först i href Skriv href="adressen", inte href="/adressen"
Start markerad på alla sidorMatch="NavLinkMatch.All" saknas Lägg tillbaka den på startsidans NavLink
RZ1006 eller oväntat Razor-felEtt @ i vanlig text, till exempel i en mejladress Skriv @@ för ett bokstavligt snabel-a
CSS-ändringen syns inteWebbläsaren cachar stilmallen Ctrl+F5
Sidan är tom men inget fel visas@code-blocket kraschade tyst Titta i terminalen där dotnet run körs, inte i webbläsaren

6. Orden

Orden från det här passet. De används i uppgiften utan förklaring.

Ordträning

OrdBetyder
renderingskedjanOrdningen filerna körs i när en förfrågan blir en sida.
pipelineRaderna i Program.cs som varje förfrågan passerar, i tur och ordning.
routingAtt matcha en adress mot rätt sida.
routerKomponenten i Routes.razor som gör matchningen.
layoutRamen som alla sidor delar. Sidan stoppas in i @Body.
@BodyPlatsen i layouten där den valda sidan hamnar.
NavLinkLänkkomponent som själv markerar sig när den pekar på sidan du står på.
NavLinkMatch.AllKräver att hela adressen stämmer, inte bara början. Behövs på startsidans länk.
base hrefRaden i App.razor som gör att länkar kan skrivas utan inledande snedstreck.
wwwrootMappen med filer som skickas ut som de är: CSS, bilder, ikoner.
statisk filEn fil som levereras oförändrad, utan att kod kört.
NotFoundSidan som visas när ingen route matchar. Ger statuskod 404.