Dela via


Flera värdbaserade ASP.NET Core-appar Blazor WebAssembly

Anmärkning

Det här är inte den senaste versionen av den här artikeln. Den senaste versionen av den här artikeln finns i .NET 7-versionen.

Den här artikeln beskriver hur du konfigurerar en värdbaserad Blazor WebAssembly app som värd för flera Blazor WebAssembly appar.

Konfiguration

Välj den version av den här artikeln som matchar dina värdkrav, antingen port/domänvärd (till exempel :5001/:5002 eller firstapp.com/secondapp.com) eller vägvärd med underkatalog (till exempel /FirstApp och /SecondApp).

Med det aktuella värdvalet omfattar den här artikeln port/domänvärd (till exempel :5001/:5002 eller firstapp.com/secondapp.com).

I följande exempel:

  • Projektnamnet för den värdbaserade Blazor WebAssembly appen finns MultipleBlazorApps i en mapp med namnet MultipleBlazorApps.
  • De tre projekten i lösningen innan en andra klientapp läggs till finns MultipleBlazorApps.Client i Client mappen, MultipleBlazorApps.Server i Server mappen och MultipleBlazorApps.Shared i Shared mappen.
  • Den första (första) klientappen är standardklientprojektet för lösningen som skapats Blazor WebAssembly från projektmallen.
  • En andra klientapp läggs till i lösningen i MultipleBlazorApps.SecondClient en mapp med namnet SecondClient.
  • Om du vill kan serverprojektet (MultipleBlazorApps.Server) hantera sidor eller vyer som en Razor Pages- eller MVC-app.
  • Den första klientappen är tillgänglig i en webbläsare på port 5001 eller med en värd för firstapp.com. Den andra klientappen är tillgänglig i en webbläsare på port 5002 eller med en värd av secondapp.com.

Med den aktuella markeringen beskriver den här artikeln routningsundersökvägsvärd (till exempel /FirstApp och /SecondApp).

I följande exempel:

  • Projektnamnet för den värdbaserade Blazor WebAssembly appen finns MultipleBlazorApps i en mapp med namnet MultipleBlazorApps.
  • De tre projekten i lösningen innan en andra klientapp läggs till finns MultipleBlazorApps.Client i Client mappen, MultipleBlazorApps.Server i Server mappen och MultipleBlazorApps.Shared i Shared mappen.
  • Den första (första) klientappen är standardklientprojektet för lösningen som skapats Blazor WebAssembly från projektmallen.
  • En andra klientapp läggs till i lösningen i MultipleBlazorApps.SecondClient en mapp med namnet SecondClient.
  • Om du vill kan serverprojektet (MultipleBlazorApps.Server) hantera sidor eller vyer som en formell Razor pages- eller MVC-app.
  • Båda klientapparna använder standardporten MultipleBlazorApps.Server som definieras av projektets Properties/launchSettings.json fil i dess applicationUrl värde. Den första klientappen är tillgänglig i en webbläsare vid /FirstApp underkatalogen. Den andra klientappen är tillgänglig genom en webbläsare på /SecondApp understig.

Exemplen som visas i den här artikeln kräver ytterligare konfiguration för:

  • Åtkomst till apparna direkt på exempelvärddomänerna firstapp.com och secondapp.com.
  • Certifikat för klientapparna för att aktivera TLS/HTTPS-säkerhet.
  • Konfigurera serverappen som en Razor Pages-app för följande funktioner:
    • Integrering av Razor komponenter i sidor eller vyer.
    • Förrenderar Razor-komponenter.

Ovanstående konfigurationer ligger utanför omfånget för den här artikeln. Mer information finns i följande resurser:

Använd en befintlig värdbaserad Blazor WebAssemblylösning eller skapa en ny värdbaserad Blazor WebAssembly lösning från projektmallen Blazor WebAssembly genom att skicka -ho|--hosted alternativet om du använder .NET CLI eller markerar kryssrutan ASP.NET Core Hosted i Visual Studio när projektet skapas i IDE.

Använd en mapp för lösningen med namnet MultipleBlazorApps och ge projektet MultipleBlazorAppsnamnet .

Skapa en ny mapp i lösningen med namnet SecondClient. I den nya mappen lägger du till en andra Blazor WebAssembly klientapp med namnet MultipleBlazorApps.SecondClient. Lägg till projektet som en fristående Blazor WebAssembly app. Om du vill skapa en fristående Blazor WebAssembly app ska du inte godkänna -ho|--hosted alternativet om du använder .NET CLI eller inte använder kryssrutan ASP.NET Core Hosted om du använder Visual Studio.

Gör följande ändringar i MultipleBlazorApps.SecondClient projektet:

  • Kopiera komponenten FetchData (Pages/FetchData.razor) från Client/Pages mappen till SecondClient/Pages mappen. Det här steget krävs eftersom en fristående Blazor WebAssembly app inte anropar ett Server projekts kontrollant för väderdata. Den använder en statisk datafil. Genom att kopiera komponenten FetchData till det tillagda projektet gör den andra klientappen även ett webb-API-anrop till server-API:et för väderdata.
  • SecondClient/wwwroot/sample-data Ta bort mappen eftersom weather.json filen i mappen inte används.

I följande tabell beskrivs lösningens mappar och projektnamn när SecondClient mappen och MultipleBlazorApps.SecondClient projektet har lagts till.

Fysisk mapp Projektnamn Beskrivning
Client MultipleBlazorApps.Client Blazor WebAssembly klientapplikation
SecondClient MultipleBlazorApps.SecondClient Blazor WebAssembly klientapplikation
Server MultipleBlazorApps.Server ASP.NET Core-serverapp
Shared MultipleBlazorApps.Shared Projekt för delade resurser

Projektet MultipleBlazorApps.Server hanterar de två Blazor WebAssembly klientapparna och tillhandahåller väderdata till klientapparnas FetchData komponenter via en MVC-styrenhet. MultipleBlazorApps.Server Alternativt kan projektet även hantera sidor eller vyer som en traditionell Razor pages- eller MVC-app. Steg för att aktivera betjänande sidor eller vyer beskrivs senare i den här artikeln.

Anmärkning

Demonstrationen i den här artikeln använder namn på statiska webbtillgångssökvägar FirstApp för MultipleBlazorApps.Client projektet och SecondApp för MultipleBlazorApps.SecondClient projektet. Namnen "FirstApp" och "SecondApp" är bara i demonstrationssyfte. Andra namn är acceptabla för att särskilja klientappar, till exempel App1/App2,Client1/Client2 , 1/2eller liknande namngivningsscheman.

När begäranden dirigeras till klientapparna via en port eller domän används "FirstApp" och "SecondApp" internt för att dirigera begäranden och hantera svar för statiska tillgångar och visas inte i webbläsarens adressfält.

Anmärkning

Demonstrationen i den här artikeln använder namn på statiska webbtillgångssökvägar FirstApp för MultipleBlazorApps.Client projektet och SecondApp för MultipleBlazorApps.SecondClient projektet. Namnen "FirstApp" och "SecondApp" är bara i demonstrationssyfte. Andra namn är acceptabla för att särskilja klientappar, till exempel App1/App2,Client1/Client2 , 1/2eller liknande namngivningsscheman.

"FirstApp" och "SecondApp" visas också i webbläsarens adressfält eftersom begäranden dirigeras till de två klientapparna med dessa namn. Andra giltiga URL-routningssegment stöds och routningssegmenten behöver inte strikt matcha de namn som används för att dirigera statiska webbtillgångar internt. Att använda "FirstApp" och "SecondApp" för både intern routning av statiska tillgångar och routning av appbegäran är bara för konvektion i den här artikelns exempel.

I den första klientappens projektfil (MultipleBlazorApps.Client.csproj) lägger du till en <StaticWebAssetBasePath> egenskap i en <PropertyGroup> med värdet FirstApp för för att ange bassökvägen för projektets statiska tillgångar:

<StaticWebAssetBasePath>FirstApp</StaticWebAssetBasePath>

MultipleBlazorApps.SecondClient I appens projektfil (MultipleBlazorApps.SecondClient.csproj):

  • Lägg till en <StaticWebAssetBasePath> egenskap i en <PropertyGroup> med värdet SecondApp:

    <StaticWebAssetBasePath>SecondApp</StaticWebAssetBasePath>
    
  • Lägg till en projektreferens för MultipleBlazorApps.Shared-projektet till en <ItemGroup>.

    <ItemGroup>
      <ProjectReference Include="..\Shared\MultipleBlazorApps.Shared.csproj" />
    </ItemGroup>
    

I serverappens projektfil (Server/MultipleBlazorApps.Server.csproj) skapar du en projektreferens för den tillagda MultipleBlazorApps.SecondClient klientappen i en <ItemGroup>:

<ProjectReference Include="..\SecondClient\MultipleBlazorApps.SecondClient.csproj" />

I serverappens Properties/launchSettings.json fil konfigurerar du applicationUrl profilen Kestrel (MultipleBlazorApps.Server) för åtkomst till klientapparna på portarna 5001 och 5002. Om du konfigurerar din lokala miljö för att använda exempeldomänerna kan URL:er för applicationUrl använda firstapp.com och secondapp.com inte använda portarna.

Anmärkning

Användningen av portar i den här demonstrationen ger åtkomst till klientprojekten i en lokal webbläsare utan att du behöver konfigurera en lokal värdmiljö så att webbläsare kan komma åt klientapparna via värdkonfigurationerna firstapp.com och secondapp.com. I produktionsscenarier är en typisk konfiguration att använda underdomäner för att särskilja klientapparna.

Till exempel:

  • Portarna tas bort från konfigurationen av den här demonstrationen.
  • Värdarna ändras så att de använder underdomäner, till exempel www.contoso.com för webbplatsbesökare och admin.contoso.com administratörer.
  • Ytterligare värdar kan inkluderas för ytterligare klientappar och minst en värd till krävs om serverappen också är en Razor Pages- eller MVC-app som hanterar sidor eller vyer.

Om du planerar att visa sidor eller vyer från serverappen använder du följande applicationUrl inställning i Properties/launchSettings.json filen, vilket tillåter följande åtkomst:

  • Razor Valfritt svarar Pages- eller MVC-appen (MultipleBlazorApps.Server projektet) på begäranden på port 5000.
  • Svar på begäranden för den första klienten (MultipleBlazorApps.Client projektet) finns på port 5001.
  • Svar på begäranden för den andra klienten (MultipleBlazorApps.SecondClient projektet) finns på port 5002.
"applicationUrl": "https://localhost:5000;https://localhost:5001;https://localhost:5002",

Om du inte planerar att serverappen ska hantera sidor eller vyer och endast betjäna klientapparna Blazor WebAssembly använder du följande inställning, som tillåter följande åtkomst:

  • Den första klientappen svarar på port 5001.
  • Den andra klientappen svarar på port 5002.
"applicationUrl": "https://localhost:5001;https://localhost:5002",

