Building a Chat App with Blazor, Identity and SignalR - Definitive Guide (2023)

In this guide, we'll build a complete chat app from scratch with Blazor WebAssembly using Identity and SignalR. When I started to create a chat component forBlazorHéroe, I couldn't find many resources online that fully covered this particular requirement. All I got were simple apps that just demonstrated basic use of SignalR in Blazor, which didn't look good either.

So I'm putting together this guide to cover everything you need to know when building real-time chat apps with Blazor, which also integrates with Microsoft Identity. This enables us to have a personal chat with registered users in our system. You can find themfull app source code here.

I would also make sure the app we are building looks clean and professional. To help me with this I use the MudBlazor component library for Blazor. This is what our final product would look like.

Building a Chat App with Blazor, Identity and SignalR - Definitive Guide (1)

Here is the list of features and topics that we will cover in this implementation:

  • Blazor WebAssembly 5.0 with ASP.NET Core hosted template.
  • MudBlazor Integrations - Super cool UI.
  • SignalR Integrations: Real-time messaging.
  • Cascading parameters.
  • Chat with registered users.
  • Chats are stored in the database via EFCore.
  • Notification popup for new messages.
  • Notification sound for new messages.

PRO TIP: Because this guide covers everything from a database perspective to building a clean UI with Blazor, the content is also quite extensive. I recommend that you bookmark this page for future reference should you need it. Also have your favorite drink 😉

Table of Contents

Configure the Blazor WebAssembly project

As mentioned above, let's start by creating a new Blazor WebAssembly app project ineyes studio2019. Make sure you have the latest .NET SDK installed.

Building a Chat App with Blazor, Identity and SignalR - Definitive Guide (2)

I call the app BlazorChat 😛 for obvious reasons

Building a Chat App with Blazor, Identity and SignalR - Definitive Guide (3)

Make sure you select Individual Accounts as the authentication type so that Visual Studio can apply the necessary code for login/registration and profile management.I took this approach to keep this implementation simple as our main goal is to build the chat app with Blazor.

Also make sure you have the Hosted ASP.NET Core checkbox checked as SignalR requires a server model. We will also look at using HttpClient in this implementation to retrieve chat logs and store them in our local database.

Building a Chat App with Blazor, Identity and SignalR - Definitive Guide (4)

After Visual Studio creates your shiny new Blazor app, you should always update any existing packages first. To do this, open the package manager console and run the following command.


Mudblazor component integration

Now let's add some Material Design to our application. MudBlazor is one of the libraries that has come the closest to bringing the feel of the Material UI to Blazor apps. I also used this great component library in BlazorHero.

Let's configure MudBlazor for Blazor. Open the Package Manager Console and make sure you have BlazorChat.Client set as the default project (as seen in the screenshot below). Run the following command to install the latest version of MudBlazor in your app.

Building a Chat App with Blazor, Identity and SignalR - Definitive Guide (5)

Once installed, open the _Imports.razor file in the client project in the Pages folder and add the following to the end of the file. This helps us to use MudBlazor components throughout the application without having to import the namespace into each component/page. We will also add other interfaces/services to this Razor component later in this guide.

@with MudBlazor

I've compiled UI code throughout the guide so you can get started with MudBlazor without wasting too much time. Let's try to create a UX admin panel with navigation bar (top), side menu (sidebar) and the content in the middle. do you have an idea, okay?

First, open index.html from the wwwroot folder of the BlazorChat.Client project. Replace all HTML code with the following code. In simple terms, we used MudBlazor's style sheets and part of its js file instead of the default styles we get with Blazor.

<!DOCTYPE html><html><head> <meta charset="utf-8" /> <meta name="viewport" content="ancho=ancho-del-dispositivo, escala-inicial=1.0, escala-máxima= 1.0, user-scalable=no" /> <title>Blazor Chat</title> <base href="/" /> <link href=",400,500,700 &display= swap" rel="hoja de estilo" /> <link href="_content/MudBlazor/MudBlazor.min.css" rel="hoja de estilo" /></head><body> <div id="app ">Cargando... </div> <div id="blazor-error-ui"> Se produziu um error não controlado. <a href="" class="reload">Recarregar</a> <a class="dismiss">🗙</a> </div> <script src="_content/Microsoft.AspNetCore.Components.WebAssembly.Authentication /AuthenticationService.js"></script> <script src="_framework/blazor.webassembly.js"></script> <script src="_content/MudBlazor/MudBlazor.min.js"></script></ corpo ></html>

Next, we need to register MudBlazor in our ASP.NET Core service container to resolve certain internal dependencies. You can also find these steps in the MudBlazor documentation.

Open the client project's Program.cs file and add the following registry along with the required namespace import.

usando MudBlazor.Services;.builder.Services.AddMudServices(c => { c.SnackbarConfiguration.PositionClass = Defaults.Classes.Position.BottomRight; });

SnackbarConfiguration is used later in the implementation.

Next we create the database and apply the migrations. Open appsettings.json in the server project. Here you can change the connection string as you like. I will use the default localdb instance for this development.

"ConnectionStrings": { "DefaultConnection": "Servidor=(localdb)\\mssqllocaldb;Database=BlazorChat;Trusted_Connection=True;MultipleActiveResultSets=true"},

Once that's done, open the package manager console again. This time, make the server project the default project (see screenshot below). Run the following command.

Update database
Building a Chat App with Blazor, Identity and SignalR - Definitive Guide (6)

Once this is done, your new database will be set up for you.

With the database ready, let's return to the MudBlazor integration. We will change some of the Razor components/layouts in this section. In the client project's shared folder, open the MainLayout.razor component. Paste the following code snippet over the existing code.

@inherits LayoutComponentBase<MudThemeProvider /><MudDialogProvider /><MudSnackbarProvider /><MudLayout> <MudAppBar Elevation="0"> <MudText Typo="Typo.h6" Class="ml-4">Blazor Chat</MudText> < MudAppBarSpacer /> <LoginDisplay /> </MudAppBar> <MudDrawer @bind-Open="_drawerOpen" Elevation="1"> <NavMenu /> </MudDrawer> <MudMainContent> <MudToolBar DisableGutters="true"> <MudIconButton Icon= "@Icons.Material.Outlined.Menu" Color="Color.Inherit" OnClick="@((e) => DrawerToggle())" Class="ml-3" /> </MudToolBar> <MudContainer MaxWidth=" MaxWidth.False" Class="mt-4"> @Body </MudContainer> </MudMainContent></MudLayout>@code { bool _drawerOpen = false; Void DrawerToggle () { _drawerOpen = !_drawerOpen; }}

