ASP.NET Core Blazor WebAssembly: Authentifizierung und Autorisierung mit IdentityServer in Aktion

Seit der Version Blazor WebAssembly 3.2.0 enthält Blazor umfangreiche Unterstützung für clientseitige Authentifizierung, wodurch die Implementierung von OpenID Connect und OAuth2 in Single-Page-Applications (SPAs) deutlich vereinfacht wird. In diesem Artikel sehen wir uns an, wie wir Authentifizierung und Autorisierung in einem Blazor-WebAssembly-Client realisieren können. Zusätzlich werden wir die Client UI auf Basis von Nutzerrechten entsprechend dynamisch anpassen.

In diesem Artikel:

ASP.NET Core Blazor WebAssembly: Authentifizierung und Autorisierung mit IdentityServer in Aktion
Patrick Jahr ist Architekt bei Thinktecture. Sein Fokus liegt auf Backend-Systemen mit .NET Core und der Frontend-Entwicklung mit Angular.

Artikelserie

  1. Authentifizierung und Autorisierung mit IdentityServer in Aktion ⬅
  2. Authentifizierung und Autorisierung mit Keycloak in Aktion

Version Information:

  • ASP.NET Core Blazor: 3.2.0
  • ASP.NET Core: 3.1.3
  • IdentityServer 4
  • MatBlazor: 2.4.3

Anhand einer Demoapplikation wird nachvollziehbar, wie ein Blazor-WebAssembly-Client sich bei einem IdentityServer anmelden kann. Zusätzlich werden wir Informationen über den aktuellen Nutzer abfragen und nutzen, indem wir bestimmte Bereiche nur für autorisierte Nutzer zugänglich machen. Mit dem Access Token, den wir vom IdentityServer erhalten, können wir dann eine token-gesicherte Web-API aufrufen oder eine sichere SignalR-Verbindung aufbauen. Weitere Informationen über den IdentityServer oder die Konfiguration der Clients, Claims und Policies, finden sich in der IdentityServer-Dokumentation.

Der gesamte Source Code zu diesem Artikel befindet sich im zugehörigen GitHub Repository.

Authentifizierungsarchitektur in Blazor WebAssembly

Bevor wir darin einsteigen, eine Authentifizierung und Autorisierung im Blazor-Client zu implementieren, betrachten wir zuerst die Security-Architektur innerhalb von Blazor WebAssembly:

  • (1) Eingebettet in eine Razor-Seite wird im ersten Schritt die RemoteAuthenticatorView aufgerufen, die eine Aktion (z.B. login oder logout) entgegen nimmt.
  • (2) Anschließend nutzt diese Komponente den RemoteAuthenticationService, der als Brücke zwischen dem C#-Code und dem JavaScript-Code dient.
  • (3) Unter Verwendung der JsRuntime verwendet der RemoteAuthenticationService den AuthenticationService. Hier handelt es sich um eine JavaScript-Implementierung.
  • (4 & 5) Der AuthenticationService ruft in unserem Fall den IdentityServer auf, um sich über diesen zu authentifizieren und Tokens zurück zu erhalten.
  • (6 & 7) Ist das Ergebnis erfolgreich, speichert der AuthenticationService die Daten im Session Storage und gibt das Ergebnis zurück an den RemoteAuthenticationService.
  • (8 & 9) Zum Schluss teilt der RemoteAuthenticationService der RemoteAuthenticatorView mit, ob der Login erfolgreich war.

Blazor-Client erstellen und konfigurieren

Beim Erstellen eines neuen Blazor-WebAssembly-Projekts kann der Parameter -au angegeben werden. Er zeigt an, dass individuelle Benutzerkonten zur Authentifizierung genutzt werden sollen. Dies entspricht den notwendigen Voraussetzungen zur Nutzung von IdentityServer.

				
					# Erstellen einer Blazor-WASM-Applikation mit individuellen Nutzerkonten
dotnet new blazorwasm -au individual -n BlazorClient
				
			

Diese Einstellung sieht einen Platzhalter für die OpenID-Verbindungskonfiguration in der Datei Program.cs vor:

				
					public static async Task Main(string[] args)
{
  ...
  builder.Services.AddOidcAuthentication(options =>
  {
    // ... add options here
  });
  ...
}
				
			

An diesem Punkt können wir die Parameter konfigurieren, die für die Kommunikation mit IdentityServer erforderlich sind. Wir haben entweder die Möglichkeit, die Konfiguration direkt im Code zu hinterlegen, was für eine kurze Beispielimplementierung ausreichend ist, oder man verwendet für mehr Flexibilität eine Konfigurationsdatei. Dazu nutzen wir die vorhandene appsettings.json-Datei und fügen eine neue Konfiguration hinzu:

				
					{
  "Oidc": {
    "Authority": "https://localhost:5001/",
    "ClientId": "blazor-spa",
    "DefaultScopes": [
      "openid",
      "profile"
    ],
    "PostLogoutRedirectUri": "/",
    "ResponseType": "code"
  }
}
				
			

Folgende Parameter werden in der Konfigurationsdatei gesetzt:

  • Authority ist die URL des IdentityServers, die sowohl für die Umleitung als auch für die Überprüfung der Signatur der Tokens und der Identität, die sie ausgegeben hat, verwendet wird.
  • ClientId ist der eindeutige Name für die Anwendung.
  • DefaultScopes sind die Scopes, die wir während des Anmeldevorgangs anfordern möchten, wie z.B. die E-Mail-Adresse oder die Profilinformationen. Wir verwenden hier openid, um anzuzeigen, dass wir die Überprüfung der Identität des Benutzers mit OpenID Connect durchführen möchten, und profile, um einige grundlegende Informationen des Benutzers abzurufen, z.B. seinen Namen.
  • ResponseType ist der von uns verwendete Grant Type, hier der Authorization-Code-Grant.
  • PostLogoutRedirectUri URL, an die wir weitergeleitet werden wollen, sobald wir uns ausloggen.

Die von uns hinzugefügte Konfiguration übergeben wir dann an die ProviderOptions-Eigenschaft.

				
					builder.Services.AddOidcAuthentication(options =>
{
  builder.Configuration.Bind("Oidc", options.ProviderOptions);
});
				
			

Zum Schluss müssen wir die RemoteAuthenticatorView in einer Blazor-Page hinzufügen. Sie ist der zentrale Dreh- und Angelpunkt für die benutzerzentrierte Interaktion mit dem Authentifizierungssystem. Hierzu existiert in der Demoapplikation eine Seite Authentication.razor. Um nicht für jede Aktion eine neue Seite anlegen zu müssen, wird die gewünschte Aktion (wie loginoder logout) als Parameter an die Seite mit übergeben.

				
					@page "/authentication/{action}"

@using Microsoft.AspNetCore.Components.WebAssembly.Authentication

<RemoteAuthenticatorView Action="@Action" />

@code{
    [Parameter] public string Action { get; set; }
}
				
			

Auf der Startseite der Anwendung befindet sich ein Login-Button, der mit der Aktion login die Route auhentication/login aufruft und somit den Authentifizierungsprozess startet.

				
					@page "/"

@inject NavigationManager Navigation

<div style="display: flex; justify-content:center; align-items: center; height: 100%;">
    <MatButton OnClick="@BeginSignIn" Unelevated="true" Style="background-color: #ff584f;">Login</MatButton>
</div>

@code {
    private void BeginSignIn(MouseEventArgs args)
    {
        Navigation.NavigateTo("authentication/login");
    }
}
				
			

Nachdem wir nun eine erfolgreiche Authentifizierung des Clients am IdentityServer durchführen können, wollen wir uns im nächsten Schritt Nutzerdaten abrufen und verarbeiten.

Erweitern von und Arbeiten mit Informationen über den Benutzer

Über den ID-Token können wir auf die vom IdentityServer bereit gestellten Informationen über den Benutzer zugreifen. Für den Fall, dass für unsere Clientanwendung eine Information über den Benutzer zusätzlich in den Token inkludiert werden soll, wie zum Beispiel die E-Mail-Adresse, können wir diese neue Eigenschaft im IdentityServer hinzufügen. Dazu passen wir die Konfiguration für den Client an (Config.cs):

				
					public static IEnumerable<IdentityResource> IdentityResources =>
  new IdentityResource[]
  {
    new IdentityResources.OpenId(),
    new IdentityResources.Profile(),
    new IdentityResources.Email()
  };

public static IEnumerable<Client> Clients =>
  new Client[]
  {
    new Client
    {
      ClientId = "blazor-spa",
      AllowedScopes =
      {
          // Hier können neue Scopes hinzugefügt werden, welche vom Client dann abgerufen werden können
          IdentityServerConstants.StandardScopes.OpenId,
          IdentityServerConstants.StandardScopes.Profile,
          IdentityServerConstants.StandardScopes.Email
      },
      ...
    },
 };
				
			