Ta bort följande kod i serverappens Program.cs fil, som visas efter anropet till UseHttpsRedirection:

  • Om du planerar att visa sidor eller vyer från serverappen tar du bort följande kodrader:

    - app.UseBlazorFrameworkFiles();
    
    - app.MapFallbackToFile("index.html");
    
  • Om du planerar att serverappen endast ska hantera klientapparna Blazor WebAssembly tar du bort följande kod:

    - app.UseBlazorFrameworkFiles();
    
    ...
    
    - app.UseRouting();
    
    - app.MapRazorPages();
    - app.MapControllers();
    - app.MapFallbackToFile("index.html");
    

    Lämna Static File Middleware på plats:

    app.UseStaticFiles();
    
  • Lägg till mellanprogram som mappar begäranden till klientapparna. I följande exempel konfigureras mellanprogrammet så att det körs när begärandeporten antingen är 5001 för den första klientappen eller 5002 för den andra klientappen, eller om värd för begäran antingen firstapp.com är för den första klientappen eller secondapp.com för den andra klientappen.

    Anmärkning

    Användning av värdarna (firstapp.com/secondapp.com) i ett lokalt system med en lokal webbläsare kräver ytterligare konfiguration som ligger utanför omfånget för den här artikeln. För lokal testning av det här scenariot rekommenderar vi att du använder portar. Typiska produktionsappar är konfigurerade för att använda underdomäner, till exempel www.contoso.com för webbplatsbesökare och admin.contoso.com administratörer. Med rätt DNS- och serverkonfiguration, som ligger utanför den här artikelns omfång och är beroende av de tekniker som används, svarar appen på begäranden på alla värdar som namnges i följande kod.

    Där du tog bort app.UseBlazorFrameworkFiles(); raden från Program.csplacerar du följande kod:

    app.MapWhen(ctx => ctx.Request.Host.Port == 5001 || 
        ctx.Request.Host.Equals("firstapp.com"), first =>
    {
        first.Use((ctx, nxt) =>
        {
            ctx.Request.Path = "/FirstApp" + ctx.Request.Path;
            return nxt();
        });
    
        first.UseBlazorFrameworkFiles("/FirstApp");
        first.UseStaticFiles();
        first.UseStaticFiles("/FirstApp");
        first.UseRouting();
    
        first.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
            endpoints.MapFallbackToFile("/FirstApp/{*path:nonfile}", 
                "FirstApp/index.html");
        });
    });
    
    app.MapWhen(ctx => ctx.Request.Host.Port == 5002 || 
        ctx.Request.Host.Equals("secondapp.com"), second =>
    {
        second.Use((ctx, nxt) =>
        {
            ctx.Request.Path = "/SecondApp" + ctx.Request.Path;
            return nxt();
        });
    
        second.UseBlazorFrameworkFiles("/SecondApp");
        second.UseStaticFiles();
        second.UseStaticFiles("/SecondApp");
        second.UseRouting();
    
        second.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
            endpoints.MapFallbackToFile("/SecondApp/{*path:nonfile}", 
                "SecondApp/index.html");
        });
    });
    

    Varning

    API som förlitar sig på värdrubriken, till exempel HttpRequest.Host och RequireHost, är föremål för potentiell förfalskning av klienter.

    Använd någon av följande metoder för att förhindra förfalskning av värd- och portar:

  • Lägg till mellanprogram som mappar begäranden till klientapparna. I följande exempel konfigureras mellanprogrammet så att det körs när undersökvägen för begäran är /FirstApp för den första klientappen eller /SecondApp för den andra klientappen.

    Där du tog bort app.UseBlazorFrameworkFiles(); raden från Program.csplacerar du följande kod:

    app.MapWhen(ctx => ctx.Request.Path.StartsWithSegments("/FirstApp", 
        StringComparison.OrdinalIgnoreCase), first =>
    {
        first.UseBlazorFrameworkFiles("/FirstApp");
        first.UseStaticFiles();
        first.UseStaticFiles("/FirstApp");
        first.UseRouting();
    
        first.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
            endpoints.MapFallbackToFile("/FirstApp/{*path:nonfile}",
                "FirstApp/index.html");
        });
    });
    
    app.MapWhen(ctx => ctx.Request.Path.StartsWithSegments("/SecondApp", 
        StringComparison.OrdinalIgnoreCase), second =>
    {
        second.UseBlazorFrameworkFiles("/SecondApp");
        second.UseStaticFiles();
        second.UseStaticFiles("/SecondApp");
        second.UseRouting();
    
        second.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
            endpoints.MapFallbackToFile("/SecondApp/{*path:nonfile}",
                "SecondApp/index.html");
        });
    });
    
  • Ange bassökvägen i varje klientapp:

    I den första klientappens index.html fil (Client/wwwroot/index.html) uppdaterar <base> du taggvärdet så att det återspeglar undersökvägen. Det avslutande snedstrecket krävs:

    <base href="/FirstApp/" />
    

    I den andra klientappens index.html fil (SecondClient/wwwroot/index.html) uppdaterar <base> du taggvärdet så att det återspeglar undersökvägen. Det avslutande snedstrecket krävs:

    <base href="/SecondApp/" />
    