Line 2-4: Components needed for MudBlazor to work.
Line 9 - This is a component generated by Visual Studio when we validate individual user accounts when building the Blazor project, remember? We will change this component shortly.
Line 12: This is where the NavMenu component is rendered. We will also modify this component.
Line 19: This is where the request body would be presented.

That's pretty much all you need to consider on this layout page. Drawer Toggle is another cool feature that has been implemented. Gives the app a smooth UI when toggling the sidebar. We'll come back to this layout page later in this guide to implement cascading parameters and add some code to SignalR.

Then open the LoginDisplay component and replace the entire component with the following code snippet.

@usando Microsoft.AspNetCore.Components.Authorization@usando Microsoft.AspNetCore.Components.WebAssembly.Authentication@inject NavigationManager Navigation@inject SignOutSessionStateManager SignOutManager<AuthorizeView> <Autorizado> <div class="pa-4 justifica-centro my-4 mud- text-align-center"> <MudButton Variant="Variant.Filled" Color="Color.Primary" Link="authentication/profile">Hola, @context.User.Identity.Name!</MudButton> <MudButton Variant= "Variant.Filled" Color="Color.Primary" OnClick="BeginSignOut">Cerrar session</MudButton> </div> </Autorizado> <Não autorizado> <div class="pa-4 justifique-centro my-4 barro -text-align-center"> <MudButton Variant="Variante.Filled" Color="Color.Primary" Link="autenticación/registro">Registrar</MudButton> <MudButton Variant="Variante.Filled" Color=" Color .Secondary" Link="authentication/login">Sitzung starten</MudButton> </div> </NotAuthorized></AuthorizeView>@code{ privada asíncrona Task BeginSignOut(MouseEventArgs args) { await SignOutManager. SetSignOutState(); Navigation.NavigateTo("autenticação/fecho de sessão"); }}

As you can see, the above component is part of the navigation bar that is responsible for displaying the Login/Register/Logout buttons based on the application's authentication status.

Line 6-11: If the user is authenticated, they see a welcome message along with a logout button.
Line 12-17: If you are not authenticated, a login and register button will be displayed. As simple as that.

Next we fix the NavMenu component. Paste the following source code, replacing the content inNavMenu.razorComponents.

<MudNavMenu> <MudNavLink Href="/home" Icon="@Icons.Material.Outlined.Home"> Anfang </MudNavLink> <MudNavLink Href="/chat" Icon="@Icons.Material.Outlined.Dashboard"> Chat </MudNavLink> <MudNavLink Href="" Target="_blank" Icon="@Icons.Material.Outlined.QuestionAnswer"> Dokumentation / Guia </MudNavLink></MudNavMenu>

Let's add fictional content just because. Open Index.razor and paste the following. This is not very important. I only add it to make the app more beautiful.

@page "/home"@page "/" <MudContainer Style=" display: inline block; position: fixed; top: 0; bottom: 0; left: 0; right: 0; width: 900px; height: 300px; Border: Auto;"> <MudGrid> <MudItem xs="12" sm="12" md="12"> <MudText Align="Align.Center" Typo="Typo.h2" Class="mt-4" >Blazor Chat</MudText> <MudText Align="Align.Center" Type="Type.subtitle1" Class="smaller">Full chat app in Blazor WebAssembly 5.0 with SignalR and Identity. The MudBlazor component library is responsible for the user interface.</MudText> </MudGrid></MudContainer>

Let's run the application and see what we have now.

Building a Chat App with Blazor, Identity and SignalR - Definitive Guide (7)

Very cool, yes? So we have the sidebar to help us with navigation, some buttons in the navigation bar related to authentication, and finally the content right in the middle of the page.

Let's try to register some users in the system.

Be careful not to delete or modify the Authentication.razor component in the client project's Pages folder. This is a fairly important component that handles routing to identity pages (authentication).

Building a Chat App with Blazor, Identity and SignalR - Definitive Guide (8)
Building a Chat App with Blazor, Identity and SignalR - Definitive Guide (9)

This way I managed to register 3 users:Mukesh, John and Henryfor our testing purposes.

Add chat templates

Now let's move on to the main feature of our implementation. So far we have integrated Mudblazor into our app to make it more beautiful. Now let's add some model classes for chat and related entities.

An important step in this section relates to the architecture of the project. In the server project, in the Models folder, you can see an ApplicationUser class. This class is used to add additional properties to our identity user. For example we need to add the user's birthday, just add the DateTime property in this ApplicationUser class. Inherits fields from the IdentityUser class. do you have an idea, okay?

Due to certain dependency issues we would have to do thatMove this ApplicationUser class to the BlazorChat.Shared project🇧🇷 Make sure you also change the namespace of the ApplicationUser class. Delete the ApplicationUser class from the server project. It would also mean that there would be some reference issues that would arise as a result of this action. You can fix these problems simply by referencing the ApplicationUser class, which is now in the shared project. I hope I'm clear on that. Please do not hesitatelook at the repositoryin case of confusion.

Another action to take is to install the EntityFrameworkCore package in the shared project. I do all this to keep the project simple. Otherwise we would have to deal with many DTO classes. For the ideal way to develop with a clean architecture, check out the BlazorHero project.

Open the Package Manager Console, set the default project to BlazorChat.Shared and run the following command.


Let's start by adding our main chat message template. In the BlazorChat.Shared project, create a new class and name it ChatMessage.cs

public class ChatMessage { public long id { get; to found; } public string FromUserId { get; to found; } get public string ToUserId {; to found; } message public string { received; to found; } Public date and time creation date { get; to found; } Public virtual application user FromUser { get; to found; } public virtual ApplicationUser ToUser { get; to found; 🇧🇷

As you can understand, we are creating the ChatMessage entity which should contain all the details of a single chat message. This includes the identification, the user IDs of the participants, the actual message, the creation date and some virtual properties that may give us access to the properties of the participating users. It's clear, yes?

Extending the ApplicationUser class

Now that we've added the Chat Message entity model, let's extend ApplicationUser by adding some collections. The idea is that a certain user has sent and received many chats. This means that user A can be both the recipient of a series of chat messages and the sender of a collection of chats. That's why we added virtual collections so that users are tied to messages. This will later help us to extract the necessary details from the conversation.

Open ApplicationUser.cs in the shared project and add the following.

public class ApplicationUser: IdentityUser{ public virtual ICollection<ChatMessage> ChatMessagesFromUsers { get; Builder; } public virtual ICollection<ChatMessage> ChatMessagesToUsers { get; Builder; } public ApplicationUser() {ChatMessagesFromUsers = new HashSet<ChatMessage>(); ChatMessagesToUsers = new HashSet<ChatMessage>(); }}

Then open the Context class in the BlazorChat.Server project. It is usually located in the data folder named ApplicationDbContext. This is where you need to add the entities and constructor logic that will be directly reflected in our database. Since we created the ChatMessage entity, add it here.

public class ApplicationDbContext: ApiAuthorizationDbContext<ApplicationUser>{ public ApplicationDbContext(DbContextOptions options,IOptions<OperationalStoreOptions> operatingStoreOptions) : base(options, operatingStoreOptions){} public DbSet<ChatMessage> ChatMessages { get; Builder; } Invalid protection of a vacuum OnModelCreating(constructor ModelBuilder) { base.OnModelCreating(constructor); builder.Entity<ChatMessage>(entity => { entidad.HasOne(d => d.FromUser) .WithMany(p => p.ChatMessagesFromUsers) .HasForeignKey(d => d.FromUserId) .OnDelete(DeleteBehavior.ClientSetNull); entidad.HasOne(d => d.ToUser).WithMany(p => p.ChatMessagesToUsers).HasForeignKey(d => d.ToUserId).OnDelete(DeleteBehavior.ClientSetNull); }); }}

Line 4: Here we define a ChatMessage DbSet named ChatMessages. This is how our table will be named.
Line 8-10: Here we mention the one-to-many relationship between user and chat messages.

Add migrations and update the database

Now save all changes and open the package manager console. Remember to set the default project to the server project whenever you do anything with databases, since the data contexts reside within the server project.

Run the following commands. This will update your database, add the new ChatMessages table, and set up foreign key references.

add-migration chatModelsupdate-database
Building a Chat App with Blazor, Identity and SignalR - Definitive Guide (10)

Let's take a look at our database to see the changes and additions. You can see the expected result here.

Building a Chat App with Blazor, Identity and SignalR - Definitive Guide (11)

Chat Controller Settings

Now that we're done with the database implementation part, let's move on to the server-side implementation. Here we ideally need a controller that can return/send data to the ChatMessages table. For this project we need 4 endpoints on this controller. They are the following:

  • It accepts the participant ID and returns a list of ChatMessages that occurred between the 2 participants.
  • Returns a list of users available for chat.
  • Returns the details of a chat user.
  • Stores a specific chat message (with participant IDs) in the database.

Why do we need these endpoints? Let me make it clearer from a UI perspective. Our chat UI components ideally have 2 sections (think of the map for now).

