I moderne webudvikling er asynkrone operationer og håndtering af store datamængder en uundværlig del af udviklingsprocessen. Specielt når man arbejder med Blazor-applikationer, er det afgørende at forstå, hvordan man interagerer med eksterne tjenester som Web API'er og hvordan man korrekt håndterer og præsenterer data for brugeren. Denne tekst udforsker, hvordan Blazor arbejder med Web API-tjenester, især med fokus på hvordan man indlæser og viser employee-data og relaterede oplysninger som lande og byer.

Blazor er et kraftfuldt rammeværk fra Microsoft, der tillader udvikling af webapplikationer med C#. Det gør det muligt for udviklere at skrive interaktive webgrænseflader, der kan køre både på klienten og serveren. Når det kommer til at arbejde med data, især JSON-formatet, bliver det hurtigt nødvendigt at forstå, hvordan dataene hentes og håndteres effektivt.

Et godt eksempel på datahåndtering i Blazor ses i koden, der bliver brugt til at hente employee-data fra et Web API. I denne proces ser vi flere vigtige elementer, som det er nødvendigt at forstå.

Først oprettes der en HttpClient, som bruges til at oprette forbindelse til API'et. Denne klient konfigureres ved hjælp af en fabriksmetode (httpClientFactory.CreateClient), som gør det muligt at holde styr på instansiering og genbrug af klienten. Web API'et i dette tilfælde tilbyder flere ruter: én for medarbejdere (api/employees), én for lande (api/countries), og én for byer (api/cities). Disse ruter bliver tilgået asynkront ved hjælp af metoden GetFromJsonAsync, som gør det muligt at hente JSON-data og automatisk deserialisere dem til de ønskede objekter, herunder en liste af medarbejdere og oplysninger om lande og byer.

Håndtering af data i et Blazor-projekt kræver mere end bare at hente data. Der er flere overvejelser, der bør tages i betragtning. For det første skal vi sikre os, at dataene bliver håndteret korrekt, når de kommer fra serveren. Dette betyder blandt andet, at vi skal have en strategi for at håndtere store mængder data uden at forringe brugeroplevelsen. Her anvendes JSON-serialisering, hvor vi kan definere specifikke indstillinger såsom ReferenceHandler.Preserve for at undgå problemer med cirkulære referencer i JSON-objekterne.

Når dataene er blevet hentet og deserialiseret korrekt, bliver de gjort tilgængelige i applikationen. I koden ses, hvordan medarbejderne gemmes i en IQueryable<Employee>-variable, som giver mulighed for yderligere filtrering og sortering, hvis det er nødvendigt. For både lande og byer hentes der data og gemmes i arrays, som kan bruges til at præsentere valg i brugergrænsefladen.

En vigtig funktion, som bør nævnes, er metoden OnChange. Denne metode håndterer ændringer i brugerens input og giver mulighed for at opdatere dataene dynamisk. Hvis en bruger f.eks. vælger et bestemt land eller en by, kan man filtrere medarbejderne baseret på deres placering. Denne funktion er uundværlig i en interaktiv applikation, hvor brugerens input påvirker visningen af data i realtid.

Ud over de tekniske aspekter af datahåndtering i Blazor er det vigtigt at forstå, hvordan man sikrer en effektiv og brugervenlig grænseflade. Dette betyder blandt andet, at man skal have fokus på at optimere API-kald, sikre korrekt fejlbehandling og tilbyde brugeren en visuel feedback, når dataene bliver hentet eller der opstår fejl.

En god praksis i Blazor-applikationer er at gøre brug af asynkrone metoder som OnParametersSetAsync for at undgå at blokere brugergrænsefladen. Dette gør det muligt at hente data i baggrunden og opdatere visningen, når dataene er klar, uden at påvirke applikationens ydeevne. Når man arbejder med Web API-tjenester, bør man også overveje at implementere caching-teknikker for at reducere antallet af nødvendige API-kald og dermed forbedre applikationens hastighed og effektivitet.

En anden vigtig overvejelse er, hvordan man håndterer potentielle fejl. I kodeeksemplet er der en try-catch-blok, der fanger eventuelle undtagelser, som kan opstå under API-kaldet. Det er vigtigt at håndtere disse fejl på en hensigtsmæssig måde, så brugeren ikke bliver mødt med uforståelige fejlmeddelelser. En god fejlmeddelse giver både udvikleren og brugeren indsigt i, hvad der gik galt, og hvordan fejlen kan rettes.

I komplekse applikationer, der afhænger af mange API-kald, kan man overveje at implementere et system til at håndtere afhængigheder mellem dataene. For eksempel kan medarbejdere være afhængige af oplysninger om deres placering (land og by), så det er vigtigt at sikre, at disse data er tilgængelige, før medarbejderne vises i brugergrænsefladen.

Det er også vigtigt at huske, at selvom datahåndtering er et teknisk aspekt af udviklingen, så er brugeroplevelsen afgørende. Dataene skal præsenteres på en måde, der er let at forstå og bruge. Dette kan indebære at vise data på en overskuelig måde, med mulighed for at filtrere og søge på tværs af de forskellige oplysninger. Når applikationen håndterer store datamængder, er det også en god idé at overveje at implementere funktioner som uendelig scroll eller paginering for at forhindre, at hele datasættet bliver indlæst på én gang, hvilket kan hæmme performance.

Hvordan arbejder man med REST-klienter og sikrer webtjenester i ASP.NET Core Minimal API'er?

Når man arbejder med webtjenester i moderne applikationer, er det essentielt at kunne teste og interagere med dem effektivt. REST Client i Visual Studio Code tilbyder en brugervenlig måde at sende HTTP-anmodninger til webtjenester og modtage svar direkte i editoren. I denne guide vil vi gennemgå, hvordan man bruger REST Client til at oprette, opdatere, hente og slette data i en webtjeneste bygget med ASP.NET Core Minimal API'er, samtidig med at vi fokuserer på at sikre webtjenester og forstå grundlæggende sikkerhedsmekanismer som CORS og HTTP logging.

Først og fremmest skal REST Client-plugin'et være installeret i Visual Studio Code. Hvis du ikke allerede har installeret det, kan du gøre det via Extensions-sektionen i VS Code ved at søge efter "REST Client by Huachao Mao". Når du har installeret det, kan du begynde at interagere med din webtjeneste.

Oprettelse af HTTP-anmodninger

Start med at åbne dit foretrukne projekt i Visual Studio Code. Hvis du arbejder med en projektstruktur som Northwind.WebApi.Service, skal du sørge for, at webtjenesten kører korrekt, normalt under HTTPS-profilen. Opret derefter en mappe som f.eks. RestClientTests i din apps-services-net7 folder. I denne mappe kan du oprette en fil med navnet webapi-get-products.http. I denne fil skriver du en HTTP-anmodning for at hente de første ti produkter, der er på lager og ikke er udgået:

http
GET https://localhost:5091/api/products/

Når du sender denne anmodning, vil REST Client returnere et JSON-svar, der indeholder de første ti produkter, som opfylder disse betingelser. Ved at klikke på "Send Request" får du hurtigt indsigt i svarstrukturen og kan kontrollere om anmodningen er blevet behandlet korrekt.

For at udvide dine tests kan du tilføje flere anmodninger i samme fil, som f.eks. at hente produkter på en bestemt side eller med bestemte filtreringer. Anmodningerne kan også omfatte forskellige HTTP-metoder som POST, PUT og DELETE for at interagere med dataene:

  • POST anmodning for at tilføje et nyt produkt:

http
POST https://localhost:5091/api/products/ Content-Type: application/json { "productName": "Harry's Hamburgers", "supplierId": 7, "categoryId": 6, "quantityPerUnit": "6 per box", "unitPrice": 24.99, "unitsInStock": 0, "unitsOnOrder": 20, "reorderLevel": 10, "discontinued": false }
  • PUT anmodning for at opdatere et produkt:

http
PUT https://localhost:5091/api/products/81
Content-Type: application/json { "productName": "Harry's Hamburgers", "supplierId": 7, "categoryId": 6, "quantityPerUnit": "12 per box", "unitPrice": 44.99, "unitsInStock": 50, "unitsOnOrder": 20, "reorderLevel": 10, "discontinued": false }
  • DELETE anmodning for at slette et produkt:

http
DELETE https://localhost:5091/api/products/81

Når du arbejder med REST Client, vil du hurtigt se statuskoder som 201 for succesfuld oprettelse, 204 for succesfuld opdatering og 404 for at indikere, at et objekt ikke længere findes. Disse statuskoder er essentielle for at forstå, hvordan webtjenesten reagerer på dine anmodninger.

Sikring af Web API med CORS og HTTP Logging

Når du har oprettet funktionelle webtjenester, er det vigtigt at forstå de sikkerhedsmekanismer, der beskytter dine tjenester. En af de primære udfordringer er at beskytte mod angreb via cross-origin anmodninger. Moderne webbrowseres sikkerhedspolitik, kaldet "Same Origin Policy", sikrer, at kun anmodninger fra samme oprindelse (dvs. samme protokol, domæne og port) kan tilgå din webtjeneste. Det betyder, at hvis en webside forsøger at tilgå din API fra en anden oprindelse, vil anmodningen blive nægtet, medmindre du eksplicit tillader det.

Dette kan opnås med CORS (Cross-Origin Resource Sharing). Ved at konfigurere CORS i din ASP.NET Core applikation kan du tillade specifikke domæner at få adgang til dine webtjenester. CORS kan nemt konfigureres i Program.cs filen:

csharp
builder.Services.AddCors(options => { options.AddPolicy("AllowSpecificOrigin", policy => policy.WithOrigins("https://example.com").AllowAnyHeader().AllowAnyMethod()); });

Samtidig er det vigtigt at forstå, hvordan HTTP logging kan hjælpe med at identificere og analysere anmodninger. Ved at konfigurere HTTP logging i din applikation kan du få indsigt i, hvilke oprindelser der forsøger at tilgå dine tjenester, og hvilke anmodninger der bliver sendt.

For at aktivere HTTP logging, tilføj følgende i din Program.cs fil:

csharp
builder.Services.AddHttpLogging(options => { options.RequestHeaders.Add("Origin"); options.LoggingFields = HttpLoggingFields.All; });

Dette gør det muligt for dig at logge både anmodningens oprindelse og de data, der sendes til og modtages fra din webtjeneste.

Skjul visse API-paths i Swagger

I nogle tilfælde vil du måske have en sti, som er funktionel, men som ikke skal vises i Swagger-dokumentationen. Dette kan opnås ved at bruge metoden ExcludeFromDescription():

csharp
app.MapGet("/", () => "Hello World!")
.ExcludeFromDescription();

Dette er nyttigt, hvis du har interne endpoints, som ikke skal være synlige for slutbrugeren, men stadig skal være tilgængelige for interne systemer.

Det er også vigtigt at bemærke, at når du arbejder med webtjenester, bør du være opmærksom på mulige angreb som f.eks. SQL injection, cross-site scripting (XSS) og andre sårbarheder, der kan udnytte svagheder i din webtjeneste. Ved at implementere korrekt sikkerhedsinfrastruktur og regelmæssigt teste dine webtjenester, kan du reducere risikoen for angreb markant.

Hvordan bygger man en service, der understøtter GraphQL?

At opbygge en GraphQL-service er en proces, der involverer flere faser, lige fra at vælge den rette projektstruktur til at definere de nødvendige GraphQL-forespørgsler og sikre, at de fungerer effektivt. Selvom der ikke er en standard .NET-skabelon til GraphQL, kan man nemt komme i gang ved at vælge en ASP.NET Core Empty-projekt skabelon og derefter tilføje de nødvendige pakker og konfigurationer.

Først oprettes et nyt projekt ved hjælp af den tomme ASP.NET Core skabelon. Selvom GraphQL i sig selv ikke kræver en webserver, da det ikke er bundet til HTTP, er det ofte en praktisk tilgang at vælge en webserver til at komme i gang. Efter at have oprettet et projekt skal der tilføjes en pakke, der understøtter GraphQL, såsom Hot Chocolate, som kan findes på nuget.org. Når pakken er tilføjet, opdateres projektets konfiguration, så serveren lytter på de rette porte, både HTTP og HTTPS, og der oprettes et endpoint til GraphQL.

Dernæst defineres den GraphQL-schema, der skal eksponeres af webservicen. Et simpelt eksempel på en "Hello World" forespørgsel kan illustrere, hvordan man skaber en grundlæggende forespørgsel. En klasse, som f.eks. Query.cs, indeholder en metode som GetGreeting(), der returnerer teksten "Hello, World!". Når denne metode er defineret, konfigureres applikationen til at bruge GraphQL-serveren og registrerer forespørgselsklassen. Det er vigtigt at sikre, at forespørgslen korrekt rutes til et endpoint, som i dette tilfælde er graphql.

Når serveren er startet, kan udvikleren navigere til en interface som BananaCakePop for at teste sin GraphQL-endpoint. Dette giver en visuel brugerflade, hvor man kan skrive og afvikle GraphQL-forespørgsler. Når man f.eks. skriver en simpel forespørgsel som { greeting }, vil serveren returnere "Hello, World!" i et JSON-format. Det er muligt at udforske, hvordan man arbejder med mere komplekse forespørgsler og hvordan man håndterer data tilbage fra serveren.

GraphQL forespørgsler kan også navngives for at gøre det lettere at identificere dem i systemer som Microsoft Azure og Application Insights. Navngivne forespørgsler kan være nyttige til overvågning og fejlfinding, da de giver mulighed for at spore specifikke anmodninger og svar.

En yderligere funktionalitet i GraphQL er, at man kan undlade præfikset Get i metodenavne, der svarer til GraphQL-felter. For eksempel kan man i stedet for GetGreeting() blot bruge greeting, og GraphQL-serveren vil automatisk forstå og eksponere dette som et felt. Derudover skal man være opmærksom på, at C# bruger TitleCase til metode- og klassedefinitioner, mens GraphQL kræver camelCase for feltnavne.

En anden vigtig aspekt ved udvikling af GraphQL API’er er brugen af Entity Framework Core (EF Core) til at definere datamodeller, der kan spørges gennem GraphQL. EF Core modeller kan integreres i GraphQL-systemet, så data fra en database kan blive tilgængelig som en del af GraphQL-schemat. Dette betyder, at udviklere nemt kan udvide deres API med datakilder og sikre, at de får de nødvendige oplysninger på en effektiv måde. GraphQL gør det muligt at anmode om præcist de data, der er nødvendige, hvilket resulterer i færre og mere målrettede anmodninger til serveren, og derved forbedrer ydeevnen.

Når man arbejder med GraphQL, er det vigtigt at forstå begreberne som "queries", "mutations" og "subscriptions". Queries bruges til at hente data, mutations bruges til at ændre data, og subscriptions gør det muligt at modtage realtidsopdateringer, når data ændres. Det er afgørende at designe et schema, der afspejler de behov og den struktur, som den pågældende applikation kræver.

Endvidere er det også vigtigt at overveje sikkerhed og validering af de forespørgsler, der modtages. Dette inkluderer at beskytte følsomme data mod uautoriseret adgang og sikre, at kun valide forespørgsler bliver accepteret af serveren. Det kan omfatte godkendelse og autorisation, så kun bestemte brugere kan tilgå specifikke GraphQL-felter eller foretage ændringer i systemet.

Samtidig bør man være opmærksom på, at GraphQL, selvom det tilbyder stor fleksibilitet, også kan medføre kompleksitet i visse scenarier, især når man håndterer flere datakilder og relationer. Det er derfor vigtigt at tage højde for både udviklingstid og systemets kompleksitet, når man beslutter sig for at implementere GraphQL i et projekt.

Hvordan Strukturerer Man Projekter i .NET for Effektiv Udvikling?

At arbejde med komplekse løsninger i .NET kan hurtigt blive en udfordring, især når antallet af projekter vokser, og det er nødvendigt at navigere gennem mange forskellige applikationer og tjenester. Det er her, en god strukturering af projekter og navngivning bliver essentiel. I denne kontekst skal vi overveje de bedste praksisser for projektstruktur, navngivning og portnummerering, som kan hjælpe med at skabe en mere overskuelig og vedligeholdelsesvenlig udviklingsproces.

Når du begynder at udvikle flere applikationer og tjenester, vil du hurtigt støde på en lang række projekter, herunder websites, API'er, og databaser. For at holde styr på disse projekter er det vigtigt at etablere en klar og konsekvent struktur. Navngivningen af dine projekter bør afspejle applikationens eller løsningen, så enhver udvikler hurtigt kan forstå, hvad hvert projekt indeholder.

