Samouczek: tworzenie aplikacji do czatu serwera Blazor Server

W tym samouczku pokazano, jak skompilować i zmodyfikować aplikację serwera Blazor. Dowiesz się, jak:

  • Utwórz prosty pokój rozmów przy użyciu szablonu aplikacji Blazor Server.
  • Praca ze składnikami Razor.
  • Użyj obsługi zdarzeń i powiązania danych w składnikach Razor.
  • Szybkie wdrażanie w usłudze aplikacja systemu Azure w programie Visual Studio.
  • Migrowanie z lokalnego usługi SignalR do usługi Azure SignalR Service.

Chcesz rozpocząć?

Wymagania wstępne

Masz problemy? Daj nam znać.

Tworzenie lokalnego pokoju rozmów w aplikacji Blazor Server

Począwszy od programu Visual Studio 2019 w wersji 16.2.0, usługa Azure SignalR Service jest wbudowana w proces publikowania aplikacji internetowej, aby zarządzać zależnościami między aplikacją internetową i usługą SignalR. Możesz pracować w lokalnym wystąpieniu usługi SignalR w lokalnym środowisku projektowym i pracować w usłudze Azure SignalR Service dla usługi aplikacja systemu Azure Service w tym samym czasie bez żadnych zmian w kodzie.

  1. Utwórz aplikację do czatu platformy Blazor:

    1. W programie Visual Studio wybierz pozycję Utwórz nowy projekt.

    2. Wybierz pozycję Aplikacja Blazor.

    3. Nadaj aplikacji nazwę i wybierz folder.

    4. Wybierz szablon Aplikacja serwera Blazor.

      Uwaga

      Upewnij się, że masz już zainstalowany zestaw .NET Core SDK 3.0 lub nowszy, aby umożliwić programowi Visual Studio poprawne rozpoznawanie platformy docelowej.

      In Create a new project, select the Blazor app template.

    5. Projekt można również utworzyć, uruchamiając dotnet new polecenie w interfejsie wiersza polecenia platformy .NET:

      dotnet new blazorserver -o BlazorChat
      
  2. Dodaj nowy plik języka C# o nazwie BlazorChatSampleHub.cs i utwórz nową klasę BlazorChatSampleHub wyprowadzaną z Hub klasy dla aplikacji do czatu. Aby uzyskać więcej informacji na temat tworzenia centrów, zobacz Tworzenie i używanie centrów.

    using System;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.SignalR;
    
    namespace BlazorChat
    {
        public class BlazorChatSampleHub : Hub
        {
            public const string HubUrl = "/chat";
    
            public async Task Broadcast(string username, string message)
            {
                await Clients.All.SendAsync("Broadcast", username, message);
            }
    
            public override Task OnConnectedAsync()
            {
                Console.WriteLine($"{Context.ConnectionId} connected");
                return base.OnConnectedAsync();
            }
    
            public override async Task OnDisconnectedAsync(Exception e)
            {
                Console.WriteLine($"Disconnected {e?.Message} {Context.ConnectionId}");
                await base.OnDisconnectedAsync(e);
            }
        }
    }
    
  3. Dodaj punkt końcowy dla centrum w metodzie Startup.Configure() .

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapBlazorHub();
        endpoints.MapFallbackToPage("/_Host");
        endpoints.MapHub<BlazorChatSampleHub>(BlazorChatSampleHub.HubUrl);
    });
    
  4. Zainstaluj pakiet, Microsoft.AspNetCore.SignalR.Client aby używać klienta usługi SignalR.

    dotnet add package Microsoft.AspNetCore.SignalR.Client --version 3.1.7
    
  5. Utwórz nowy składnik Razor o nazwie ChatRoom.razor w folderze w Pages celu zaimplementowania klienta usługi SignalR. Wykonaj poniższe kroki lub użyj pliku ChatRoom.razor .

    1. Dodaj dyrektywę @page i instrukcje using. Użyj dyrektywy , @inject aby wstrzyknąć usługę NavigationManager .

      @page "/chatroom"
      @inject NavigationManager navigationManager
      @using Microsoft.AspNetCore.SignalR.Client;
      
    2. @code W sekcji dodaj następujących członków do nowego klienta usługi SignalR w celu wysyłania i odbierania komunikatów.

      @code {
          // flag to indicate chat status
          private bool _isChatting = false;
      
          // name of the user who will be chatting
          private string _username;
      
          // on-screen message
          private string _message;
      
          // new message input
          private string _newMessage;
      
          // list of messages in chat
          private List<Message> _messages = new List<Message>();
      
          private string _hubUrl;
          private HubConnection _hubConnection;
      
          public async Task Chat()
          {
              // check username is valid
              if (string.IsNullOrWhiteSpace(_username))
              {
                  _message = "Please enter a name";
                  return;
              };
      
              try
              {
                  // Start chatting and force refresh UI.
                  _isChatting = true;
                  await Task.Delay(1);
      
                  // remove old messages if any
                  _messages.Clear();
      
                  // Create the chat client
                  string baseUrl = navigationManager.BaseUri;
      
                  _hubUrl = baseUrl.TrimEnd('/') + BlazorChatSampleHub.HubUrl;
      
                  _hubConnection = new HubConnectionBuilder()
                      .WithUrl(_hubUrl)
                      .Build();
      
                  _hubConnection.On<string, string>("Broadcast", BroadcastMessage);
      
                  await _hubConnection.StartAsync();
      
                  await SendAsync($"[Notice] {_username} joined chat room.");
              }
              catch (Exception e)
              {
                  _message = $"ERROR: Failed to start chat client: {e.Message}";
                  _isChatting = false;
              }
          }
      
          private void BroadcastMessage(string name, string message)
          {
              bool isMine = name.Equals(_username, StringComparison.OrdinalIgnoreCase);
      
              _messages.Add(new Message(name, message, isMine));
      
              // Inform blazor the UI needs updating
              InvokeAsync(StateHasChanged);
          }
      
          private async Task DisconnectAsync()
          {
              if (_isChatting)
              {
                  await SendAsync($"[Notice] {_username} left chat room.");
      
                  await _hubConnection.StopAsync();
                  await _hubConnection.DisposeAsync();
      
                  _hubConnection = null;
                  _isChatting = false;
              }
          }
      
          private async Task SendAsync(string message)
          {
              if (_isChatting && !string.IsNullOrWhiteSpace(message))
              {
                  await _hubConnection.SendAsync("Broadcast", _username, message);
      
                  _newMessage = string.Empty;
              }
          }
      
          private class Message
          {
              public Message(string username, string body, bool mine)
              {
                  Username = username;
                  Body = body;
                  Mine = mine;
              }
      
              public string Username { get; set; }
              public string Body { get; set; }
              public bool Mine { get; set; }
      
              public bool IsNotice => Body.StartsWith("[Notice]");
      
              public string CSS => Mine ? "sent" : "received";
          }
      }
      
    3. Dodaj znaczniki interfejsu użytkownika przed sekcją @code w celu interakcji z klientem usługi SignalR.

      <h1>Blazor SignalR Chat Sample</h1>
      <hr />
      
      @if (!_isChatting)
      {
          <p>
              Enter your name to start chatting:
          </p>
      
          <input type="text" maxlength="32" @bind="@_username" />
          <button type="button" @onclick="@Chat"><span class="oi oi-chat" aria-hidden="true"></span> Chat!</button>
      
          // Error messages
          @if (_message != null)
          {
              <div class="invalid-feedback">@_message</div>
              <small id="emailHelp" class="form-text text-muted">@_message</small>
          }
      }
      else
      {
          // banner to show current user
          <div class="alert alert-secondary mt-4" role="alert">
              <span class="oi oi-person mr-2" aria-hidden="true"></span>
              <span>You are connected as <b>@_username</b></span>
              <button class="btn btn-sm btn-warning ml-md-auto" @onclick="@DisconnectAsync">Disconnect</button>
          </div>
          // display messages
          <div id="scrollbox">
              @foreach (var item in _messages)
              {
                  @if (item.IsNotice)
                  {
                      <div class="alert alert-info">@item.Body</div>
                  }
                  else
                  {
                      <div class="@item.CSS">
                          <div class="user">@item.Username</div>
                          <div class="msg">@item.Body</div>
                      </div>
                  }
              }
              <hr />
              <textarea class="input-lg" placeholder="enter your comment" @bind="@_newMessage"></textarea>
              <button class="btn btn-default" @onclick="@(() => SendAsync(_newMessage))">Send</button>
          </div>
      }
      
  6. Zaktualizuj składnik, NavMenu.razor aby wstawić nowy NavLink składnik, aby połączyć się z pokojem rozmów w obszarze NavMenuCssClass.

    <li class="nav-item px-3">
        <NavLink class="nav-link" href="chatroom">
            <span class="oi oi-chat" aria-hidden="true"></span> Chat room
        </NavLink>
    </li>
    
  7. Dodaj kilka klas CSS do site.css pliku, aby stylizować elementy interfejsu użytkownika na stronie czatu.

    /* improved for chat text box */
    textarea {
        border: 1px dashed #888;
        border-radius: 5px;
        width: 80%;
        overflow: auto;
        background: #f7f7f7
    }
    
    /* improved for speech bubbles */
    .received, .sent {
        position: relative;
        font-family: arial;
        font-size: 1.1em;
        border-radius: 10px;
        padding: 20px;
        margin-bottom: 20px;
    }
    
    .received:after, .sent:after {
        content: '';
        border: 20px solid transparent;
        position: absolute;
        margin-top: -30px;
    }
    
    .sent {
        background: #03a9f4;
        color: #fff;
        margin-left: 10%;
        top: 50%;
        text-align: right;
    }
    
    .received {
        background: #4CAF50;
        color: #fff;
        margin-left: 10px;
        margin-right: 10%;
    }
    
    .sent:after {
        border-left-color: #03a9f4;
        border-right: 0;
        right: -20px;
    }
    
    .received:after {
        border-right-color: #4CAF50;
        border-left: 0;
        left: -20px;
    }
    
    /* div within bubble for name */
    .user {
        font-size: 0.8em;
        font-weight: bold;
        color: #000;
    }
    
    .msg {
        /*display: inline;*/
    }
    
  8. Naciśnij klawisz F5 , aby uruchomić aplikację. Teraz możesz zainicjować czat:

    An animated chat between Bob and Alice is shown. Alice says Hello, Bob says Hi.