  • Section A: To really talk,
  • Section B: to view available chat users.

If you click on a chat user in section B, the chat history should load with the user in section A. Also, we need to be able to send new messages. So these 3 endpoints are quite a must.

I think that makes a lot of sense. Now let's start with our controller. In the server project's Controllers folder, add and name a new controllerChatController.cs

[Route("api/[controller]")][ApiController][Autorizar]public class ChatController : ControllerBase{ private readonly UserManager<ApplicationUser> _userManager; aula specific ApplicationDbContext _context; Public ChatController(UserManager<ApplicationUser> userManager, ApplicationDbContext context) { _userManager = userManager; _contexto = context; }}

This is what our controller would initially look like. You can see that the entire controller is protected with an authorization attribute. I also inject ApplicationDbContext and UserManager into the controller's constructor. Now let's add each of the endpoints here.

Get all users

First, let's add all registered users to our database.

[HttpGet("users")]Public AsynchronousTask<IActionResult> GetUsersAsync(){ var userId = User.Claims.Where(a => a.Type == ClaimTypes.NameIdentifier).Select(a => a.Value). PrimeiroOPdefault(); var allUsers = await _context.Users.Where(user => user.Id != userId).ToListAsync(); return Ok (todos os usuários);}

Line 3: Get the user ID from the user claims.
Line 4: Returns a list of all registered users except the current user. You don't want to see your own name in the contact list, do you? 🇧🇷

Get user details

Similarly, using ApplicationDbContext, we return the details of a single user in terms of the passed user ID.

[HttpGet("users/{userId}")]public async Task<IActionResult> GetUserDetailsAsync(string userId){ var user = await _context.Users.Where(user => user.Id == userId).FirstOrDefaultAsync(); voltar Ok(usuário);}

Save chat message

Our client project would send a ChatMessage object to this endpoint with the message. In this endpoint we add the current user as the sender, the creation date and also the data of the receiving user. Finally, we store the data in our database.

[HttpPost]Tarefa assíncrona pública<IActionResult> SaveMessageAsync(ChatMessage message){ var userId = User.Claims.Where(a => a.Type == ClaimTypes.NameIdentifier).Select(a => a.Value).FirstOrDefault() ; Nachricht.FromUserId = userId; message.CreatedDate = DateTime.Now; message.ToUser = await _context.Users.Where(user => user.Id == message.ToUserId).FirstOrDefaultAsync(); aguarde _context.ChatMessages.AddAsync(message); zurück Ok(aguarda _context.SaveChangesAsync());}

Get a conversation between 2 participants

So here's the idea. The client would request the list of chat messages with a specific user. This API endpoint would retrieve the primary user's current user ID, retrieve data from the participant ID database, and return a list of chat messages.

[HttpGet("{contactId}")]public async Task<IActionResult> GetConversationAsync(string contactId){ var userId = User.Claims.Where(a => a.Type == ClaimTypes.NameIdentifier).Select(a => a .Valor).PrimeroOPredeterminado(); var mensajes = await _context.ChatMessages .where(h => (h.FromUserId == contactId && h.ToUserId == userId) || (h.FromUserId == userId && h.ToUserId == contactId)) .OrderBy(a => a.CreatedDate) .Include(a => a.FromUser) .Include(a => a.ToUser) .Select(x => new ChatMessage { FromUserId = x.FromUserId, Message = x.Message, CreatedDate = x .CreatedDate, Id = x.Id, ToUserId = x.ToUserId, ToUser = x.ToUser, FromUser = x.FromUser }).ToListAsync(); voltar Ok(mensagen);}

Line 4: Gets the current ClaimsPrincipal user ID.
Line 6 - Filters the chat message table, which contains user IDs and chat participants.
Line 7: For messages to be sorted by creation time.
Line 8-9: Also contains user entities.
Line 20: Returns the filtered chats.

Building a Chat App with Blazor, Identity and SignalR - Definitive Guide (12)

Introducing the hero Blazor!

Blazor Hero - A clean architecture template built for Blazor WebAssembly using MudBlazor components. It's as easy as running a command line CLI to start building awesome Blazor projects!


Aggregating SignalR Hub

Now for the hero of the show, SignalR.Let's try to understand what SignalR is and how it would help our app to be more alive. According to Wikipedia, SignalR is an open-source package for Microsoft technologies that essentially allows server code to send notifications to client-side applications. Therefore, if something changes on the server, you can notify all clients (browsers) of this change. It would be more like an event when triggered. It is also possible to have clients send notifications to other clients through the server using SignalR Hubs.

So the idea is that whenever a user types a message and hits send, they hit the hub function, which notifies the recipient (user/customer) that a new message has been received. In this case, we add a snack bar (toast notification) that alerts the participant to a new message. Also, every time the message is sent, to be real time, we have to make sure that a new message is shown for both users, even without them having to refresh their browsers. You'll understand more about this when we write the code.

Add a new class in the server project and name it SignalRHub.

public class SignalRHub: hub { public asynchronous task SendMessageAsync(ChatMessage, username string) {await Clients.All.SendAsync("ReceiveMessage", message, username); } public asynchronous task ChatNotificationAsync(chain message, chain receiver userid, chain sender userid) { await Clients.All.SendAsync("ReceiveChatNotification", message, receiver userid, chain sender userid) receiver, sender) ; 🇧🇷

Line 3: Notify all customers and add a new message to the chat.
Line 4 - Notifies the client logged in with a specific userid that a new message has been received.

Now let's register the SignalR service. Open Startup.cs from the server project and add the following in the fileconfigure servicesMethod.


Then add in the configure methodline 6for the UseEndpoints extension.

app.UseEndpoints(endpoints =>{ endpoints.MapRazorPages(); endpoints.MapControllers(); endpoints.MapFallbackToFile("index.html"); endpoints.MapHub<SignalRHub>("/signalRHub");});

So far we have completed our database design, API endpoints, adding and configuring SignalHub. Now the only task left is to get our BlazorChat.Client to consume the created API and style the chat components as needed. Let's start with the client-side implementation.

Chat Manager - Client Side

To use our API endpoints more cleanly, let's create an interface and its implementation. In BlazorChat.Client, create a new folder name manager and add a ChatManager.cs class and interfaceIChatManager.cs.

public interface IChatManager{ Task<List<ApplicationUser>> GetUsersAsync(); Tara SaveMessageAsync(ChatMessage message); Task<List<ChatMessage>> GetConversationAsync(string contactId); Tarea<Usuário do aplicativo> GetUserDetailsAsync(string userId);}
public ChatManager class: IChatManager{ private one-on-one HttpClient _httpClient; Public ChatManager (HttpClient httpClient) { _httpClient = httpClient; } public async Task<List<ChatMessage>> GetConversationAsync(string contactId) { return await _httpClient.GetFromJsonAsync<List<ChatMessage>>($"api/chat/{contactId}"); } tarea asíncrona public<usuário do aplicativo> GetUserDetailsAsync(string userId) { return await _httpClient.GetFromJsonAsync<ApplicationUser>($"api/chat/users/{userId}"); } public async Task<List<ApplicationUser>> GetUsersAsync() { var data = await _httpClient.GetFromJsonAsync<List<ApplicationUser>>("api/chat/users"); Devolver Dados; } Save Public Profile SaveMessageAsync(ChatMessage Menu) { await _httpClient.PostAsJsonAsync("api/chat", Menu); }}

Here we're using the HttpClient instance, which by default is already initialized. We have 4 methods corresponding to each end of the API. The HTTP response message is then converted into the required patterns and sent back to the recipient.

Before we forget, let's register this manager in the client application container.

builder.Services.AddTransient<ICatManager, ChatManager>();

Installing the SignalR client package

Open the package manager console and set the client project as the default project. Now run the following command to install the SignalR client. This is responsible for receiving server notifications sent by our previously created hub.


Necessary imports

As mentioned earlier in this article, we need to add more imports to the _Imports.razor component to make them available in other Razor components. Open _Imports.razor and add the following.

@inject NavigationManager _navigationManager@inject ISnackbar _snackBar@inject IJSRuntime _jsRuntime@inject AuthenticationStateProvider _stateProvider;@usando BlazorChat.Client.Managers@inject IChatManager _chatManager

Material Chat UI

Well, this is where the real fun comes in. Let's start building the UI for our chat component. This is a mockup of what we want our UI to look like. Kind?

Building a Chat App with Blazor, Identity and SignalR - Definitive Guide (13)

Let's start by creating a new RazorComponent in the client project's Pages folder. I call the component Chat.razor.

Building a Chat App with Blazor, Identity and SignalR - Definitive Guide (14)

In addition, we also need a C# class that binds to this Razor component. Make sure you give it a name similar to your component, but with an additional .cs extension.

Building a Chat App with Blazor, Identity and SignalR - Definitive Guide (15)

But before we move on to the chat component, some changes are required on the MainLayout page. Open the MainLayout.razor page and add the following code snippet to the @code section of the component.

Be sure to import the SignalR client namespace into the MainLayout.razor component with the following code:
@using Microsoft.AspNetCore.SignalR.Client; at the top of the component's code (under @inherits LayoutComponentBase).

hubConnection privada hubConnection;public bool IsConnected => hubConnection.State == HubConnectionState.Connected;protegido substituir tarefa assíncrona OnInitializedAsync(){ hubConnection = new HubConnectionBuilder().WithUrl(_navigationManager.ToAbsoluteUri("/signalRHub")).Build(); espera hubConnection.StartAsync(); hubConnection.On<string, string, string>("ReceiveChatNotification", (message, receiverUserId, senderUserId) => { if (CurrentUserId == receiverUserId) { _snackBar.Add(mensaje, Severity.Info, config => { config.VisibleStateDuration = 10000; config.HideTransitionDuration = 500; config.ShowTransitionDuration = 500; config.Action = "¿Chat?"; config.ActionColor = Color.Info; config.Onclick = snackbar => { _navigationManager.NavigateTo($"chat/{ senderUserId }"); devuelve Tarea.TareaCompletada; }; }); } }); var estado = esperar _stateProvider.GetAuthenticationStateAsync(); var usuario = estado.Usuario; CurrentUserId = usuario.Claims.Where(a => a.Type == "sub").Select(a => a.Value).FirstOrDefault();}

Line 1: Here we declare HubConnection. This is the connection that we will also pass to the chat component via the Cascading Parameter property.
Line 5 - Initializes the HubConnection instance when the app first ran. Note that you are subscribed to the singalrHub API endpoint. Do you remember that you assigned the same endpoint to SignalR Hub in the server project?

Line 6: Kick Initiates the connection.
Line 7 - When one of the clients sends a new message to the user who is now logged in, a notification is displayed in the UI. This is done with the help of this event.
Line 20 – Clicking on the generated notification redirects the user to the sender's chat box. I love this feature 😀
Line 28: Gets the current user ID of the claims principal.

Finally, in the HTML section, remember to add the @body tag before? Here we need to replace with the following code.

<CascadingValue Value="hubConnection"> @Cuerpo</CascadingValue>

This means that the hubConnection instance will be propagated to each child of the layout page that also contains our chat component.

Now let's return to our chat component. I'll start with the C# class Chat.razor.cs.

public partial class chat { [Cascade Parameters] public HubConnection hubConnection { get; to found; } [parameters] public string CurrentMessage { get; to found; } [parameters] public string CurrentUserId { get; to found; } [parameters] public string CurrentUserEmail { get; to found; } List<ChatMessage> private messages = new List<ChatMessage>(); private asynchronous task SubmitAsync() { if (!string.IsNullOrEmpty(CurrentMessage) && !string.IsNullOrEmpty(ContactId)) { var chatHistory = new ChatMessage() { Message = CurrentMessage, ToUserId = ContactId, CreatedDate = DateTime.Now }; wait _chatManager.SaveMessageAsync(chatHistory); chatHistory.FromUserId = CurrentUserId; await hubConnection.SendAsync("SendMessageAsync", chatHistory, CurrentUserEmail); current message = string.empty; } } Protected override asynchronous task OnInitializedAsync() { if (hubConnection == null) { hubConnection = new HubConnectionBuilder().WithUrl(_navigationManager.ToAbsoluteUri("/signalRHub")).Build(); } if (hubConnection.State == HubConnectionState.Disconnected) { Expect hubConnection.StartAsync(); } hubConnection.On<ChatMessage, string>("ReceiveMessage", async (message, username) => { if ((ContactId == message.ToUserId && CurrentUserId == message.FromUserId) || (ContactId == message.FromUserId && CurrentUserId == message.ToUserId)) { if ((ContactId == message.ToUserId && CurrentUserId == message.FromUserId)) { messages.Add(new ChatMessage { Message = message.Message, Date Created = message.Date Created , Source User = new ApplicationUser() { Email = CurrentUserEmail } } ); await hubConnection.SendAsync("ChatNotificationAsync", $"New message from {userName}", ContactId, CurrentUserId); } else if ((ContactId = = message. FromUserId && CurrentUserId == message.ToUserId)) { messages.Add(new ChatMessage { Message = message.Message, Creation Date = message.Creation Date, User = new Application User() { Email = Mail contact email } }); } The status has changed();} }); wait GetUsersAsync(); var state = expected _stateProvider.GetAuthenticationStateAsync(); var user = state.user; CurrentUserId = user.Claims.Where(a => a.Type == "sub").Select(a => a.Value).FirstOrDefault(); CurrentUserEmail = user.Claims.Where(a => a.Type == "name").Select(a => a.Value).FirstOrDefault(); if (!string.IsNullOrEmpty(ContactId)) { expected LoadUserChat(ContactId); } } Public List<ApplicationUser> ChatUsers = new List<ApplicationUser>(); [parameter] public string ContactEmail { get; to found; } [parameters] public string ContactId { get; to found; } Asynchronous task LoadUserChat(string userId) { var contact = await _chatManager.GetUserDetailsAsync(userId); ContactId = Contact.Id; contact email = contact.Email; _navigationManager.NavigateTo($"chat/{ContactId}"); messages = new list<chat message>(); Messages = waiting _chatManager.GetConversationAsync(ContactId); } private asynchronous task GetUsersAsync() { ChatUsers = await _chatManager.GetUsersAsync(); 🇧🇷

Line 3 - It is important to declare the CascadingParameter attribute because we will get the HubConnection instance from our main component, the MainLayout page.

Line 8 - 23 - When the user types a message and clicks send, this method is called. It first ensures that a valid recipient is available and the message is not empty. It then assigns that data to a new ChatMessage object and passes it to the API to store in the database. After that, SignalR is activated by passing the current user's email and message.

Line 24 - 60: Fired when this component loads. To be on the safe side, we first check that the received hubConnection instance is not null and has stopped working. If this is the case, this will be fixed as a first step. Line 34-50 processes the event to add the real-time incoming message to the chat box. We first check whether the current user ID or the selected contact is part of the conversation. In this case, add the message to the required chat field. Line 48 ensures that the component is re-rendered to make the app look more real-time.

Line 64 - 72 - When the user clicks on an available user from the contact list, this method is called. Also note that the conversation is loaded via the API.

Line 73 – 76: loads all registered users via the call API.

Finally, let's add HTML/components to the Chat.razor component.

@page "/chat/{ContactId}"@page "/chat"<div class="d-flex flex-grow-1 flex-row"> <MudPaper Elevation="25" Class="py-4 flex-grow -1"> <MudToolBar Dense="true"> @if (string.IsNullOrEmpty(ContactId)) { <MudIcon Icon="@Icons.Material.Outlined.Person" Style="margin-right:10px"></MudIcon > <MudText Typo="Typo.h6">chatten</MudText> } else { <MudIcon Icon="@Icons.Material.Outlined.ChatBubble" Style="margin-right:10px"></MudIcon> <MudText Tippfehler ="Typo.h6">@ContactEmail</MudText> } </MudToolBar> <div class="d-flex flex-column px-4" style="max-height:65vh;min-height:65vh; desbordamiento: Deplatzieren;" id="chatContainer"> @foreach (var mensaje en mensajes) { <div class="d-flex flex-row my-4"> <div class="mr-4"> <MudAvatar Color="Color.Secondary" Style="Höhe:50px; Breite:50px;">@message.FromUser.Email.ToUpper().FirstOrDefault()</MudAvatar> </div> <div> <MudText Typo="Typo.body1">@message .FromUser.Email</MudText> <MudText Typo="Typo.caption" Style="font-size: xx-small!important;">@message.CreatedDate.ToString("dd MMM, aaaa hh:mm tt") </MudText> <MudText Typo="Typo.body2" Style=" padding: 15px;background-color: var(--mud-palette-background-grey);border-radius: 5px;margin-top:5px"> @message.Message</MudText> </div> </div> } </div> <MudPaper Elevation="25" Class="d-flex flex-row px-2 mx-4" Style=""> < MudTextField T="string" Placeholder="Ingrese su mensaje..."DisableUnderLine="true" Class="mt-n2 mx-4" @bind-Value="CurrentMessage" For="@(()=> CurrentMessage) " /> <MudButton OnClick="SubmitAsync" StartIcon="@Icons.Material.Outlined.Send" Color="Color.Secondary" ButtonType="ButtonType.Butt on">S end</MudButton> </MudPaper> </MudPaper> <MudPaper Elevation="25" Class="pa-3 ml-6" MinWidth="350px"> <MudToolBar Dense="true"> <MudText Typo="Typo .h6" Inline="true" Class="mr-2">#</MudText> <MudText Typo="Typo.h6">contatos</MudText> </MudToolBar> <div class="d -flex flex- coluna px-4" style="altura máxima: 70vh; Mindesthöhe: 70vh; overflow:scroll;"> <MudList Clickable="true"> @foreach (var usuario en ChatUsers) { <MudListItem Class="pa-0 px-2" OnClick="@(() => LoadUserChat(user.Id) )"> <div class="d-flex flex-row mt-n1 mb-n1"> <div class="mr-4"> <MudBadge Class="my-2"> @if (usuario.Id == ContactId) { <MudAvatar Color="Color.Secondary" Style="height:50px; width:50px;"> @user.Email.ToUpper().FirstOrDefault() </MudAvatar> } else { <MudAvatar Color="Color.Dark" Style="height:50px; width:50px;">@user.Email.ToUpper().FirstOrDefault()</MudAvatar> } </MudBadge> </div> <div> <MudText Typo="Typo.body2" Class="mt-3 mb -n2">@usuario.Email</MudText> <MudText Typo="Typo.caption" Style="font-size: xx-small!important;">@user.Id</MudText> </div> </ div> </MudListItem> } </MudList> </div> </MudPaper></div>

Line 1 – 2: Declare the routes of this component.
Line 18-30: Scrolls through the chat message list and displays it in the browser.
Line 35: The Send Message button.
Line 45 – 69: Iterate through all registered users as received by the API.

Most of the code here is dedicated to improving the user interface. I'll skip your explanations because I think it's self-explanatory. If in doubt, leave a comment below.

Blazor chat in action.

So this is what our app looks like. I demonstrate the functions using 2 browser instances with different users. Sounds great right?

Building a Chat App with Blazor, Identity and SignalR - Definitive Guide (16)

additional adjustments

However, there is always room for improvement. Here are some things I considered as requirements when building this chat component for Blazor Hero.

