XAML er det deklarative sprog, som ligger til grund for brugergrænseflader i .NET MAUI og andre .NET-baserede GUI-frameworks. Dets syntaks og semantik blev først introduceret med WPF i 2006 og har siden dannet rygraden i flere teknologier som Silverlight, UWP, WinUI og Xamarin.Forms. I dag er XAML en nøglekomponent i udviklingen af moderne applikationer på tværs af platforme, herunder Android, iOS, Windows og macOS via .NET MAUI.
XAML tillader, at udviklere beskriver brugergrænsefladen i en kompakt, læsbar og genanvendelig form. Den største styrke ved XAML er separationen af præsentation og logik: layoutet defineres i XAML, mens interaktionen og adfærden håndteres i C#-kodebaggrund. Dette muliggør en mere struktureret og vedligeholdelsesvenlig tilgang til udvikling, særligt i større projekter med flere udviklere.
Hvor C#-kode til opbygning af brugerflader ofte er omfangsrig og repetitiv, tilbyder XAML en mere kondenseret form. En simpel værktøjslinje med knapper kræver adskillige linjer i C#, men kan udtrykkes med blot få deklarative linjer i XAML. Samtidig giver XAML en indbygget understøttelse for ressourcedeling og styling på forskellige niveauer – fra individuelle kontroller til globale applikationsniveauer.
Et andet centralt aspekt ved XAML er understøttelsen af data binding. Binding tillader dynamisk forbindelse mellem UI-komponenter og underliggende datamodeller. Denne mekanisme forenkler synkroniseringen mellem brugergrænsefladen og applikationens tilstand, især når man anvender MVVM-mønstret (Model-View-ViewModel), som XAML og .NET MAUI er optimeret til.
Når en XAML-fil kompileres, kræves det, at den tilknyttede C#-klasse kalder InitializeComponent() i sin konstruktør. Denne metode indlæser og initialiserer de deklarerede UI-elementer og deres tilstande. Det er denne proces, der oversætter de deklarative markup-definitioner til konkrete .NET-objekter og tilknytter dem til hændelseslogik, fx klik-metoder.
.NET MAUI anvender flere navnerum til at organisere sine typer. Det primære er Microsoft.Maui.Controls, som indeholder de centrale UI-komponenter som Button, Image, ContentPage og VerticalStackLayout. Derudover findes Microsoft.Maui.Graphics, som definerer typer til farver, punkter, skrift og grafikoperationer, og Microsoft.Maui, som indeholder hjælpeklasser og basale strukturer. For at gøre disse typer tilgængelige i XAML, importeres de via xmlns-attributter i roden af XAML-filen. Nogle navnerum, som fx x, anvendes til almindelige XAML-funktioner, mens local typisk refererer til projektets egne klasser.
For udvikling i .NET MAUI kræves passende udviklingsmiljø: Visual Studio 2022 på Windows til at kompilere WinUI 3-applikationer, og Visual Studio for Mac med Xcode for at målrette macOS Catalyst og iOS. Der findes CLI-værktøjer til oprettelse af MAUI-projekter, men den visuelle understøttelse er endnu begrænset udenfor Visual Studio.
Ved at anvende komponentbiblioteker som Radzen Blazor og MudBlazor kan udviklere også bygge webbas
Hvordan oprette en simpel Web API Service med .NET MAUI og konfigurere den til at tillade usikre forbindelser
Når du udvikler en applikation med .NET MAUI, kan du oprette en webtjeneste ved at bruge ASP.NET Core Web API. Dette giver en enkel og effektiv måde at eksponere data, såsom kunder fra en database, via HTTP. I denne proces vil vi gennemgå, hvordan du opretter en web API service, konfigurerer den til at håndtere både sikre og usikre forbindelser, og hvordan du tester den både på en lokal maskine og via emulerede enheder som Android og iOS.
Først skal du oprette et webservice-projekt i din løsning. I dette tilfælde bruger vi ASP.NET Core Web API med minimale API'er. Projektet skal konfigureres uden autentifikation og med HTTPS aktiveret. Docker skal ikke bruges, og OpenAPI-understøttelse skal være aktiveret for at gøre det nemmere at dokumentere og teste API'et via Swagger UI.
Når projektet er oprettet, skal du tilføje en reference til Northwind-databasen, som blev oprettet i et tidligere kapitel. Denne reference gør det muligt for webtjenesten at tilgå og manipulere kundedata, der er gemt i SQL Server-databasen.
For at sikre, at alle projekter og afhængigheder er korrekt komplieret, skal du køre dotnet build fra kommandolinjen. Dette sikrer, at alle nødvendige biblioteker er opdateret og kompileret korrekt, inden du starter webtjenesten.
Når webtjenesten er oprettet og bygget, skal du opdatere launchSettings.json-filen for at angive de rigtige porte for både HTTP og HTTPS. Dette giver dig mulighed for at teste din API på forskellige protokoller, alt efter om du ønsker en sikker eller usikker forbindelse.
I programmet Program.cs skal du fjerne eventuelle standard-tjenester og erstatte dem med endpoints for CRUD-operationer på kundedataene. Dette indebærer at oprette endpoints for at hente alle kunder, hente en enkelt kunde, oprette en ny kunde, opdatere en eksisterende kunde og slette en kunde.
Efter at have implementeret CRUD-operationerne, skal du køre webtjenesten med HTTPS-konfigurationen aktiveret. Swagger UI vil automatisk blive tilgængelig, så du kan dokumentere og teste din API direkte i browseren. Når du har startet webtjenesten, kan du bruge Swagger til at prøve operationer som at hente kundedata og teste API'ets funktionalitet i realtid.
For at muliggøre usikre forbindelser, især under test, skal du konfigurere API'en til at tillade HTTP-anmodninger. Dette opnås ved at kommentere HTTPS-omdirigeringen i Program.cs. Du kan derefter bruge en almindelig HTTP-forbindelse til at tilgå API'en uden at kræve en sikker TLS-forbindelse.
Når du tester din .NET MAUI-applikation, især på emulerede enheder som Android, kan du bemærke, at Android-enheder ikke kan tilgå localhost direkte. I stedet skal du bruge den specielle IP-adresse 10.0.2.2, som henviser til den lokale maskine i en virtuel router, der bruges af Android-emulatoren. Dette gør det muligt for Android-emulerede enheder at kommunikere med den lokale webtjeneste.
For at muliggøre usikre forbindelser i en iOS-applikation, skal du justere Info.plist-filen for at tillade HTTP-anmodninger. Dette kan gøres ved at tilføje NSAppTransportSecurity-indstillinger, hvor du enten tillader "Arbitrary Loads" (vilkårlige belastninger) eller kun tillader lokal netværkstrafik, afhængigt af de specifikke krav til applikationen.
Det er også vigtigt at forstå, at selvom du kan tillade usikre forbindelser til API'en under testning, bør du undgå at bruge denne metode i produktionsmiljøer. For at sikre dine API'er i produktionsmiljøer anbefales det at anvende HTTPS og implementere passende autentifikation og autorisation for at beskytte følsomme data.
En vigtig del af arbejdet med API'er er også at forstå, hvordan du håndterer fejlhåndtering og statuskoder korrekt. For eksempel skal du sørge for, at dine API-endpoints korrekt returnerer 404 (ikke fundet) ved fejlsøgning og 204 (ingen indhold) efter vellykkede opdateringer og sletninger. At sikre korrekt fejlhåndtering og dokumentation forbedrer både udviklerens og brugerens oplevelse.
Hvordan Rollebaseret Adgangskontrol og Brugerautentifikation Arbejder i Applikationer
I moderne systemer, især dem, der håndterer følsomme oplysninger, er det afgørende at have en pålidelig mekanisme til at kontrollere både brugeradgang og autorisation. En af de mest effektive måder at gøre dette på er gennem rollebaseret adgangskontrol (RBAC) og et solidt system til brugerautentifikation. Ved at bruge roller i stedet for at tildele individuelle rettigheder til hver bruger, kan systemet være både fleksibelt og skalerbart. Dette sikrer, at adgangen kan ændres nemt, uden at det kræver, at individuelle brugere får ændrede rettigheder.
En grundlæggende tilgang til dette er at tildele en bruger en rolle snarere end at tildele specifikke adgange til objekter direkte. Et godt eksempel på dette er det britiske monarksystem, hvor retten til at få adgang til Buckingham Palace kunne tildeles "Monarken af Storbritannien", i stedet for den specifikke person, der i øjeblikket er monark. På denne måde, når en ny person træder ind i rollen, er det ikke nødvendigt at ændre rettighederne for rollen, kun at opdatere medlemskabet af den rolle.
Rollebaseret adgangskontrol er således meget mere fleksibelt og vedligeholdelsesvenligt end at tildele rettigheder direkte til brugere. Dette system sikrer, at man ikke behøver at revidere sikkerhedsindstillingerne hver gang der sker en ændring i organisationens struktur. I stedet for at ændre adgangen for Charles Philip Arthur George Windsor som individ, ændrer man blot medlemsskabet af rollen, og tilføjer den nye monark.
Autentifikation og autorisation er to fundamentale processer i denne sammenhæng. Autentifikation beskæftiger sig med at identificere en bruger og bekræfte, at de er, hvem de påstår at være. Dette kan gøres gennem forskellige mekanismer som brugernavne og adgangskoder, biometrisk autentifikation, eller multifaktorautentifikation. Når en bruger er autentificeret, skal systemet også bestemme, hvilken adgang de har – dette gøres via autorisation. Autorisation handler om at afgøre, hvilke ressourcer en bruger kan tilgå, baseret på deres rolle og de krav, der er defineret af systemet.
Autentifikationen implementeres gennem grænseflader i System.Security.Principal namespace, hvor IIdentity og IPrincipal er de centrale elementer. IIdentity repræsenterer brugerens identitet og omfatter egenskaber som navn og autentifikationstype. I et typisk scenarie implementeres IIdentity af en klasse som GenericIdentity, der indeholder oplysninger om brugerens autentifikationstype og dennes krav (som for eksempel rollemedlemskab eller fødselsdato). IPrincipal er derimod en grænseflade, der knytter en bruger til deres rolle eller gruppe, og bruges til at verificere, om en bruger har de nødvendige rettigheder til at udføre en bestemt handling.
Disse mekanismer spiller sammen i et autentifikationssystem, der muliggør, at en bruger kan logge ind og få tildelt de nødvendige tilladelser. Et eksempel på dette kan ses i en simpel implementering af brugerautentifikation i en applikation, hvor brugeren indtaster deres brugernavn og adgangskode, og hvis de er valideret, oprettes en instans af GenericIdentity og GenericPrincipal for at angive, hvilke roller de har, og hvilke rettigheder de får adgang til.
Når en bruger logger ind, kan systemet automatisk associeres med deres rolle. For eksempel kan en bruger med rollen "Admin" få adgang til administrative funktioner i applikationen, mens en bruger med rollen "Bruger" kun får adgang til grundlæggende funktioner. Dette muliggør en finmasket kontrol af adgangen til systemet, hvor kun de brugere, der har de nødvendige rettigheder, får lov til at udføre bestemte handlinger.
Det er vigtigt at forstå, at både autentifikation og autorisation er nødvendige for at sikre, at systemet fungerer korrekt. Autentifikation bekræfter en brugers identitet, mens autorisation kontrollerer, hvad brugeren har lov til at gøre. Selv hvis en bruger er korrekt autentificeret, betyder det ikke nødvendigvis, at de har adgang til alle ressourcer i systemet – det afhænger af deres rolle og de specifikke tilladelser, der er tildelt den rolle.
For at implementere et effektivt autentifikations- og autorisationssystem skal man også tænke på vedligeholdelsen af brugere og deres rettigheder. Et system, hvor brugerens rettigheder konstant er afhængige af den aktuelle rolle, gør det muligt hurtigt at tilpasse systemet til ændringer i organisationen, uden at det kræver store ændringer i infrastrukturen.
En god praksis er også at anvende systemer, der understøtter "claims", som er et koncept, hvor specifik information om en bruger – som for eksempel deres rolle, privilegier eller medlemskab af bestemte grupper – gemmes som del af autentifikationsprocessen. Disse claims gør det muligt hurtigt at evaluere en brugers adgang baseret på deres oplysninger, uden at skulle opdatere hvert enkelt system manuelt, hver gang der sker en ændring i brugerens status eller rolle.
Det er også væsentligt at forstå, at autentifikation og autorisation bør implementeres med en høj grad af sikkerhed. Brugen af stærke adgangskoder, kryptering og andre sikkerhedsforanstaltninger, som multifaktorautentifikation, er nødvendige for at beskytte både brugere og applikationer mod uautoriseret adgang.
Hvordan Beskytter Man Applikationens Funktioner med Autorisation og Autentifikation?
For at beskytte en applikations funktionalitet er det essentielt at forstå, hvordan autentifikation og autorisation fungerer i et softwaremiljø. I den virkelige verden er der flere metoder til at sikre, at kun autoriserede brugere har adgang til bestemte funktioner i applikationen. I denne sammenhæng er det nødvendigt at anvende teknikker som autentifikation og rollebaseret adgangskontrol (RBAC), der giver mulighed for at bestemme, hvilke funktioner en bruger kan få adgang til baseret på deres identitet og rolle.
For at begynde at forstå, hvordan disse koncepter implementeres, lad os starte med en simpel autentifikations- og autorisationskontrol. Antag, at en bruger forsøger at logge ind i applikationen. Koden nedenfor viser en simpel måde at autentificere og hente brugerens informationer:
Når brugeren har logget ind, kan vi tilgå deres rolle og tjekke, om de har de nødvendige rettigheder til at tilgå bestemte funktioner. Som illustreret i outputtet ovenfor, kan vi hente brugernavnet, autentificeringstype og den rolle, som brugeren tilhører. Hvis brugeren er medlem af en bestemt rolle, f.eks. "Admins", kan vi give dem adgang til særlige funktioner. Dette er grundlaget for autorisation i en applikation, hvor vi ikke kun tjekker brugerens identitet, men også hvilken rolle de har.
Et mere avanceret trin er at implementere beskyttelse af funktioner, som kun skal være tilgængelige for bestemte brugere. I det følgende eksempel ser vi, hvordan vi kan beskytte en funktion, så kun administratorer kan få adgang til den:
Denne metode sikrer, at kun brugere, der er logget ind og har rollen "Admins", kan få adgang til den beskyttede funktion. Hvis en bruger uden de rette rettigheder forsøger at tilgå funktionen, vil en SecurityException blive kastet.
Det er også muligt at anvende try-catch blokke til at håndtere fejl og undtagelser, der opstår, når en bruger ikke har de nødvendige rettigheder:
Dette giver applikationen mulighed for at håndtere fejl på en kontrolleret måde, hvor vi kan vise en bruger en specifik fejlmeddelelse, hvis de forsøger at tilgå en funktion uden den nødvendige autorisation.
Når man udvikler applikationer, er det vigtigt at forstå, at den bedste praksis ikke er at opbygge sine egne autentifikations- og autorisationssystemer, men at anvende etablerede og veltestede løsninger. Kommercielle eller open-source løsninger som IdentityServer4 eller Azure Active Directory giver mulighed for at implementere standarder som OAuth 2.0 og OpenID Connect, der er blevet grundigt gennemtestet og valideret. Dette minimerer risikoen for at introducere sikkerhedshuller i applikationen.
I den virkelige verden anbefales det stærkt at bruge en etableret løsning til autentifikation og autorisation, frem for selv at implementere disse systemer. En god løsning kan f.eks. være Azure Active Directory, som Microsoft tilbyder. Det giver mulighed for at håndtere brugeridentiteter og -roller på en sikker og skalerbar måde. Læs mere om dette emne i den næste kapitel, der dækker webtjenester og deres sikkerhed.
Samtidig skal man også overveje de yderligere sikkerhedsforanstaltninger, der er nødvendige for at beskytte følsomme data i applikationen. For eksempel bør man aldrig opbevare brugernes adgangskoder i klartekst. Det anbefales at bruge saltning og hashing af adgangskoder, så de bliver beskyttet, selv hvis en angriber får adgang til databasen. Det er også nødvendigt at implementere kryptering, hvis der skal opbevares følsomme data som kreditkortnumre eller personlige oplysninger.
Det er vigtigt at forstå, at implementeringen af en robust sikkerhedsinfrastruktur kræver en grundig forståelse af både autentifikation, autorisation, kryptering og de bedste praksis for at beskytte data. Selvom teknologien kan virke kompleks, er det fundamentale formål at sikre, at kun de rigtige personer får adgang til de rigtige ressourcer i applikationen.
Hvordan kombinere datakilder ved hjælp af GraphQL i en ASP.NET Core-applikation?
I denne artikel udforsker vi, hvordan vi kan kombinere data fra forskellige kilder ved hjælp af GraphQL i en ASP.NET Core-applikation. Vi går gennem, hvordan man opsætter nødvendige modeller, arbejder med HTTP-anmodninger og hvordan man integrerer GraphQL med en eksisterende webapplikation.
For at starte, skal vi definere de nødvendige modelklasser for de data, vi ønsker at hente via GraphQL. For eksempel, i mappen Models opretter vi en klasse kaldet ResponseProducts.cs, som skal håndtere de produkter, der tilhører en bestemt kategori. Denne klasse vil indeholde en indre klasse, DataProducts, som har en egenskab ProductsInCategory, der repræsenterer en liste af produkter. Ydermere definerer vi en Data-egenskab, som indeholder dataen fra GraphQL-forespørgslen:
På samme måde kan vi oprette en ResponseCategories.cs-fil for at håndtere kategorierne af produkter. Denne fil kan se ud som følger:
Derefter skal vi definere en IndexViewModel.cs-klasse, der kan opbevare al data, vi måtte ønske at vise i visningen. Dette vil omfatte HTTP-statuskoden, råresponsteksten, produkter, kategorier og fejlmeddelelser:
Når de nødvendige klasser er på plads, kan vi gå videre med at konfigurere HTTP-klienten i vores Program.cs-fil. Her registrerer vi en HTTP-klient, som er konfigureret til at kommunikere med GraphQL-tjenesten:
Når HTTP-klienten er konfigureret, er det tid til at arbejde med controlleren. I HomeController.cs definerer vi en asynkron metode, der håndterer HTTP-anmodningerne. Først forsøger vi at sende en simpel GET-anmodning til tjenestens rod for at sikre, at tjenesten er oppe. Derefter sender vi en POST-anmodning til GraphQL-endepunktet, hvor vi bruger GraphQL-syntaksen til at forespørge om produkter i en bestemt kategori. Dette gøres ved at indkapsle GraphQL-spørgsmålet i en JSON-krop:
Når GraphQL-forespørgslen er blevet behandlet, viser vi de relevante produkter på frontend ved hjælp af Razor-syntaks i Index.cshtml-filen:
En vigtig del af dette arbejde er at sikre, at GraphQL-spørgsmålene er korrekt formateret og at de nødvendige data bliver sendt og modtaget effektivt. En anden vigtig overvejelse er, at arbejdet med asynkrone metoder er afgørende for at opretholde en god ydelse, da HTTP-anmodninger kan tage en vis tid, og vi ønsker ikke at blokere brugergrænsefladen.

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