Masz problemy? Daj nam znać.

Publikowanie na platformie Azure

Podczas wdrażania aplikacji Blazor w usłudze aplikacja systemu Azure Zalecamy użycie usługi Azure SignalR Service. Usługa Azure SignalR Service umożliwia skalowanie aplikacji Blazor Server w górę do dużej liczby współbieżnych połączeń usługi SignalR. Ponadto globalne zasięg usługi SignalR i centra danych o wysokiej wydajności znacznie pomagają w zmniejszeniu opóźnienia ze względu na lokalizację geograficzną.

Ważne

W aplikacji serwera Blazor stany interfejsu użytkownika są zachowywane po stronie serwera, co oznacza, że do zachowania stanu jest wymagana lepka sesja serwera. Jeśli istnieje jeden serwer aplikacji, sesje sticky są zapewniane zgodnie z projektem. Jeśli jednak istnieje wiele serwerów aplikacji, istnieje prawdopodobieństwo, że negocjacje klienta i połączenie mogą przejść do różnych serwerów, co może prowadzić do niespójnego zarządzania stanem interfejsu użytkownika w aplikacji Blazor. W związku z tym zaleca się włączenie sesji serwera sticky, jak pokazano poniżej w appsettings.json:

"Azure:SignalR:ServerStickyMode": "Required"
  1. Kliknij prawym przyciskiem myszy projekt i przejdź do pozycji Publikuj. Użyj następujących ustawień:

    • Element docelowy: Azure
    • Konkretny element docelowy: obsługiwane są wszystkie typy usługi aplikacja systemu Azure.
    • App Service: utwórz lub wybierz wystąpienie usługi App Service.

    The animation shows selection of Azure as target, and then Azure App Serice as specific target.

  2. Dodaj zależność usługi Azure SignalR Service.

    Po utworzeniu profilu publikowania zostanie wyświetlony komunikat z zaleceniem, aby dodać usługę Azure SignalR Service w obszarze Zależności usługi. Wybierz pozycję Konfiguruj , aby utworzyć nową lub wybrać istniejącą usługę Azure SignalR Service w okienku.

    On Publish, the link to Configure is highlighted.

    Zależność usługi przeprowadzi następujące działania, aby umożliwić aplikacji automatyczne przełączenie się do usługi Azure SignalR Service podczas pracy na platformie Azure:

    • Zaktualizuj HostingStartupAssembly usługę Azure SignalR Service.
    • Dodaj odwołanie do pakietu NuGet usługi Azure SignalR Service.
    • Zaktualizuj właściwości profilu, aby zapisać ustawienia zależności.
    • Skonfiguruj magazyn wpisów tajnych zgodnie z wybranym wyborem.
    • Dodaj konfigurację w appsettings.json , aby aplikacja docelowa usługi Azure SignalR Service.

    On Summary of changes, the checkboxes are used to select all dependencies.

  3. Opublikuj aplikację.

    Teraz aplikacja jest gotowa do opublikowania. Po zakończeniu procesu publikowania aplikacja zostanie automatycznie uruchomiona w przeglądarce.

    Uwaga

    Uruchomienie aplikacji może wymagać pewnego czasu z powodu opóźnienia wdrożenia usługi aplikacja systemu Azure Service. Możesz użyć narzędzi debugera przeglądarki (zwykle przez naciśnięcie klawisza F12), aby upewnić się, że ruch został przekierowany do usługi Azure SignalR Service.

    Blazor SignalR Chat Sample has a text box for your name, and a Chat! button to start a chat.