  • One of the main problems was that although the system worked perfectly, the user had to scroll down to see the last message. I did a lot of research on this and finally came to using IJSRuntime to achieve it.
  • To cool down the system and get a better user experience, why not also play a notification sound when a new message arrives? Again, IJSRuntime was helpful.

I wonder why I go with JS? While Blazor can be written without relying on Javascript, there are still many scenarios and requirements not yet supported by C# in Blazor. Trust me, this is minimal JS usage.

Automatically scroll to the bottom of the chat.

In the wwwroot folder, create a new folder and name it js. Add a new javascript file here and name it scroll.js.

window.ScrollToBottom = (elementName) => {elemento = document.getElementById(elementName); elemento.scrollTop = elemento.scrollHeight - elemento.clientHeight;}

Now add the reference to this js file in the index.html of the wwwroot folder.

<command string src="js/scroll.js"></command string>

Now that our js is created, how and where do we call it?

First, we need to call the hover function when rendering occurs in the chat component. Luckily, Blazor has an event for that. Add the following method to the Chat.razor.cs class.

protected canceled async task OnAfterRenderAsync(bool firstRender){ await _jsRuntime.InvokeAsync<string>("ScrollToBottom", "chatContainer");}

This means that on every render the js function is called which in turn scrolls to the end of the div with the id.chatContainer.

soonhubConnection.On("ReceiveMessage", async(message, username) =>event, we need this js to be called. Add line 1 of the following code snippet just above the StateHasChanged method.

await _jsRuntime.InvokeAsync<string>("ScrollToBottom", "chatContainer");StateHasChanged();

Let's see how it works.

Building a Chat App with Blazor, Identity and SignalR - Definitive Guide (17)

Perfect! See how AutoScroll makes our app way cooler 😉

IMPORTANT: Due to browser caching it can sometimes happen that new JS/changes are not reflected in the browser, which also results in browser-level exceptions. I usually reload the page with CTRL+F5, which forces Chrome to reload the page without caching. This is very important when developing client-side applications.

Play notification sound.

Here's my favorite feature. BlazorHero suddenly felt like an enterprise app thanks to this cool feature. We will try to play a short MP3 notification when a new message arrives.

In the js folder, add a new javascript file and name it sons.js

ventana.PlayAudio = (elementName) => { document.getElementById(elementName).play();}

As before, make sure to add the sound.js reference to the index.html page.

Also, create a new folder under the wwwroot folder and name it media. Download an MP3 notification sound from the internet and put it in your media folder. I'm sure you will find tons of notification tones on the internet.

Then open the MainLayout.razor page again and add line 3 of the following snippet directly above MudThemeProvider.

@inherits LayoutComponentBase@usando Microsoft.AspNetCore.SignalR.Client;<audio id="notification" src="/media/notification.mp3" /><MudThemeProvider /><MudDialogProvider />

On the same layout page, in the OnInitializedAsync method, just below if (CurrentUserId == receiverUserId), add the following code snippet.

_jsRuntime.InvokeAsync<string>("PlayAudio", "Notification");

Run the app to test this functionality. Please note that you may need a full Chrome update by pressing CTRL + F5.

There you have it, we've now built a complete real-time chat app with Blazor using Identity, SignalR and Mudblazor components.

That's it for this extremely detailed guide. I hope I presented a clear solution for the community to work on.

Please consider supporting me by buying me a coffee.

Thanks for your visit. You can buy me a coffee by clicking the button below. Health!

Building a Chat App with Blazor, Identity and SignalR - Definitive Guide (18)


In this article, we'll build a complete chat app in Blazor from scratch using Identity and SignalR. The user interface is maintained with the help of MudBlazor. The source code for the full implementation can be found here. Did you learn something new? Let me know in the comment section. If you enjoyed this article, be sure to share it with your peers and Blazor developers. It helps me reach a wider audience and motivates me to produce more content on a regular basis.

Leave your valuable questions and suggestions in the comment section below. If you think you learned something new from this article, be sure to share it with your developer community. Happy coding!


How do I add identity to Blazor app? ›

Right click on the Blazor web project and select Add - New Scaffolded Item... Select Identity from both the left and middle panes in Add New Scaffolded Item dialog.

Does Blazor use SignalR? ›

Blazor Server

This option hosts Razor components in the ASP.NET Core Web App, which means that the application is 100% run on the server. Blazor Server uses SignalR to communicate between the server and the client via the WebSockets protocol.

What is the difference between Blazor server app and Blazor WebAssembly app? ›

Blazor Server apps have direct access to server and network resources where the app is executing. Because Blazor WebAssembly apps execute on a client, they don't have direct access to server and network resources.

How to implement SignalR in C#? ›

Publish to Azure
  1. Create a web project.
  2. Add the SignalR client library.
  3. Create a SignalR hub.
  4. Configure the project to use SignalR.
  5. Add code that sends messages from any client to all connected clients.
Feb 22, 2023

Can Blazor be used for mobile apps? ›

Mobile Blazor Bindings enable developers to build native and hybrid mobile apps using C# and . NET for Android, iOS, Windows, macOS, and Tizen using familiar web programming patterns. This means you can use the Blazor programming model and Razor syntax to define UI components and behaviors of an application.

Can we create mobile app using Blazor? ›

You can develop a native mobile app in Blazor using Experimental Mobile Blazor Bindings. This allows developers to develop mobile applications in C# and . NET for iOS and Android. It uses Razor syntax to define UI components and the underlying UI components are based on Xamarin.

Why is Blazor not popular? ›

Blazor projects are slow on the client-side because you have to download the entire dot net runtime along with the necessary DLL libraries on your browser. Additionally, Blazor apps have latency issues.

What are the downsides of Blazor? ›

Downsides of Blazor Server Applications

Since it runs on the server, it must be connected to the server all the time, so there's no offline support. Each interaction must go to the server which can cause network delays. Scalability can be a challenge because an application instance is created per user.

What are the limitations of Blazor WebAssembly? ›

The Blazor WebAssembly hosting model has the following limitations: The app is restricted to the capabilities of the browser. Capable client hardware and software (for example, WebAssembly support) is required. Download size is larger, and apps take longer to load.

Is SignalR obsolete? ›

This browser is no longer supported. Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.

How do I create a chat application using SignalR? ›

Set up the Project

In Solution Explorer, right-click the project and select Add > New Item. In Add New Item - SignalRChat, select Installed > Visual C# > Web > SignalR and then select SignalR Hub Class (v2). Name the class ChatHub and add it to the project. This step creates the ChatHub.

What is difference between SignalR and WebSocket? ›

WebSocket is an event-driven protocol that enables bidirectional, full-duplex communication between client and server. In contrast, SignalR is a solution that provides an abstraction layer on top of WebSockets, making it easier and faster to add realtime web functionality to apps.

Is Blazor fast enough? ›

Blazor is very fast in terms of build and debugging. Because it takes advantage of Visual Studio and the whole experience accumulated among its tools and plugins, the development and debugging can be really fast.

Is Blazor gaining popularity? ›

Blazor is one of the latest web development frameworks that enables developers to build web applications with C# and HTML. It has been gaining momentum drastically since its release in 2018 with its high efficiency and productive programming model.

Is Blazor slower than JavaScript? ›

In essence, you can write C# code where you'd previously use JavaScript, and Blazor will compile that C# to WebAssembly to allow it to run in the browser. However, I was a little surprised to find that when I tested the speed of it versus the application written in JavaScript, it was noticeably slower.

Should I use Blazor or react? ›

React is a well-established Javascript-based UI library that has numerous third-party libraries, packages, and extensions. These tools help streamline the development process and optimize React apps. Besides, React helps build high-performance SPAs, making it a better choice than Blazor.

Do companies use Blazor? ›

Who uses Blazor? 24 companies reportedly use Blazor in their tech stacks, including Scopeland Technology GmbH, Objectivity Software Development, and Weland Solutions AB.

What language does Blazor use? ›

Blazor is a framework for building interactive client-side web UI with . NET: Create rich interactive UIs using C# instead of JavaScript.

Is Blazor better than Angular? ›

Support: The size of the community using Angular is very high when compared to Blazor. So, the chances of finding a solution to the problem we face during the app development are high for Angular. Use of TypeScript: TypeScript has attributes that are way better than JavaScript's.

Can Blazor run offline? ›

Offline support. By default, apps created using the PWA template option have support for running offline. A user must first visit the app while they're online. The browser automatically downloads and caches all of the resources required to operate offline.

What are hybrid apps with Blazor? ›

Blazor Hybrid apps with WPF and Windows Forms

Razor components run natively in the Windows desktop and render to an embedded Web View. Using Blazor in WPF and Windows Forms enables you to add new UI to your existing Windows desktop apps that can be reused across platforms with . NET MAUI or on the web.

Who are Blazor competitors? ›

React, JavaScript, Vaadin, Xamarin, and Flutter are the most popular alternatives and competitors to Blazor.

Is Blazor SEO friendly? ›

A blazor WASM app is not SEO friendly. The search engine will not load it, so all it see is the content of index. html. If you want SEO, you would supply addition pages for the search engines.

Why use Blazor instead of JavaScript? ›

Deciding whether to use Blazor WebAssembly instead of one of the many JavaScript frameworks readily available largely depends on your team's experience and comfort level with learning a new language. If you or your team is more comfortable coding in C# vs JavaScript, Blazor is a solid option for you.

Is Blazor ready for production? ›

Yes, Blazor is ready to be used in production, it is a life changer, Blazor is a framework that optimizes development speed, helps considerably reducing code duplication and inconsistencies between front-end and api/backend models, and in turn it helps reducing bugs and development costs, in top of that, since Blazor ...

Can Blazor compete with angular? ›

Contrarily, Blazor is constantly changing and, despite its potential, lacks the maturity to rival Angular. Angular supports progressive web apps (PWAs). However, server-side Blazor cannot be utilized as a PWA. Instead, leveraging Angular tooling is more useful.

Does Blazor follow MVC? ›

Blazor applications are component-based. Blazor components can be used in existing ASP.NET MVC applications.

Is WebAssembly a security risk? ›

One of the most significant risks associated with WebAssembly is that it limits visibility into vulnerabilities. WebAssembly must run in a sandboxed environment, typically the same as the JavaScript sandbox.

Can Blazor WebAssembly be decompiled? ›

The WASM files can be decompiled using the WebAssembly-to-C decompiler.

Does WebAssembly have a future? ›

Wasm is the future: Providing a faster, more secure, and more efficient way to bring things together. Wasm, though more lightweight, may not replace containers any time soon. But you can expect Wasm to become part of a whole lot of software going forward.

What is better than SignalR? ›

There are many alternatives for signalR that are used, like Firebase, pusher, webRTC, RabbitMQ, gRPC, and MQTT.

How many clients can SignalR handle? ›

IIS on client operating systems has a limit of 10 concurrent connections. SignalR's connections are: Transient and frequently re-established. Not disposed immediately when no longer used.

Does SignalR keep connection alive? ›

Currently, SignalR client will send a keepalive ping 15s after connected. In some cases, the client connection terminates unexpectedly and the TCP become half-open before the first ping and the hub server will think the client won't send ping as it's an old version client.

How do I create a simple chat app? ›

How To Make a Chat App in 3 Easy Steps
  1. Name & logo. To make an app choose a template, or a blank app and set the name and icons.
  2. Set Features. Select features from the Chat app maker that suits best your needs.
  3. Publish. Push the Publish button, and we will do the rest to publish your Chat App. Build your chat app now.

What do you need to build a chat app? ›

Chat App Development Steps: Process Overview
  1. Create a Directory & Install Dependencies. ...
  2. Build the Front-End Chat Interface & Chat Client. ...
  3. Create and/or Connect the Back End (Chat Server) ...
  4. Prioritize Feature Expansion Based on User Feedback.
Mar 3, 2021

How to store SignalR chat in database? ›

You already implemented the chat, you just need to implement the database, using a manager, inject the manager in to your hub and save/get the messages. Since you did not provided any code, look at this example: Inject the database manager in to your hub using DI. This is just a example how you can do it.

What will replace WebSockets? ›

WebTransport is a new specification that could offer an alternative to WebSockets. For applications that need low-latency, event-driven communication between endpoints, WebSockets has been the go-to choice, but WebTransport may change that.

Which language is best for WebSockets? ›

A WebSocket server can be written in any server-side programming language that is capable of Berkeley sockets, such as C(++), Python, PHP, or server-side JavaScript.

What are the disadvantages of WebSockets? ›

The biggest downside to using WebSocket is the weight of the protocol and the hardware requirements that it brings with it. WebSocket requires a TCP implementation, which may or may not be a problem, but it also requires an HTTP implementation for the initial connection setup.

How do I add an identity framework to an existing project? ›

Configure Identity in . NET Core 6
  1. Install the NuGet Packages:
  2. Configure the connection string in appsettings file.
  3. Create the DbContext class.
  4. Register Database Context service in the Startup.
  5. Register the Identity service.
  6. Configure the Authentification and Authorization middleware:
  7. Add the first migration.
Jan 25, 2022

How do I add an identity provider? ›

Adding an IdP

Launch the SAML configuration page for your MCMP instance by opening https:// /platform/identityproviders (for example, Click Add Identity Provider. The Add Identity Provider screen displays.

How do you set up an identity? ›

Try these strategies to begin establishing a more concrete, independent identity.
  1. Define your values. Values and personal beliefs are fundamental aspects of identity. ...
  2. Make your own choices. ...
  3. Spend time alone. ...
  4. Consider how to achieve your ideals.
Jun 17, 2020

How do I get the Element ID in Blazor? ›

How do I get an element by ID or Class in Blazor?
  1. The getElementsByClassName() method returns a collection of all elements in the document with the specified class names.
  2. The getElementById() method returns a collection of all elements in the document with the specified ID names.
Aug 25, 2022

What is the difference between ASP.NET identity and aspnetcore identity? ›

One of the biggest differences when it comes to ASP.NET Core Identity compared to ASP.NET Identity is how little code you need to include in your project. ASP.NET Core Identity now ships as a Razor Class Library, meaning its UI and logic are all available from a NuGet package.

Is asp net Core Identity Secure? ›

ASP.NET Core 2.2 makes it easy to secure web pages with a user name and password. Simply click a checkbox and the sensitive pages are protected.

How do you set HttpContext user identity for an application manually? ›

You can achieve this by manually settings HttpContext. User: var identity = new ClaimsIdentity("Custom"); HttpContext. User = new ClaimsPrincipal(identity);

Can I create my own identity provider? ›

You can create and manage an IAM identity provider in the AWS Management Console or with AWS CLI, Tools for Windows PowerShell, or AWS API calls. After you create a SAML provider, you must create one or more IAM roles. A role is an identity in AWS that doesn't have its own credentials (as a user does).

Can I use Google as an identity provider? ›

To configure Google as an identity provider: Go to the Identity Providers page in the Google Cloud console. Click Add A Provider. Select Google from the list.

What are 3 things that make up your identity? ›

Ethnicity, Race and Culture

All of these factors influence our identities from the moment we're born, especially when our families identify strongly with these associations. Along with creating a foundation for our system of beliefs, these factors also influence our behaviors and attitudes.

How do you build a strong identity? ›

How to build a healthy self-identity
  1. Build positive relationships. It is estimated that more than 50% of young people often worry about what other people think of them. ...
  2. Self-reflection. ...
  3. Positive affirmation. ...
  4. Practice mindfulness. ...
  5. Seek treatment.
May 20, 2022

What is the difference between self and identity? ›

In general, 'identity' is used to refer to one's social 'face' – how one perceives how one is perceived by others. 'Self' is generally used to refer to one's sense of 'who I am and what I am' and is the way the term is employed in this book.

How do I bind an HTML element in Blazor? ›

How do you bind the value of the HTML element with a C# property in Blazor? You have to use the bind attribute to reflect the DOM element value in the C# property. @code { string name; private void PrintName() { Console. WriteLine(name); // Here the entered name will be printed. } }

How do I render raw HTML in Blazor? ›

Raw HTML can be rendered in Blazor by using the MarkupString. You can set the raw HTML as a string to any parameter and cast it in a markup string.

How to get value from HTML element in Blazor? ›

The value of an input element is updated in the wrapper with the change events of elements in Blazor. To get the current value for each character input, you must use the oninput event of the input element. This can be achieved by binding the oninput event (native event) using the @bind:event=“oninput“.


Top Articles
Latest Posts
Article information

Author: Nathanial Hackett

Last Updated: 25/01/2024

Views: 6180

Rating: 4.1 / 5 (52 voted)

Reviews: 83% of readers found this page helpful

Author information

Name: Nathanial Hackett

Birthday: 1997-10-09

Address: Apt. 935 264 Abshire Canyon, South Nerissachester, NM 01800

Phone: +9752624861224

Job: Forward Technology Assistant

Hobby: Listening to music, Shopping, Vacation, Baton twirling, Flower arranging, Blacksmithing, Do it yourself

Introduction: My name is Nathanial Hackett, I am a lovely, curious, smiling, lively, thoughtful, courageous, lively person who loves writing and wants to share my knowledge and understanding with you.