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.
Du kan ta igen passet på egen hand. Gör i den här ordningen, och räkna med ungefär två timmar:
- 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.
- Gör avsnitt 3 och 4: lägg
till en sida och en menypost. Prova att ta bort
@pageoch se 404:an. Klassen gjorde exakt det tillsammans. - Gör guiden steg 3 till 8. Det är samma arbete som klassen hade 30 minuter på sig att påbörja.
- 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.
| Ordning | Fil | Ansvar | När den körs |
|---|---|---|---|
| 1 | Program.cs |
Startar webbservern och bestämmer vad den kan svara på | En gång, vid uppstart |
| 2 | Components/App.razor |
Själva HTML-dokumentet: html, head och body |
Vid varje förfrågan |
| 3 | Components/Routes.razor |
Matchar adressen mot rätt sida. Ingen träff ger NotFound | Vid varje förfrågan |
| 4 | Components/Layout/MainLayout.razor |
Ramen alla sidor delar: meny och innehållsyta | Vid varje förfrågan |
| 5 | Components/Pages/… |
Sidan själv. Fyller @Body i layouten |
Vid varje förfrågan |
| 6 | wwwroot/app.css |
Utseendet | Eget anrop, efter att HTML:en kommit fram |
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:
AddRazorComponents()— anmäler att projektet har Razor-komponenter.MapRazorComponents<App>()— vid varje förfrågan, börja iApp. Det är raden som kopplar ihop webbservern med din kod.app.Run()— nu lyssnar servern. Terminalen står kvar och väntar.
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.
//
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 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>.
lang="sv"— vilket språk texten är skriven på. En skärmläsare väljer uttal med det.<meta charset="utf-8" />— raden som gör att åäö fungerar.<base href="/" />— därför skrivs menylänkar utan inledande snedstreck.<Routes />— här stoppas den valda sidan in.@Assets[…]— ger filen ett versionsnummer så att webbläsaren inte visar en gammal cachad stilmall.
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.
DefaultLayout— vilken ram sidorna får om de inte säger annat.NotFoundPage— vad som visas när ingenting matchar. Det är den som gav 404 på/finns-inte.FocusOnNavigate— flyttar tangentbordsfokus till<h1>vid sidbyte, så att den som navigerar utan mus hamnar rätt.
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.
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.
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>
NavLinkär en komponent, inte<a>. Den märker själv när den pekar på sidan du står på och markerar sig.href="adressen"utan snedstreck först — på grund av<base href="/" />i App.razor.
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
| Symptom | Orsak | Åtgärd |
|---|---|---|
| Ny sida ger 404 | @page saknas eller är felstavad |
Första raden ska vara @page "/adressen" |
| Sidan finns men saknar meny | Filen ligger utanför Components/Pages/ |
Flytta filen dit |
| Menylänken går till fel adress | Snedstreck först i href |
Skriv href="adressen", inte href="/adressen" |
| Start markerad på alla sidor | Match="NavLinkMatch.All" saknas |
Lägg tillbaka den på startsidans NavLink |
RZ1006 eller oväntat Razor-fel | Ett @ i vanlig text, till exempel i en mejladress |
Skriv @@ för ett bokstavligt snabel-a |
| CSS-ändringen syns inte | Webblä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
| Ord | Betyder |
|---|---|
| renderingskedjan | Ordningen filerna körs i när en förfrågan blir en sida. |
| pipeline | Raderna i Program.cs som varje förfrågan passerar, i tur och ordning. |
| routing | Att matcha en adress mot rätt sida. |
| router | Komponenten i Routes.razor som gör matchningen. |
| layout | Ramen som alla sidor delar. Sidan stoppas in i @Body. |
| @Body | Platsen i layouten där den valda sidan hamnar. |
| NavLink | Länkkomponent som själv markerar sig när den pekar på sidan du står på. |
| NavLinkMatch.All | Kräver att hela adressen stämmer, inte bara början. Behövs på startsidans länk. |
| base href | Raden i App.razor som gör att länkar kan skrivas utan inledande snedstreck. |
| wwwroot | Mappen med filer som skickas ut som de är: CSS, bilder, ikoner. |
| statisk fil | En fil som levereras oförändrad, utan att kod kört. |
| NotFound | Sidan som visas när ingen route matchar. Ger statuskod 404. |