ASP.NET Core rammeværket gør det muligt at udvikle komplekse og dynamiske brugergrænseflader ved at bruge flere tilgange, herunder Razor Pages, MVC og Blazor. Hver af disse tilgange har sine egne styrker og anvendelser, hvilket giver udviklere fleksibilitet i at vælge den bedste løsning til deres specifikke behov. Når en bruger foretager en anmodning, som eksempelvis ved at indsende en formular, begynder ASP.NET Core at behandle denne anmodning ved at knytte data til den relevante model. Dette bind af data sker via egenskaber i den relevante modelklasse, og hvis der er fejl i navnene på disse egenskaber, kan nogle af dem mangle værdier. Dette understreger vigtigheden af at have korrekt navn på datafelterne for at sikre, at de bliver korrekt behandlet.
ASP.NET Core tilbyder en effektiv måde at binde data på via såkaldte "tag helpers", som forenkler processen med at tilføje valideringsattributter til modelklasser. Denne form for bindning gør det muligt at validere data, hvilket er essentielt i enhver form for dynamisk UI-udvikling. MVC-mønsteret (Model-View-Controller) giver yderligere muligheder for at skabe komplekse applikationer, hvor forretningslogik og dynamiske visninger kan styres præcist efter behov. Dette gør det muligt for udviklere at skille sig af med komplekse UI-layouts og bruge de rigtige værktøjer til den rigtige opgave.
Når vi ser på Blazor og dets integration med JavaScript-frameworks, åbner det op for endnu flere muligheder for at bygge dynamiske brugergrænseflader. Blazor er en relativt ny teknologi, som bruger WebAssembly-standarden og tilbyder en fleksibel og kraftfuld ramme for at bygge webapplikationer. Blazor giver udviklere mulighed for at bygge en applikation, der kører på både server og klient ved at bruge C#, hvilket skaber en stærk kobling mellem serverlogik og frontend-rendering.
WebAssembly er et væsentligt element i denne sammenhæng, da det giver mulighed for at køre kode direkte i browseren med en høj ydelse og lav starttid. Når en Blazor-applikation bruges i en browser, kræves det, at både de nødvendige .NET runtime-filer og de komplierede applikationssamlinger hentes. Denne tilgang gør det muligt at manipulere DOM (Document Object Model) og foretage browser API-opkald effektivt og sikkert. Det betyder, at Blazor-applikationer kan køre uden at kræve en stor initial belastning, hvilket giver en bedre brugeroplevelse.
Blazor Server repræsenterer en anden tilgang, hvor UI’en behandles på serveren i stedet for at blive rendere direkte i browseren. Denne model bruger SignalR-teknologi til at opdatere UI’en i realtid gennem en vedvarende serverforbindelse. Når brugeren interagerer med applikationen, evaluerer Blazor komponentgrafen og sender ændringer til klienten som en binær repræsentation. Denne tilgang gør det muligt for applikationen at reagere hurtigt på brugerinput og giver samtidig mulighed for at opretholde en høj grad af serverstyring og sikkerhed.
Blazor er bygget omkring komponenter, der minder om dem, vi ser i moderne JavaScript-frameworks som Angular. Hver komponent består af en eller flere UI-elementer, der er udviklet til et specifikt formål. Disse komponenter er genanvendelige og gør det muligt at opdele komplekse UI’er i mindre, mere håndterbare stykker. Alle Blazor-komponenter er gemt i filer med .razor-udvidelsen, som integrerer både Razor-syntaxen og C#-koden. Ved at bruge denne struktur kan udviklere opnå høj grad af modularitet og genbrugelighed i deres applikationer.
Med Blazor får vi desuden nye muligheder for at forbedre brugeroplevelsen ved at bruge den nye render-interaktive tilstand. Når en Blazor-applikation indlæses, renderes HTML’en først på serveren, hvilket giver en fuldt funktionel side, som brugeren kan interagere med med det samme. Når Blazor-frameworket er indlæst på klientsiden, bliver applikationen gradvist opdateret til en interaktiv applikation. Denne proces optimerer tid til interaktivitet og giver brugeren en mere flydende oplevelse, da de ikke skal vente på, at hele applikationen indlæses, før de kan begynde at interagere med den.
En vigtig overvejelse ved brug af Blazor og JavaScript-frameworks er, at begge teknologier har deres egne fordele og ulemper, afhængigt af applikationens behov. For udviklere, der er vant til JavaScript, kan Blazor tilbyde et velkendt miljø med stærk understøttelse af C#, som kan udnytte .NETs omfattende biblioteker og funktioner. På den anden side tilbyder JavaScript-baserede løsninger som Angular og React en mere etableret og udbredt teknologi med stor community-opbakning og et væld af færdige komponenter. Valget mellem Blazor og JavaScript-frameworks bør derfor afhænge af applikationens krav og udviklerens erfaring med de enkelte teknologier.
Når du udvikler med Blazor, er det også vigtigt at forstå, hvordan interaktiviteten og renderingen fungerer på tværs af server- og klientsiden. Blazor Server giver en enklere arkitektur med server-drevet rendering, mens Blazor WebAssembly kræver, at både runtime og applikationssamlinger hentes til klienten. For at få den bedste brugeroplevelse er det afgørende at vælge den rette model baseret på projektets kompleksitet og den ønskede interaktivitet.
Hvordan fungerer middleware i ASP.NET Core 9?
Middleware er hjertet af anmodnings- og responsforløbet i ASP.NET Core 9. Det udgør en række komponenter, som hver især får mulighed for at læse, ændre eller stoppe behandlingen af en HTTP-anmodning, før den sendes videre i kæden. Denne struktur giver en bemærkelsesværdig fleksibilitet og magt til udviklere, og forståelsen af den er afgørende for at bygge robuste, skalerbare og vedligeholdelige webapplikationer.
Når en anmodning ankommer til en ASP.NET Core 9-applikation, går den først gennem det definerede middleware-pipeline. Hver komponent i denne pipeline modtager anmodningen og får valget mellem at modificere den, sende den videre, eller stoppe hele processen. Dette kaldes "short-circuiting", og det anvendes typisk i sikkerhedsrelaterede situationer, hvor f.eks. en uautoriseret anmodning afvises tidligt, før yderligere ressourcer bliver brugt.
Tre centrale metoder bruges til at definere middleware-komponenter i ASP.NET Core 9: Run, Map og Use.
Run definerer en afsluttende middleware, som ikke kalder nogen næste komponent. Dette betyder, at det, der udføres her, er den endelige håndtering af anmodningen. F.eks. returnere en statisk tekst eller en fejlbesked. Map bruges til at skabe forgreninger i pipelinen, typisk afhængig af stien i URL’en. En bestemt sti som /SomeRoute kan have sin egen pipeline med middleware, som kun køres for anmodninger, der matcher netop den sti. Use er den mest fleksible og anvendte metode, da den tillader middleware at udføre logik før og efter, at næste komponent i kæden kaldes — typisk ved hjælp af await next().
Midlertidig håndtering af anmodningen giver mulighed for logning, ændring af headers, validering eller caching. Når anmodningen når bunden af kæden og behandles færdig, returneres svaret op gennem den samme kæde — i omvendt rækkefølge. Det betyder, at middleware også kan fange og ændre svaret på vej tilbage. Dette dobbeltsidede kontrolforløb er en af de mest elegante egenskaber ved ASP.NET Core-arkitekturen.
Et simpelt eksempel er logning. En middleware-komponent kan fange anmodningen, skrive anmodningsmetode og sti til konsollen, kalde næste middleware, og derefter, når svaret kommer tilbage, skrive statuskoden. På denne måde har udvikleren både indsigt og kontrol over hele forløbet. Dette er fundamentalt i moderne systemovervågning og optimering.
Ved at oprette egne middleware-klasser kan udviklere strukturere deres kode og genbruge logik på tværs af applikationen. Dette forbedrer testbarhed og kodevedligeholdelse. Middleware kan registreres globalt i Program.cs, hvilket giver mulighed for central styring af applikationens adfærd.
En vigtig faktor at forstå er rækkefølgen, hvori middleware-komponenterne registreres. Da pipelinen behandles sekventielt, og svarene returneres i omvendt rækkefølge, kan en forkert rækkefølge føre til uventede bivirkninger eller tabt funktionalitet. Eksempelvis skal autentificering næsten altid ske tidligt i pipelinen, mens fejlhåndtering placeres bedst omkring hele kæden, så alle potentielle un
Hvordan pakker man en applikation i en container?
En container er et selvstændigt, eksekverbart softwarepakke, der indeholder alt, hvad der er nødvendigt for at køre et stykke software. Denne teknologi har revolutioneret måden, vi håndterer applikationer på, og tilbyder mange fordele i forhold til traditionelle metoder. En af de største fordele ved containere er deres evne til at skabe et isoleret og konsistent runtime-miljø, som fungerer på tværs af forskellige platforme og systemer. Det betyder, at applikationen opfører sig ens, uanset om den kører på en udviklingsmaskine, en testserver eller i produktion.
Containere adskiller sig fra traditionelle virtuelle maskiner (VM'er), som er softwareemuleringer af fysiske computere, og som kræver et komplet operativsystem for at fungere. Containerteknologi, derimod, anvender et mere letvægtsapproach ved at dele systemressourcer såsom netværk og processorkraft med værtsmaskinen, hvilket gør containere langt mere ressourceeffektive end VM'er. Containers skal kun bruge et runtime-miljø i stedet for et fuldt operativsystem. Det er denne forskel, der gør containere til et attraktivt valg, især i cloud-miljøer, hvor skalerbarhed og effektiv ressourceanvendelse er af stor betydning.
Docker er den mest kendte og brugte containerplatform, der giver os de nødvendige værktøjer til at bygge, implementere og administrere containere. Docker består af tre hovedkomponenter: Docker Engine, Docker CLI og Docker Hub. Docker Engine er det runtime, der styrer containere, mens Docker CLI er kommandolinjeinterfacet, som bruges til at interagere med Docker. Docker Hub fungerer som en cloud-baseret lagerplads, hvor man kan dele og hente Docker images – de grundlæggende byggesten, som containere er baseret på.
Et Docker image kan sammenlignes med et fotografi af applikationens nuværende version, og det indeholder alle nødvendige filer og afhængigheder for at kunne køre applikationen. Det er ud fra disse images, at containere oprettes. Dockerfile, en simpel tekstfil, beskriver hvordan disse images bygges og konfigureres. Dockerfile angiver for eksempel, hvilket base-image der skal anvendes, hvilke applikationsfiler der skal inkluderes, og hvordan eventuelle afhængigheder skal installeres.
Når du skal pakke en applikation i en container, som for eksempel en UrlShortener applikation, skal du først sørge for, at Docker Engine er installeret på din maskine. Herefter opretter du et Dockerfile, som beskriver, hvordan applikationen skal bygges og pakkes ind i en container. I tilfældet med UrlShortener applikationen vil Dockerfile se ud som følger:
Når denne fil er oprettet, kan den bruges til at bygge et image, som derefter kan bruges til at oprette containere. Hver linje i Dockerfile’en har sin funktion. For eksempel angiver linjen FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base, at basen for containeren skal være et image, der indeholder runtime-miljøet for ASP.NET Core 8.0-applikationer. Derudover angiver WORKDIR /app, at arbejdsbiblioteket i containeren skal være /app, hvilket betyder, at alle efterfølgende operationer vil blive udført i denne mappe.
Det er vigtigt at forstå, at containere og Docker ikke kun handler om effektiv ressourcebrug, men også om fleksibilitet og skalerbarhed. Docker understøtter flere container runtime-miljøer såsom containerd, CRI-O, runc og Podman, som giver udviklere forskellige muligheder afhængig af deres behov. Dette åbner op for en større grad af tilpasning og giver mulighed for at vælge den bedste løsning baseret på applikationens krav.
Det er også væsentligt at bemærke, at Docker ikke er den eneste mulighed på markedet. Andre container-runtime-løsninger, såsom Kubernetes, er blevet populær i store skala-distribueringer, da de tilbyder omfattende værktøjer til styring af containeriserede applikationer i store, distribuerede systemer.
For at sikre at din applikation fungerer optimalt i et containeriseret miljø, bør du tænke på containerens isolering som et fundamentalt aspekt. Hver container fungerer som en "black box", hvor applikationen kører isoleret fra andre containere og værtsystemet. Denne isolation er vigtig, da den forhindrer konflikter mellem applikationer, der kan opstå, når de deler systemressourcer. Samtidig muliggør den fleksibilitet i forhold til at kunne deployere applikationen på forskellige platforme uden at bekymre sig om miljøspecifikke problemer.
En vigtig faktor i containerisering er også håndtering af afhængigheder. Når du bygger en container, er det vigtigt at sikre, at alle nødvendige biblioteker, framework-versioner og værktøjer er inkluderet i containeren, så applikationen kan køre problemfrit uden at skulle installere yderligere software på værtsmaskinen. Dockerfile’en gør dette muligt ved at angive de præcise instruktioner for, hvad der skal installeres og hvordan applikationen skal bygges.
Det er også en god idé at anvende versionsstyring af de Docker images, du arbejder med. Ved at bruge tags i Docker Hub eller ved at versionere dine egne images kan du nemt holde styr på ændringer og sikre, at du altid bruger den nyeste, stabile version af dine containeriserede applikationer. Dette kan være med til at undgå problemer, der opstår ved inkompatibilitet eller opdateringsfejl.
Hvordan kan CI/CD Pipeline sikre pålidelig deployment og automatisere processer effektivt?
Selvom CD-pipelinen er en automatiseret proces, der betyder, at den kan publicere nye versioner af en applikation i forskellige miljøer automatisk, er det muligt at etablere godkendelsesflows, hvor ansvarlige personer for hvert miljø kan vælge, om de godkender en deployment. Aktiviteterne omkring godkendelsen udløser den automatiske deployment-flow eller annullerer den, alt efter behov. Godkendelsesmetoden bringer compliance-fordele og giver teams fuld kontrol over deployment-flowet i visse miljøer.
Afhængigt af leveringsflowet i hver organisation er der ofte behov for at gennemgå deployment-processen, især i produktionsmiljøer. Denne tilgang skaber en automatiseret kommunikationsproces mellem CD-pipelinen og de personer, der gennemgår deployment. Værktøjer som GitHub, Azure DevOps og GitLab har mekanismer, der gør det muligt at konfigurere sådanne godkendelsesflows. For eksempel kan du lære mere om deploymentsgennemgang gennem GitHub Actions på https://docs.github.com/en/actions/managing-workflow-runs/reviewing-deployments.
CI og CD er stærke metoder til at automatisere processer, så vores applikationer konstant kan leveres til forskellige miljøer med kvalitet for øje. Dette gør det muligt at levere nye versioner af applikationer flere gange om dagen og samtidig hurtigt kunne tilbyde rettelser og rollback i de forskellige miljøer, hvis det bliver nødvendigt.
For at demonstrere CI/CD i praksis vil vi bruge GitHub Actions til at automatisere processen med at generere og publicere et Docker-billede fra en UrlShortener-applikation. Sørg for, at du har installeret alt, der er nævnt i afsnittet "Tekniske krav", så du kan følge de trin, der beskrives her. For at automatisere CI/CD-processen skal vi gennemføre følgende trin:
-
Konfigurere hemmeligheder i GitHub-repositoriet.
-
Oprette GitHub Actions.
-
Aktivere GitHub Actions ved hver push-begivenhed, der sendes til repositoriet.
-
Bygge et Docker-billede.
-
Publicere det oprettede billede til Docker Hub.
-
Køre det tidligere oprettede Docker-billede på den lokale maskine.
Inden du begynder at automatisere, skal du forstå det grundlæggende i GitHub Actions.
GitHub Actions er et automatiseringsværktøj, der er bygget ind i GitHub og gør det muligt at oprette, administrere og køre arbejdsprocesser direkte i dit repository. Actions, som det er almindeligt kaldet, kan udløses af forskellige begivenheder, såsom kodeindsendelser, pull-requests eller tidsudløb. GitHub Actions oprettes ved hjælp af YAML-filstrukturen, som findes i .github/workflows-mappen i bogen's GitHub-repository.
En YAML (YAML Ain't Markup Language) fil er et menneskelæsbart datastandard, der ofte anvendes til konfigurationsfiler og udveksling af data mellem programmeringssprog med forskellige datastrukturer. YAML-filer bruger indrykning til at angive struktur, hvilket gør dem lette at læse og skrive. Det er ofte brugt i scenarier, hvor konfiguration skal være menneskelæselig og let at analysere af maskiner, såsom i CI/CD-pipelines, cloud-opsætningsfiler og applikationskonfigurationsindstillinger.
Når du arbejder med GitHub Actions, definerer YAML-filer workflows, der automatiserer processer som opbygning, test og deployment af applikationer. GitHub Actions giver mange muligheder for at automatisere processer, ikke kun begrænset til CI/CD-kontekster. Når du har forstået, hvordan GitHub Actions fungerer, kan du begynde at konfigurere dit repository og oprette dine første actions.
For at automatisere oprettelsen og publiceringen af et Docker-billede gennem GitHub Actions er det vigtigt at forstå, hvordan den pipeline, vi opretter, fungerer. I tidligere sektioner lærte vi om grundprincipperne i containerstrategien ved hjælp af Docker og brugte Docker’s multi-stage build til at implementere denne proces. Multi-stage build indeholder alle nødvendige trin til at generere en applikation og til sidst skabe et billede, der er klar til brug. Under pipeline-flowet er der nogle opkald til Docker Hub, som er det offentlige containerregister, vi bruger til at pakke URLShortener-applikationen.
For at kunne publicere et Docker-billede til et offentligt eller privat container-register, skal der udføres en godkendelse. I Docker Hub sker denne godkendelse med brugernavn og adgangskode. Da disse oplysninger er følsomme, bør de ikke indsættes direkte i en GitHub Actions YAML-fil, især ikke hvis repositoriet er offentligt. Den bedste praksis er at administrere disse legitimationsoplysninger sikkert ved hjælp af Secrets. Følg disse trin for at tilføje de nødvendige secrets:
-
Gå til dit ASP.NET-8.0-Core-Essentials repository via din GitHub-bruger.
-
Gå til "Settings"-fanen.
-
I side-menuen, gå til "Secrets and variables | Actions".
-
Klik på "New repository secret"-knappen.
-
Indtast "DOCKER_HUB_USERNAME" i "Name"-feltet.
-
Indtast dit Docker Hub-brugernavn i "Secret"-feltet.
-
Klik på "Add Secret"-knappen.
-
Gentag for at tilføje "DOCKER_HUB_PASSWORD".
Når secrets er blevet tilføjet, kan GitHub Actions få adgang til dem under kørsel.
Dernæst skal vi oprette CI/CD-pipelinen. Vi har nu lært, hvordan man administrerer Docker Hub-legitimationsoplysninger sikkert, hvilket vi har brug for at kunne godkende gennem pipelinen og sende det nyligt oprettede billede. I GitHub-repositoriet skal du nu få adgang til "Actions"-fanen. Der findes flere pipeline-skabeloner, som er klar til brug, og som kan være et godt udgangspunkt for forskellige applikationstyper.
Det er essentielt at forstå de muligheder og fleksibilitet, GitHub Actions giver, ikke kun for CI/CD-pipelines, men også til enhver form for automatisering af workflows i softwareudvikling. Den integrerede tilgang til versionering, test og deployment betyder, at fejl kan rettes hurtigt, og nye versioner kan rulles ud effektivt uden manuel indgriben. Samtidig bør man altid overveje, hvordan man håndterer sikkerhed og overholdelse, især i produktionsmiljøer, hvor godkendelsesflows er nødvendige for at sikre kvaliteten af hver deployment. Denne automatisering skaber grundlaget for en robust og skalerbar DevOps-struktur, der kan håndtere konstant ændrende krav.
Hvordan skaleres, stoppes og overvåges cloud-native applikationer effektivt?
Når en cloud-native applikation skal skaleres, sker det ofte ved at skabe en ny containerinstans. Denne instans startes hurtigt op, hvilket sikrer, at den er klar til at håndtere forespørgsler næsten øjeblikkeligt. Når instansen er operationel, begynder load balanceren automatisk at fordele trafik til den. Dette automatiske scale-out-mønster muliggør responsivitet under øget belastning og sikrer samtidig høj tilgængelighed.
I det modsatte tilfælde – ved scale-in eller deployment af en ny version – stopper load balanceren med at sende nye anmodninger til den gamle instans. For at undgå afbrudte transaktioner anvendes en strategi for graceful shutdown, hvor den gamle instans får lov til at færdiggøre igangværende anmodninger før nedlukning. Ressourcer frigives først, når alle opgaver er afsluttet, hvorefter instansen bliver termineret.
I ASP.NET Core 9 kan en graceful shutdown implementeres gennem håndtering af cancellation tokens. I praksis betyder det, at man registrerer callbacks på applikationens stopbegivenheder og udfører nødvendige oprydningsopgaver, såsom lukning af forbindelser, logning og oprydning af afhængigheder. Dette skaber en robust og forudsigelig nedlukningsproces og forhindrer datatab eller ufuldstændige transaktioner.
Men robusthed handler ikke kun om selve driften. Der bør også være en ensartethed mellem udviklings- og produktionsmiljøer – dev/prod parity. Den klassiske undskyldning "It works on my machine!" opstår netop, når denne ensartethed mangler. Forskelle i CPU-ressourcer, hukommelse, tilladelser eller netværkskonfigurationer kan føre til fejl, der er svære at reproducere. Derfor bør udviklingsteams investere i Infrastructure as Code-værktøjer som Terraform og Bicep. Disse sikrer, at miljøerne er konsistente, automatiserede og versionerbare, hvilket minimerer miljørelaterede fejl og øger sikkerheden.
Containerisering spiller også en central rolle her. Ved at containerisere applikationer sikres det, at de opfører sig ens på tværs af forskellige miljøer – om det så er udvikling, test eller produktion. Konsekvens og isolation i miljøer reducerer risikoen for sideeffekter og forbedrer teamsamarbejdet.
Logs er et andet centralt aspekt i en cloud-native arkitektur. Tidligere blev logs betragtet som statiske tekstfiler, kun brugt ved fejlfinding. I dag anskues logs som en kontinuerlig strøm af hændelser, som skal behandles og analyseres i realtid. I stedet for at gemme logs lokalt, bør man benytte dedikerede overvågningssystemer som Elasticsearch, Azure Monitor, Datadog, eller open source-værktøjer som Prometheus og Grafana.
Ved at analysere logstrømme kan teams visualisere trends, opdage flaskehalse og træffe informerede beslutninger om automatiseret skalering. Logs giver også indsigt i fejladfærd og understøtter sikkerheds- og auditkrav i distribuerede systemer.
Det er dog vigtigt, at applikationen ikke bliver afhængig af specifikke log-instrumenteringsværktøjer. Mange løsninger kræver SDK-integrationer, hvilket kan føre til en høj grad af kobling. Her kommer OpenTelemetry ind som en central løsning. Det er et open source-projekt under CNCF, som tilbyder en standardiseret måde at indsamle, processere og eksportere telemetridata – herunder logs, traces og metrics. Ved at anvende OpenTel
Hvordan Immanent Kritik Kan Modarbejde Alt-Right: En Undersøgelse af Teori og Praxis
Hvordan skal man introducere en taler korrekt og værdigt?
Hvordan kan TypeScript forbedre dit udviklingsarbejde?
Hvordan Risici i Forsyningskæder Kan Simuleres ved Hjælp af Monte Carlo

Deutsch
Francais
Nederlands
Svenska
Norsk
Dansk
Suomi
Espanol
Italiano
Portugues
Magyar
Polski
Cestina
Русский