Et godt eksempel på en sådan struktur er bruken af et fælles præfiks for alle projektnavne, som i dette tilfælde er “Northwind”. Dette navn stammer fra et fiktivt firma, som Microsoft har brugt i deres eksempler gennem mange år. Ved at bruge “Northwind” som præfiks for alle projekterne, gør du det lettere at identificere relaterede projekter og forstå, hvordan de hænger sammen. For eksempel kunne et projekt for en MVC-baseret hjemmeside hedde “Northwind.Mvc”, mens en API-tjeneste kunne have navnet “Northwind.WebApi.Service”.

Der er mange måder at strukturere og navngive projekter på. Hvis du arbejder i et team, er det vigtigt at fastlægge en konvention, så alle følger den samme tilgang. En god praksis er at anvende projektets type som en del af navnet, såsom “class library”, “console app” eller “website”. Dette hjælper med hurtigt at identificere, hvilken type funktionalitet hvert projekt tilbyder. Et eksempel kunne være et projekt til gRPC-tjenester, der kunne navngives “Northwind.gRPC.Service” for serverdelen og “Northwind.gRPC.Client.Mvc” for en klientapplikation.

Portnummerering er også en vigtig del af udviklingsmiljøet, især når flere projekter skal køres samtidigt. For at undgå portnummerkonflikter bør du følge en fast portnummerkonvention. En effektiv metode er at bruge portnumre, der er dynamisk knyttet til kapitlet i en bog eller en version af applikationen. Eksempelvis kunne et projekt, som omhandler en webapplikation fra kapitel 15, bruge portnummeret 5151 for den sikre HTTPS-forbindelse. Dette gør det nemt at holde styr på, hvilke portnumre der er i brug, og forhindrer at flere projekter forsøger at bruge de samme numre.

En anden væsentlig del af projektudvikling i .NET er håndtering af advarsler under kompilering. Standardindstillingen i de fleste .NET-projekter er, at advarsler bliver ignoreret, selvom de kan indikere potentielle problemer med koden. For at sikre høj kvalitet og undgå at negligere potentielle fejl, anbefales det at konfigurere projektet til at behandle advarsler som fejl. Dette betyder, at kompileringen vil blive stoppet, hvis der opstår advarsler, hvilket giver udvikleren mulighed for at rette problemerne, før de fortsætter med at bygge løsningen. Denne tilgang fremmer bedre kodningspraksis og sikrer, at advarsler ikke bliver overset.

Det er dog vigtigt at være opmærksom på specifikke tilfælde, hvor denne praksis måske ikke er hensigtsmæssig. For eksempel, i tilfælde af gRPC-projekter, kan der være situationer, hvor advarsler fra eksterne værktøjer som Google’s gRPC-kodegenerering ikke bør behandles som fejl. Dette skyldes, at visse genererede kodenavne kan indeholde små bogstaver, hvilket udløser advarsler, som ikke nødvendigvis indikerer en fejl i applikationen.

Det er også værd at overveje, at selvom C# og .NET giver udviklere en bred vifte af muligheder for at bygge apps og tjenester, er det vigtigt at forstå, at visse teknologier og metoder stadig er under udvikling. Det betyder, at der er potentiale for fremtidige ændringer i sprog og platforme, som kan kræve tilpasninger af eksisterende løsninger. For eksempel er der i øjeblikket advarsler om brugen af typer, der kun indeholder små bogstaver i deres navne. Selvom dette kan virke som en mindre problemstilling, er det en indikator på, at fremtidige versioner af C# måske vil reservere små bogstaver til nøgleord, hvilket kan skabe kompatibilitetsproblemer med eksisterende kode. Det er derfor vigtigt at holde sig opdateret med de nyeste versioner af .NET og C# for at sikre, at dine applikationer forbliver kompatible og funktionelle.

Ved at følge disse retningslinjer for projektstruktur, navngivning, portnummerering og håndtering af advarsler kan du skabe en mere effektiv udviklingsproces, der gør det lettere at navigere i komplekse løsninger og minimere tekniske problemer. Dette er grundlaget for at bygge robuste, skalerbare applikationer, der er lette at vedligeholde og videreudvikle.