Mer information om UseStaticFilesfinns i ASP.NET Statiska kärnfilerBlazor.

Mer information om UseBlazorFrameworkFiles och MapFallbackToFilefinns i följande resurser:

Anmärkning

Dokumentationslänkar till .NET-referenskällan läser vanligtvis in lagringsplatsens standardgren, vilket representerar den aktuella utvecklingen för nästa version av .NET. Om du vill välja en tagg för en specifik version använder du listrutan Välj bland grenar eller taggar. Mer information finns i Så här väljer du en versionstagg för ASP.NET Core-källkod (dotnet/AspNetCore.Docs #26205).

Begäranden från klientapparna till /WeatherForecast i server-API:et är antingen till /FirstApp/WeatherForecast eller /SecondApp/WeatherForecast beroende på vilken klientapp som gör begäran. Därför kräver kontrollvägarna som returnerar väderdata från serverns API en ändring för att inkludera segmenten i sökvägen.

I serverappens väderprognoskontrollant (Controllers/WeatherForecastController.cs) ersätter du den befintliga vägen ([Route("[controller]")]) till WeatherForecastController med följande vägar, som tar hänsyn till sökvägarna för klientbegäran:

[Route("FirstApp/[controller]")]
[Route("SecondApp/[controller]")]

Om du planerar att hantera sidor från serverappen lägger du till en IndexRazor sida i Pages serverappens mapp:

Pages/Index.cshtml:

@page
@model MultipleBlazorApps.Server.Pages.IndexModel
@{
    ViewData["Title"] = "Home";
}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>Home</title>
</head>
<body>
    <div class="main">
        <div class="content px-4">

            <div>
                <h1>Welcome</h1>
                <p>Hello from Razor Pages!</p>
            </div>
        </div>
    </div>
</body>
</html>

Pages/Index.cshtml.cs:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace MultipleBlazorApps.Server.Pages;

public class IndexModel : PageModel
{
    public void OnGet()
    {
    }
}
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace MultipleBlazorApps.Server.Pages
{
    public class IndexModel : PageModel
    {
        public void OnGet()
        {
        }
    }
}

Anmärkning

Föregående Index sida är ett minimalt exempel enbart i demonstrationssyfte. Om appen kräver ytterligare Razor pages-tillgångar, till exempel layout, formatmallar, skript och importer, hämtar du dem från en app som skapats Razor från sidprojektmallen. Mer information Razor finns i Sidarkitektur och begrepp i ASP.NET Core.

Om du planerar att hantera MVC-vyer från serverappen lägger du till en Index vy och en Home kontrollant:

Views/Home/Index.cshtml:

@{
    ViewData["Title"] = "Home";
}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>Home</title>
</head>
<body>
    <div class="main">
        <div class="content px-4">

            <div>
                <h1>Welcome</h1>
                <p>Hello from MVC!</p>
            </div>
        </div>
    </div>
</body>
</html>

Controllers/HomeController.cs:

using Microsoft.AspNetCore.Mvc;

namespace MultipleBlazorApps.Server.Controllers;

public class HomeController : Controller
{
    public IActionResult Index() => View();
}

Anmärkning

Föregående vy är ett minimalt Index exempel enbart i demonstrationssyfte. Om appen kräver ytterligare MVC-tillgångar, till exempel en layout, formatmallar, skript och importer, hämtar du dem från en app som skapats från MVC-projektmallen. Mer information finns i Kom igång med ASP.NET Core MVC.

Mer information om hur du använder komponenterna Razor från någon av klientapparna på sidor eller vyer i serverappen finns i Integrera ASP.NET Core-komponenter Razor med MVC eller Razor Sidor i värdbaserade Blazor WebAssembly lösningar.

Kör appen

MultipleBlazorApps.Server Kör projektet:

  • Få åtkomst till den första klientappen på https://localhost:5001.
  • Få åtkomst till den tillagda klientappen på https://localhost:5002.
  • Om serverappen är konfigurerad för att hantera sidor eller vyer öppnar du Index sidan eller vyn på https://localhost:5000.
  • Få åtkomst till den första klientappen på https://localhost:{DEFAULT PORT}/FirstApp.
  • Få åtkomst till den tillagda klientappen på https://localhost:{DEFAULT PORT}/SecondApp.
  • Om serverappen är konfigurerad för att hantera sidor eller vyer öppnar du Index sidan eller vyn på https://localhost:{DEFAULT PORT}.

I föregående exempel-URL:er {DEFAULT PORT} är platshållaren den standardport som definieras av MultipleBlazorApps.Server projektets Properties/launchSettings.json fil i dess applicationUrl värde.

Viktigt!

När du kör appen med dotnet watch kommandot (eller dotnet run) (.NET CLI) kontrollerar du att kommandogränssnittet är öppet i Server lösningens mapp.

När du använder Start-knappen i Visual Studio för att köra appen kontrollerar du att MultipleBlazorApps.Server projektet har angetts som startprojektet (markerat i Solution Explorer).

Statiska tillgångar

När en tillgång finns i en klientapps wwwroot mapp anger du sökvägen för begäran om statiska tillgångar i komponenter:

<img alt="..." src="{PATH AND FILE NAME}" />

Platshållaren {PATH AND FILE NAME} är sökvägen och filnamnet under wwwroot.

Till exempel källan för en Jeep-avbildning jeep-yj.png(vehicle) i wwwroot mappen för :

<img alt="Jeep Wrangler YJ" src="vehicle/jeep-yj.png" />

Razor stöd för klassbibliotek (RCL)

Razor Lägg till klassbiblioteket (RCL) i lösningen som ett nytt projekt:

  • Högerklicka på lösningen i Solution Explorer och välj Lägg till>nytt projekt.
  • Använd projektmallen Razor Klassbibliotek för att skapa projektet. Exemplen i det här avsnittet använder projektnamnet ComponentLibrary, som också är RCL:s sammansättningsnamn. Markera inte kryssrutan Supportsidor och vyer.

För varje värdbaserad Blazor WebAssembly klientapp skapar du en projektreferens för RCL-projektet genom att högerklicka på varje klientprojekt i Solution Explorer och välja Lägg till>projektreferens.

Använd komponenter från RCL i klientapparna med någon av följande metoder:

  • Placera ett @using-direktiv överst på komponenten för RCL:s namnområde och lägg till Razor-syntax för komponenten. Följande exempel är för en RCL med sammansättningsnamnet ComponentLibrary:

    @using ComponentLibrary
    
    ...
    
    <Component1 />
    
  • Ange RCL:s namnområde tillsammans med syntaxen Razor för komponenten. Den här metoden kräver inte något @using direktiv överst i komponentfilen. Följande exempel är för en RCL med sammansättningsnamnet ComponentLibrary:

    <ComponentLibrary.Component1 />
    

Anmärkning

Ett @using direktiv kan också placeras i varje klientapps _Import.razor fil, vilket gör RCL:s namnområde globalt tillgängligt för komponenter i projektet.

När någon annan statisk tillgång finns i mappen för wwwroot en RCL refererar du till den statiska tillgången i en klientapp enligt vägledningen i Återanvändbart Razor användargränssnitt i klassbibliotek med ASP.NET Core:

<img alt="..." src="_content/{PACKAGE ID}/{PATH AND FILE NAME}" />

Platshållaren {PACKAGE ID} är RCL:s paket-ID. Paket-ID:t är som standard projektets sammansättningsnamn om <PackageId> inte anges i projektfilen. Platshållaren {PATH AND FILE NAME} är sökväg och filnamn under wwwroot.

I följande exempel visas markup för en Jeep-avbildning (jeep-yj.png) i mappen vehicle i RCL:s wwwroot-mapp. Följande exempel är för en RCL med sammansättningsnamnet ComponentLibrary:

<img alt="Jeep Wrangler YJ" src="_content/ComponentLibrary/vehicle/jeep-yj.png" />

Ytterligare resurser