Zusätzlich muss dieser anzufordernde Scope in der Konfiguration im Blazor-Client ergänzt werden:

				
					{
  "DefaultScopes": [
    "openid",
    "profile",
    "email"
  ]
}

				
			

Haben wir alle Anpassungen gemacht, sind die neue Benutzerinformation über den ID-Token abrufbar.

Nun können wir über die context-Eigenschaft der AuthorizeView auf die Daten des aktuellen Benutzers zuzugreifen. Dafür nutzen wir die User-Property. Diese beinhaltet die Daten des aktuellen Benutzers sowie den aktuellen Zustand, ob ein Nutzer authentifiziert ist oder nicht. Im Beispiel unten sehen wir, dass wir innerhalb der View mit Authorized Inhalte darstellen können, die nur authentifizierte Benutzer sehen, beispielsweise seinen Namen und den Logout-Button. Wenn die Authentifizierung nicht erfolgreich war oder der Authentifizierungsprozess noch nicht gestartet wurde, zeigen wir via NotAuthorized den Login-Button an. Darüber hinaus können wir mit dem context auf den aktuellen AuthenticationState zugreifen, der den aktuellen Benutzer mit all seinen Ressourcen kennt 

				
					<AuthorizeView>
    <Authorized>
        <p>@context.User.Identity.Name</p>
        <MatIconButton Icon="exit_to_app" OnClick="@BeginSignOut"></MatIconButton>
    </Authorized>
    <NotAuthorized>
        <MatButton OnClick="@BeginSignIn" Unelevated="true">Login</MatButton>
    </NotAuthorized>
</AuthorizeView>

				
			

Eine ähnliche Vorgehensweise können wir auch für ganze Seiten nutzen, in dem wir dort das Authorize-Attribut hinzufügen. Durch das Attribut kann die Seite nur durch einen authentifizierten Nutzer aufgerufen werden.

				
					@page "/history"
@attribute [Authorize]
				
			

Sicher mit dem Server kommunizieren

Aufrufen einer gesicherten Web-API

Nachdem wir in unserem Blazor-Client auf den aktuellen Authentifizierungsstatus zugreifen können, möchten wir jetzt Daten von einer sicheren Web-API abrufen. Hierzu müssen wir den vom IdentityServer erhaltenen Access Token beim Aufrufen der Web-API-Methode als HTTP-Header hinzufügen.

Blazor bietet hier den Handler AuthorizationMessageHandler an, der mithilfe von Dependency Injection bereitgestellt werden kann. Dieser schaut, ob ein Token vorhanden ist und fügt diesen bei jedem HTTP-Request als Authorization-Header hinzu. Hierfür benötigen wir einen Verweis auf das Microsoft.Extension.Http-NuGet-Paket. Danach verwenden wir die IHttpClientFactory, um einen HttpClient für unsere API zu registrieren.

				
					builder.Services.AddHttpClient("Blazor.API")
    .AddHttpMessageHandler(sp => 
    {
        var handler = sp.GetService<AuthorizationMessageHandler>()
            .ConfigureHandler(
                authorizedUrls: new[] { "http://localhost:5002" },
        return handler;
    });
				
			

Der obige Code definiert einen Client mit dem Namen Blazor.API, der intern den AuthorizationMessageHandler verwendet. In der Konfiguration tragen wir die authorizedUrls ein, die ein Access Token benötigen. Danach registrieren wir die Standard-HttpClient-Instanz im Dependency-Injection-Container:

				
					builder.Services
    .AddScoped(services => services.GetRequiredService<IHttpClientFactory>()
    .CreateClient("Blazor.ServerAPI"));
				
			

Fortan wird automatisch beim Aufrufen der Web-API ein Authorization-Header mit gesendet, über den das serverseitige Web-API (bzw. die Middleware in ASP.NET Core) den Token auslesen und validieren kann.

Absichern einer SignalR-Verbindung

Möchte man aus dem Blazor-Client eine sichere SignalR-Verbindung mit einem Server aufbauen, muss auch hier der Token mitgesendet werden. Hierzu müssen wir zuerst unsere SignalR-Verbindung konfigurieren. Mithilfe der Klasse HubConnectionBuilder können wir eine Instanz einer HubConnection erstellen und konfigurieren.

				
					public class SignalRService 
{
    private IAccessTokenProvider _tokenProvider;
    // ...
    public async Task InitConnectionAsync()
    {
        // ...
        var accessTokenState = await _tokenProvider.RequestAccessToken();
        if (accessTokenState.TryGetToken(out var accessToken)) 
        {
            var apiBaseUrl = _configuration["api:baseUrl"];
            var accessTokenString = accessToken.Value;
            _hubConnection = new HubConnectionBuilder()
                .WithUrl($"{apiBaseUrl}tictactoe", options =>
                { 
                    options.AccessTokenProvider = () => Task.FromResult(accessTokenString);
                })
                .WithAutomaticReconnect(new[] { TimeSpan.Zero, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(10) })
                .Build();
            //...
        }
    }
}
				
			

Die Übergabe des Tokens an die SignalR-Verbindung findet mithilfe eines IAccessTokenProviders statt. Der IAccessTokenProvider wird über Dependency Injection der Klasse SignalRService verfügbar gemacht. Dieser gibt den aktuellen Access Token zurück, der danach beim Aufbauen der Verbindung mitgesendet wird.

Im folgenden Bild sehen wir eine bestehende WebSocket-Verbindung, welche den Token als Parameter mit an den Server sendet.

Hinweis: Das Token wird nur beim initialen Aufbau der Verbindung überprüft und gilt dann für die gesamte Lebenszeit der Verbindung.

Mehr über SignalR gibt es hier in meinem Artikel zu Echtzeitkommunikation in Aktion zum Nachlesen.

Nun kann der Client eine sichere Verbindung zum serverseitigen Hub aufbauen und sich ordnungsgemäß authentifizieren.

Arbeiten mit Rollen

Rollen im IdentityServer und in der API konfigurieren

Nachdem wir uns mit unserem Client authentifiziert haben, möchten wir uns mit dem Thema Autorisierung beschäftigen. Ist ein Nutzer nur für einen bestimmten Bereich in der Anwendung berechtigt, kann dies über Rollen geregelt werden. Diese müssen natürlich zuerst im IdentityServer konfiguriert werden.

Hierzu schauen wir uns die Klasse ProfileWithRoleIdentityResource im IdentityServer an, die die gewünschten UserClaims definiert:

				
					public class ProfileWithRoleIdentityResource
        : IdentityResources.Profile
{
    public ProfileWithRoleIdentityResource()
    {
        this.UserClaims.Add(JwtClaimTypes.Name);
        this.UserClaims.Add(JwtClaimTypes.Subject);
        this.UserClaims.Add(JwtClaimTypes.WebSite);
        this.UserClaims.Add(JwtClaimTypes.Email);
        
        // Um die Rollen dem Identity Token hinzuzufügen, fügen wir den neuen Claim Role hier hinzu
        this.UserClaims.Add(JwtClaimTypes.Role);
    }
}
				
			

Hier ergänzen wir einen Claim des Typs Role hinzu. Durch diesen Claim können dem ID-Token Informationen über die Rollen des Benutzers hinzugefügt werden.

Im nächsten Schritt fügen wir den Claim Role auch bei den ApiResources hinzu, bei denen diese Information benötigt wird.

				
					public static IEnumerable<ApiResource> Apis =>
    new ApiResource[]
    {
        new ApiResource
        {
            // ...
            UserClaims =
            {
                JwtClaimTypes.Name,
                JwtClaimTypes.Subject,
                // Hier fügen wir den neuen UserClaim für die Rollen hinzu
                JwtClaimTypes.Role
            },
            //...
        },
    };
				
			

Als letztes benötigt unser Testbenutzer im IdentityServer die Information über seine Rollen. Hierzu fügen wir in der Datei TestUser.cs zum Testen nur einem Benutzer eine Rolle hinzu. Die anderen Benutzer bekommen keine Rolle, sodass wir im Client später einen Unterschied erkennen können.

				
					public class TestUsers
    {
        public static List<TestUser> Users = new List<TestUser>
        {
            new TestUser
            {
                SubjectId = "818727", Username = "alice", Password = "alice",
                Claims =
                {
                    new Claim(JwtClaimTypes.Name, "Alice Smith"),
                    new Claim(JwtClaimTypes.GivenName, "Alice"),
                    new Claim(JwtClaimTypes.FamilyName, "Smith"),
                    new Claim(JwtClaimTypes.Email, "AliceSmith@email.com"),
                    new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean),
                    new Claim(JwtClaimTypes.WebSite, "http://alice.com"),
                    new Claim(JwtClaimTypes.Address,
                        @"{ 'street_address': 'One Hacker Way', 'locality': 'Heidelberg', 'postal_code': 69118, 'country': 'Germany' }",
                        IdentityServerConstants.ClaimValueTypes.Json),
                    
                    // Die Rolle "ProUser" dient dazu, die Spielhistory abfragen zu dürfen.
                    new Claim(JwtClaimTypes.Role, "ProUser")
                }
            },
            // ...
    }
				
			

Jetzt sind alle Schritte im IdentityServer abgeschlossen und wir können uns der Web-API widmen. Hier ist nicht viel zu tun, wir müssen lediglich das Authorize-Attribute erweitern. Da es in unserer Beispielanwendung um das Spiel TicTacToe geht, gibt es für berechtigte Benutzer die Möglichkeit Ihre Spielhistorie abzurufen. Hierzu nutzen wir die Web-API GameHistory, welcher wir das Authorize-Attribute hinzufügen.

				
					[Route("[Controller]")]
// Hier wird zusätzlich noch die Rolle angegeben, die der Nutzer besitzen muss, um die Web-API aufrufen zu dürfen.
[Authorize(Roles = "ProUser")]
public class GamesHistoryController : Controller
//...
				
			

Wie im Code zu sehen ist, müssen wir nur die Property Roles des Authorize-Attributes setzen. Nachdem das Attribut nun gesetzt ist, können nur Nutzer die Historie abrufen, welche auch dazu berechtigt sind. Dies wird in der UI dadurch ersichtlich, dass neben dem Benutzernamen noch ein Icon erscheint, welches auf die Historie weiter leitet.

Im nächsten Schritt schauen wir uns an wie wir im Client über die Autorisierung Seiten oder bestimmte Teile einer Komponente für den Nutzer ein oder ausblenden können.

Berechtigung im Client prüfen

Folgende Beispielseite im Blazor-Client zeigt Informationen über den Benutzer an und gibt, sofern er eingeloggt ist, eine Liste der Claims aus.

				
					@page "/userInfo"

<AuthorizeView Roles="ProUser">
    <Authorized>
        <p>Hallo @context.User.Identity.Name, hier ist eine Liste deiner Nutzerrechte</p>
        
            @foreach (var claim in context.User.Claims)
            {
                <div class="mat-elevation-z8 sr-card">
                    <p>@claim.Type: </p>
                    <span>@claim.Value</span>
                </div>
            }
        
    </Authorized>
    <NotAuthorized>
        @if(context.User.Identity.IsAuthenticated) {
            <p>Nur berechtigte Nutzer können diesen Bereich sehen</p>
        } else {
            <RedirectToLogin />
        }
    </NotAuthorized>
</AuthorizeView>
				
			

Im Moment wird der Role-Claim jedoch nicht für Autorisierungszwecke verwendet. Dazu müssen wir eine Einstellung im AuthenticationStateProvider in der Program.cs treffen:

				
					builder.Services.AddOidcAuthentication(options =>
{
    builder.Configuration.Bind("Oidc",  options.ProviderOptions);
    
    // Hier teilen wir dem AuthenticationStateProvider mit, dass er den 'role'-Claim verwenden soll.
    // Dies dient dazu, dass wir diese auch später in unserer Komponente oder Seite nutzen und abfragen können.
    options.UserOptions.RoleClaim = "role";
});
				
			

Jetzt können wir die Rolle verwenden, um beispielsweise den Zugriff auf Seiten nur für berechtigte Nutzer zu autorisieren, zum Beispiel über das Authorize-Attribute:

				
					@page "/history"
@attribute [Authorize(Roles = "ProUser")]
				
			

Wir können auch Teile der UI auf der Grundlage der Rolle ein- und ausblenden:

				
					<AuthorizeView Roles="ProUser">
    <Authorized>
        <p>Nur berechtigte Nutzer können diesen Bereich sehen</p>
    </Authorized>
</AuthorizeView>
				
			

Natürlich kann es auch möglich sein, dass der Nutzer zwar authentifiziert aber nicht autorisiert ist:

				
					<AuthorizeRouteView Roles="ProUser">
    <NotAuthorized>
        @if (context.User.Identity.IsAuthenticated)
        {
            <p>Leider sind Sie nicht autorisiert.</p>
        }
        else
        {
            <RedirectToLogin />
        }
    </NotAuthorized>
</AuthorizeRouteView>
				
			

Fazit

Anhand einer Beispielanwendung konnten wir sehen, wie wir Authentifizierung und Autorisierung in eine Blazor-WebAssembly-App integrieren. Hierfür setzen wir den IdentityServer4 über das OpenID-Connect-Protokoll ein.

Wir haben ein Zugriffstoken angefordert und es dazu verwendet, eine geschützte Web-API aufzurufen und den Token im Header des HTTP-Aufrufs zu übergeben. Weiterhin haben wir gesehen, wie das Hinzufügen von Role-Claims sowohl in ID-Tokens als auch in Access-Tokens im IdentityServer funktioniert und wie diese dann für die Verwendung in Blazor verfügbar sind. Zum Schluss haben wir dann noch sichergestellt, dass auch die Web-API eine rollenbasierte Autorisierung implementiert.

Kostenloser
Newsletter

Aktuelle Artikel, Screencasts, Webinare und Interviews unserer Experten für Sie

Verpassen Sie keine Inhalte zu Angular, .NET Core, Blazor, Azure und Kubernetes und melden Sie sich zu unserem kostenlosen monatlichen Dev-Newsletter an.

Diese Artikel könnten Sie interessieren
Unterschiede
.NET
Blazor WebAssembly vs. Blazor Server – Welche Unterschiede gibt es und wann wähle ich was?

Blazor WebAssembly vs. Blazor Server – Welche Unterschiede gibt es und wann wähle ich was?

Das Blazor Framework von Microsoft gibt es inzwischen in drei "Geschmacksrichtungen". Die erste ist Blazor WebAssembly, die zweite Blazor Server, und zu guter Letzt gibt es noch Blazor Hybrid. In diesem Artikel wollen wir uns die zwei "echten", also Browser-basierten, Web-Anwendungs-Szenarien WebAssembly und Server anschauen.
04.07.2022
Three different textured walls
.NET
Dependency Injection Scopes in Blazor

Dependency Injection Scopes in Blazor

The dependency injection system is a big part of how modern ASP.NET Core works internally: It provides a flexible solution for developers to structure their projects, decouple their dependencies, and control the lifetimes of the components within an application. In Blazor - a new part of ASP.NET Core - however, the DI system feels a bit odd, and things seem to work a bit differently than expected. This article will explain why this is not only a feeling but indeed the case in the first place and how to handle the differences in order to not run into problems later on.
31.05.2022
.NET
Asynchrone Operationen: Blazor WebAssembly für Angular-Entwickler – Teil 5 [Screencast]

Asynchrone Operationen: Blazor WebAssembly für Angular-Entwickler – Teil 5 [Screencast]

Eine Webanwendung will natürlich auch mit Daten gefüttert werden. Doch diese müssen irgendwo her kommen. Nichts liegt näher als diese von einer Web API zu laden. Dieser Screencast zeigt, wie asynchrone Operationen in Blazor funktionieren und welche gravierenden Unterschiede es zu Angular gibt.
26.05.2022
.NET
Typings: Blazor WebAssembly für Angular-Entwickler – Teil 4 [Screencast]

Typings: Blazor WebAssembly für Angular-Entwickler – Teil 4 [Screencast]

C# und TypeScript entstammen der Feder der selben Person. Doch sind sie deshalb auch gleich? In diesem Teil der Screencast-Serie erfahren Sie, wie mit Typen in den beiden Programmiersprachen verfahren wird und welche Unterschiede es gibt.
19.05.2022
.NET
Bindings: Blazor WebAssembly für Angular-Entwickler – Teil 3 [Screencast]

Bindings: Blazor WebAssembly für Angular-Entwickler – Teil 3 [Screencast]

Wer Komponenten einsetzt, steht früher oder später vor der Fragestellung, wie man Daten an die Komponente übergibt oder auf Ereignisse einer Komponente reagiert. In diesem Screencast wird gezeigt wie Bindings bei Komponenten funktionieren, also wie eine Komponente Daten von außerhalb benutzen und Rückmeldung bei Aktionen geben kann.
12.05.2022
.NET
Komponenten: Blazor WebAssembly für Angular-Entwickler – Teil 2 [Screencast]

Komponenten: Blazor WebAssembly für Angular-Entwickler – Teil 2 [Screencast]

Bei der Entwicklung einer Webapplikation kommt es ständig vor, dass UI-Teile immer und immer wieder verwendet werden. Damit nicht immer Copy & Paste verwendet werden muss, können diese Teile in Komponenten zusammengefasst werden.
05.05.2022