Masz problemy? Daj nam znać.

Włączanie usługi Azure SignalR Service na potrzeby programowania lokalnego

  1. Dodaj odwołanie do zestawu SDK usługi Azure SignalR przy użyciu następującego polecenia.

    dotnet add package Microsoft.Azure.SignalR
    
  2. Dodaj wywołanie metody AddAzureSignalR() w metodzie , Startup.ConfigureServices() jak pokazano poniżej.

    public void ConfigureServices(IServiceCollection services)
    {
        ...
        services.AddSignalR().AddAzureSignalR();
        ...
    }
    
  3. Skonfiguruj usługę Azure SignalR Service parametry połączenia w appsettings.json lub za pomocą narzędzia Secret Manager.

Uwaga

Krok 2 można zastąpić konfigurowaniem zestawów uruchamiania hostingu w celu korzystania z zestawu SDK usługi SignalR.

  1. Dodaj konfigurację, aby włączyć usługę Azure SignalR Service w appsettings.json:

    "Azure": {
      "SignalR": {
        "Enabled": true,
        "ConnectionString": <your-connection-string>       
      }
    }
    
    
  2. Skonfiguruj zestaw uruchamiania hostingu, aby używał zestawu SDK usługi Azure SignalR. Edytuj uruchamianie Ustawienia.json i dodaj konfigurację podobną do poniższego przykładu w pliku environmentVariables:

    "environmentVariables": {
        ...,
       "ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.Azure.SignalR"
     }
    
    

Masz problemy? Daj nam znać.

Czyszczenie zasobów

Aby wyczyścić zasoby utworzone w tym samouczku, usuń grupę zasobów za pomocą witryny Azure Portal.

Dodatkowe zasoby

Następne kroki

W tym samouczku zawarto informacje na temat wykonywania następujących czynności:

  • Utwórz prosty pokój rozmów przy użyciu szablonu aplikacji Blazor Server.
  • Praca ze składnikami Razor.
  • Użyj obsługi zdarzeń i powiązania danych w składnikach Razor.
  • Szybkie wdrażanie w usłudze aplikacja systemu Azure w programie Visual Studio.
  • Migrowanie z lokalnego usługi SignalR do usługi Azure SignalR Service.

Przeczytaj więcej na temat wysokiej dostępności: