Sdílet prostřednictvím


Migrace z webových formulářů ASP.NET do Blazor

Tip

Tento obsah je výňatek z eBooku pro Blazor vývojáře webových formulářů ASP NET pro Azure, který je k dispozici na webu .NET Docs nebo jako bezplatný soubor PDF ke stažení, který si můžete přečíst offline.

Blazor-for-ASP-NET-Web-Forms-Developers eBook cover thumbnail.

Migrace základu kódu z ASP.NET webových formulářů na Blazor časově náročný úkol, který vyžaduje plánování. Tato kapitola popisuje proces. Něco, co může usnadnit přechod, je zajistit, aby aplikace dodržovala N-vrstvou architekturu, kde model aplikace (v tomto případě webové formuláře) je oddělený od obchodní logiky. Díky tomuto logickému oddělení vrstev je jasné, co je potřeba přesunout do .NET Core a Blazor.

V tomto příkladu se používá aplikace eShop dostupná na GitHubu . eShop je katalogová služba, která poskytuje funkce CRUD prostřednictvím zadávání a ověřování formuláře.

Proč by se měla migrovat funkční aplikace?Blazor Mnohokrát není potřeba. ASP.NET webové formuláře budou i nadále podporovány po mnoho let. Mnoho funkcí, které Blazor poskytuje, se ale podporují jenom v migrované aplikaci. Mezi tyto funkce patří:

  • Vylepšení výkonu v rámci, jako je například Span<T>
  • Schopnost spustit jako WebAssembly
  • Podpora multiplatformních platforem pro Linux a macOS
  • Nasazení místní aplikace nebo sdílené architektury bez dopadu na jiné aplikace

Pokud jsou tyto nebo jiné nové funkce dostatečně působivé, může být při migraci aplikace k dispozici hodnota. Migrace může mít různé tvary; může to být celá aplikace nebo jenom určité koncové body, které vyžadují změny. Rozhodnutí o migraci je nakonec založeno na obchodních problémech, které má vývojář vyřešit.

Na straně serveru versus hostování na straně klienta

Jak je popsáno v kapitole o hostitelských modelech , Blazor je možné aplikaci hostovat dvěma různými způsoby: na straně serveru a na straně klienta. Model na straně serveru používá ASP.NET připojení Core SignalR ke správě aktualizací MODELU DOM při spouštění veškerého skutečného kódu na serveru. Model na straně klienta běží jako WebAssembly v prohlížeči a nevyžaduje připojení k serveru. Existuje řada rozdílů, které můžou mít vliv na to, které jsou pro konkrétní aplikaci nejvhodnější:

  • Spuštění jako WebAssembly v současné době nepodporuje všechny funkce (například threading).
  • Chatty komunikace mezi klientem a serverem může způsobit problémy s latencí v režimu na straně serveru
  • Přístup k databázím a interním nebo chráněným službám vyžaduje samostatnou službu s hostování na straně klienta.

V době psaní modelu na straně serveru se více podobá webovým formulářům. Většina z této kapitoly se zaměřuje na model hostování na straně serveru, protože je připravený pro produkční prostředí.

Vytvoření nového projektu

Tento počáteční krok migrace spočívá v vytvoření nového projektu. Tento typ projektu je založen na projektech stylu sady SDK rozhraní .NET a zjednodušuje většinu často používaného v předchozích formátech projektu. Další podrobnosti najdete v kapitole o struktuře projektu.

Po vytvoření projektu nainstalujte knihovny, které byly použity v předchozím projektu. Ve starších projektech Webových formulářů jste možná použili soubor packages.config k výpisu požadovaných balíčků NuGet. V novém projektu ve stylu sady SDK se packages.config nahradily <PackageReference> prvky v souboru projektu. Výhodou tohoto přístupu je, že všechny závislosti se instalují přechodně. Vypíšete jenom závislosti nejvyšší úrovně, na které vám záleží.

Řada závislostí, které používáte, jsou k dispozici pro .NET, včetně Entity Frameworku 6 a log4netu. Pokud není k dispozici žádná verze .NET nebo .NET Standard, můžete často použít verzi rozhraní .NET Framework. Vaše kilometry se můžou lišit. Jakékoli použité rozhraní API, které není dostupné v .NET, způsobí chybu za běhu. Visual Studio vás upozorní na tyto balíčky. V Průzkumník řešení se na uzlu Reference projektu zobrazí žlutá ikona.

BlazorV projektu eShop založeném na eShopu se zobrazí nainstalované balíčky. Dříve soubor packages.config uvedl všechny balíčky použité v projektu, což vedlo k tomu, že soubor má téměř 50 řádků. Fragment kódu packages.config je:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  ...
  <package id="Microsoft.ApplicationInsights.Agent.Intercept" version="2.4.0" targetFramework="net472" />
  <package id="Microsoft.ApplicationInsights.DependencyCollector" version="2.9.1" targetFramework="net472" />
  <package id="Microsoft.ApplicationInsights.PerfCounterCollector" version="2.9.1" targetFramework="net472" />
  <package id="Microsoft.ApplicationInsights.Web" version="2.9.1" targetFramework="net472" />
  <package id="Microsoft.ApplicationInsights.WindowsServer" version="2.9.1" targetFramework="net472" />
  <package id="Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel" version="2.9.1" targetFramework="net472" />
  <package id="Microsoft.AspNet.FriendlyUrls" version="1.0.2" targetFramework="net472" />
  <package id="Microsoft.AspNet.FriendlyUrls.Core" version="1.0.2" targetFramework="net472" />
  <package id="Microsoft.AspNet.ScriptManager.MSAjax" version="5.0.0" targetFramework="net472" />
  <package id="Microsoft.AspNet.ScriptManager.WebForms" version="5.0.0" targetFramework="net472" />
  ...
  <package id="System.Memory" version="4.5.1" targetFramework="net472" />
  <package id="System.Numerics.Vectors" version="4.4.0" targetFramework="net472" />
  <package id="System.Runtime.CompilerServices.Unsafe" version="4.5.0" targetFramework="net472" />
  <package id="System.Threading.Channels" version="4.5.0" targetFramework="net472" />
  <package id="System.Threading.Tasks.Extensions" version="4.5.1" targetFramework="net472" />
  <package id="WebGrease" version="1.6.0" targetFramework="net472" />
</packages>

Prvek <packages> obsahuje všechny nezbytné závislosti. Je obtížné zjistit, které z těchto balíčků jsou zahrnuty, protože je požadujete. Některé <package> prvky jsou uvedeny jednoduše tak, aby vyhovovaly potřebám požadovaných závislostí.

Projekt Blazor zobrazí seznam závislostí, které v rámci elementu v souboru projektu požadujete <ItemGroup> :

<ItemGroup>
    <PackageReference Include="Autofac" Version="4.9.3" />
    <PackageReference Include="EntityFramework" Version="6.4.4" />
    <PackageReference Include="log4net" Version="2.0.12" />
    <PackageReference Include="Microsoft.Extensions.Logging.Log4Net.AspNetCore" Version="2.2.12" />
</ItemGroup>

Jedním balíčkem NuGet, který zjednodušuje život vývojářů webových formulářů, je sada Windows Compatibility Pack. I když je .NET multiplatformní, některé funkce jsou dostupné jenom ve Windows. Funkce specifické pro Systém Windows jsou zpřístupněny instalací sady Compatibility Pack. Mezi příklady takových funkcí patří Registry, WMI a Adresářové služby. Balíček přidá přibližně 20 000 rozhraní API a aktivuje mnoho služeb, se kterými už možná znáte. Projekt eShop nevyžaduje balíček kompatibility; ale pokud vaše projekty používají funkce specifické pro Windows, balíček usnadňuje migraci.

Povolení procesu spuštění

Proces spuštění webových Blazor formulářů se změnil a následuje podobné nastavení pro ostatní služby ASP.NET Core. Při hostování na straně serveru se komponenty Razor spouští jako součást normální aplikace ASP.NET Core. Při hostování v prohlížeči používají WebAssemblykomponenty Razor podobný model hostování. Rozdíl je, že komponenty se spouští jako samostatná služba od jakéhokoli z back-endových procesů. V obou směrech je spuštění podobné.

Soubor Global.asax.cs je výchozí spouštěcí stránkou pro projekty Webových formulářů. V projektu eShop tento soubor nakonfiguruje kontejner Inversion of Control (IoC) a zpracovává různé události životního cyklu aplikace nebo požadavku. Některé z těchto událostí se zpracovávají pomocí middlewaru (například Application_BeginRequest). Jiné události vyžadují přepsání konkrétních služeb prostřednictvím injektáže závislostí (DI).

Například soubor Global.asax.cs pro eShop obsahuje následující kód:

public class Global : HttpApplication, IContainerProviderAccessor
{
    private static readonly ILog _log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

    static IContainerProvider _containerProvider;
    IContainer container;

    public IContainerProvider ContainerProvider
    {
        get { return _containerProvider; }
    }

    protected void Application_Start(object sender, EventArgs e)
    {
        // Code that runs on app startup
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
        ConfigureContainer();
        ConfigDataBase();
    }

    /// <summary>
    /// Track the machine name and the start time for the session inside the current session
    /// </summary>
    protected void Session_Start(Object sender, EventArgs e)
    {
        HttpContext.Current.Session["MachineName"] = Environment.MachineName;
        HttpContext.Current.Session["SessionStartTime"] = DateTime.Now;
    }

    /// <summary>
    /// https://autofaccn.readthedocs.io/en/latest/integration/webforms.html
    /// </summary>
    private void ConfigureContainer()
    {
        var builder = new ContainerBuilder();
        var mockData = bool.Parse(ConfigurationManager.AppSettings["UseMockData"]);
        builder.RegisterModule(new ApplicationModule(mockData));
        container = builder.Build();
        _containerProvider = new ContainerProvider(container);
    }

    private void ConfigDataBase()
    {
        var mockData = bool.Parse(ConfigurationManager.AppSettings["UseMockData"]);

        if (!mockData)
        {
            Database.SetInitializer<CatalogDBContext>(container.Resolve<CatalogDBInitializer>());
        }
    }

    protected void Application_BeginRequest(object sender, EventArgs e)
    {
        //set the property to our new object
        LogicalThreadContext.Properties["activityid"] = new ActivityIdHelper();

        LogicalThreadContext.Properties["requestinfo"] = new WebRequestInfo();

        _log.Debug("Application_BeginRequest");
    }
}

Předchozí soubor se stane Program.cs soubor na straně Blazorserveru:

using eShopOnBlazor.Models;
using eShopOnBlazor.Models.Infrastructure;
using eShopOnBlazor.Services;
using log4net;
using System.Data.Entity;
using eShopOnBlazor;

var builder = WebApplication.CreateBuilder(args);

// add services

builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();

if (builder.Configuration.GetValue<bool>("UseMockData"))
{
    builder.Services.AddSingleton<ICatalogService, CatalogServiceMock>();
}
else
{
    builder.Services.AddScoped<ICatalogService, CatalogService>();
    builder.Services.AddScoped<IDatabaseInitializer<CatalogDBContext>, CatalogDBInitializer>();
    builder.Services.AddSingleton<CatalogItemHiLoGenerator>();
    builder.Services.AddScoped(_ => new CatalogDBContext(builder.Configuration.GetConnectionString("CatalogDBContext")));
}

var app = builder.Build();

new LoggerFactory().AddLog4Net("log4Net.xml");

if (app.Environment.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}
else
{
    app.UseExceptionHandler("/Home/Error");
}

// Middleware for Application_BeginRequest
app.Use((ctx, next) =>
{
    LogicalThreadContext.Properties["activityid"] = new ActivityIdHelper(ctx);
    LogicalThreadContext.Properties["requestinfo"] = new WebRequestInfo(ctx);
    return next();
});

app.UseStaticFiles();

app.UseRouting();

app.UseEndpoints(endpoints =>
{
    endpoints.MapBlazorHub();
    endpoints.MapFallbackToPage("/_Host");
});

ConfigDataBase(app);

void ConfigDataBase(IApplicationBuilder app)
{
    using (var scope = app.ApplicationServices.CreateScope())
    {
        var initializer = scope.ServiceProvider.GetService<IDatabaseInitializer<CatalogDBContext>>();

        if (initializer != null)
        {
            Database.SetInitializer(initializer);
        }
    }
}

app.Run();

Jednou z významných změn, kterou si můžete všimnout z webových formulářů, je výslovnost injektáže závislostí (DI). Di je hlavním principem návrhu ASP.NET Core. Podporuje přizpůsobení téměř všech aspektů architektury ASP.NET Core. Existuje dokonce integrovaný poskytovatel služeb, který je možné použít pro mnoho scénářů. Pokud je požadováno další přizpůsobení, může ho podporovat mnoho komunitních projektů. Můžete například přenést investice do knihovny DI třetích stran.

V původní aplikaci eShop existuje nějaká konfigurace pro správu relací. Vzhledem k tomu, že na straně Blazor serveru se ke komunikaci používá ASP.NET Core SignalR, stav relace se nepodporuje, protože připojení můžou nastat nezávisle na kontextu HTTP. Aplikace, která používá stav relace, vyžaduje před spuštěním Blazor aplikace architekturu.

Další informace o spuštění aplikace najdete v tématu Spuštění aplikace.

Migrace modulů HTTP a obslužných rutin do middlewaru

Moduly a obslužné rutiny HTTP jsou v webových formulářích běžné vzory pro řízení kanálu požadavků HTTP. Třídy, které implementují IHttpModule nebo IHttpHandler mohou být registrovány a zpracovávat příchozí požadavky. Webové formuláře konfiguruje moduly a obslužné rutiny v souboru web.config . Webové formuláře jsou také silně založené na zpracování událostí životního cyklu aplikace. ASP.NET Core místo toho používá middleware. Middleware je registrován v Configure metodě Startup třídy. Pořadí provádění middlewaru určuje objednávka registrace.

V části Povolit spouštěcí proces byla událost životního cyklu vyvolána webovými formuláři jako metodouApplication_BeginRequest. Tato událost není v ASP.NET Core dostupná. Jedním ze způsobů, jak tohoto chování dosáhnout, je implementovat middleware, jak je vidět v příkladu Startup.cs souboru. Tento middleware provede stejnou logiku a pak přenese řízení na další obslužnou rutinu v kanálu middlewaru.

Další informace o migraci modulů a obslužných rutin naleznete v tématu Migrace obslužných rutin HTTP a modulů do ASP.NET Core middleware.

Migrace statických souborů

Aby bylo možné obsluhovat statické soubory (například HTML, CSS, obrázky a JavaScript), musí být soubory vystaveny middlewarem. UseStaticFiles Volání metody umožňuje obsluhu statických souborů z kořenové cesty webu. Výchozí kořenový adresář webu je wwwroot, ale lze ho přizpůsobit. Jak je součástí souboru Program.cs :

...

app.UseStaticFiles();

...

Projekt eShop umožňuje základní statický přístup k souborům. Pro statický přístup k souborům je k dispozici mnoho vlastních nastavení. Informace o povolení výchozích souborů nebo prohlížeče souborů najdete v tématu Statické soubory v ASP.NET Core.

Migrace nastavení sdružování a minifikace modulu runtime

Sdružování a minifikace jsou techniky optimalizace výkonu pro snížení počtu a velikosti požadavků serveru pro načtení určitých typů souborů. JavaScript a CSS často procházejí nějakou formou sdružování nebo minifikace před odesláním klientovi. Ve webových formulářích ASP.NET se tyto optimalizace zpracovávají za běhu. Konvence optimalizace jsou definovány App_Start /BundleConfig.cs soubor. V ASP.NET Core se přijímá deklarativní přístup. Soubor obsahuje seznam souborů, které mají být minifikovány, spolu s konkrétním nastavením minifikace.

Další informace o sdružování a minifikaci najdete v tématu Bundle and minify static assets in ASP.NET Core.

Migrace stránek ASPX

Stránka v aplikaci Webové formuláře je soubor s příponou .aspx . Stránka Webových formulářů lze často mapovat na součást v Blazorsouboru . Komponenta Razor je authored in a file with the .razor extension. Pro projekt eShop se pět stránek převede na stránku Razor Page.

Zobrazení podrobností například obsahuje tři soubory v projektu Webové formuláře: Details.aspx, Details.aspx.cs a Details.aspx.designer.cs. Při převodu na Blazorkód a kód se zkombinují do Details.razor. Kompilace Razor (ekvivalent toho, co je v .designer.cs souborech) je uložená v adresáři obj a ve výchozím nastavení není v Průzkumník řešení zobrazitelná. Stránka Webové formuláře se skládá z následujících značek:

<%@ Page Title="Details" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Details.aspx.cs" Inherits="eShopLegacyWebForms.Catalog.Details" %>

<asp:Content ID="Details" ContentPlaceHolderID="MainContent" runat="server">
    <h2 class="esh-body-title">Details</h2>

    <div class="container">
        <div class="row">
            <asp:Image runat="server" CssClass="col-md-6 esh-picture" ImageUrl='<%#"/Pics/" + product.PictureFileName%>' />
            <dl class="col-md-6 dl-horizontal">
                <dt>Name
                </dt>

                <dd>
                    <asp:Label runat="server" Text='<%#product.Name%>' />
                </dd>

                <dt>Description
                </dt>

                <dd>
                    <asp:Label runat="server" Text='<%#product.Description%>' />
                </dd>

                <dt>Brand
                </dt>

                <dd>
                    <asp:Label runat="server" Text='<%#product.CatalogBrand.Brand%>' />
                </dd>

                <dt>Type
                </dt>

                <dd>
                    <asp:Label runat="server" Text='<%#product.CatalogType.Type%>' />
                </dd>
                <dt>Price
                </dt>

                <dd>
                    <asp:Label CssClass="esh-price" runat="server" Text='<%#product.Price%>' />
                </dd>

                <dt>Picture name
                </dt>

                <dd>
                    <asp:Label runat="server" Text='<%#product.PictureFileName%>' />
                </dd>

                <dt>Stock
                </dt>

                <dd>
                    <asp:Label runat="server" Text='<%#product.AvailableStock%>' />
                </dd>

                <dt>Restock
                </dt>

                <dd>
                    <asp:Label runat="server" Text='<%#product.RestockThreshold%>' />
                </dd>

                <dt>Max stock
                </dt>

                <dd>
                    <asp:Label runat="server" Text='<%#product.MaxStockThreshold%>' />
                </dd>

            </dl>
        </div>

        <div class="form-actions no-color esh-link-list">
            <a runat="server" href='<%# GetRouteUrl("EditProductRoute", new {id =product.Id}) %>' class="esh-link-item">Edit
            </a>
            |
            <a runat="server" href="~" class="esh-link-item">Back to list
            </a>
        </div>

    </div>
</asp:Content>

Kód předchozí značky obsahuje následující kód:

using eShopLegacyWebForms.Models;
using eShopLegacyWebForms.Services;
using log4net;
using System;
using System.Web.UI;

namespace eShopLegacyWebForms.Catalog
{
    public partial class Details : System.Web.UI.Page
    {
        private static readonly ILog _log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        protected CatalogItem product;

        public ICatalogService CatalogService { get; set; }

        protected void Page_Load(object sender, EventArgs e)
        {
            var productId = Convert.ToInt32(Page.RouteData.Values["id"]);
            _log.Info($"Now loading... /Catalog/Details.aspx?id={productId}");
            product = CatalogService.FindCatalogItem(productId);

            this.DataBind();
        }
    }
}

Při převodu na Blazorstránku Webové formuláře se přeloží na následující kód:

@page "/Catalog/Details/{id:int}"
@inject ICatalogService CatalogService
@inject ILogger<Details> Logger

<h2 class="esh-body-title">Details</h2>

<div class="container">
    <div class="row">
        <img class="col-md-6 esh-picture" src="@($"/Pics/{_item.PictureFileName}")">

        <dl class="col-md-6 dl-horizontal">
            <dt>
                Name
            </dt>

            <dd>
                @_item.Name
            </dd>

            <dt>
                Description
            </dt>

            <dd>
                @_item.Description
            </dd>

            <dt>
                Brand
            </dt>

            <dd>
                @_item.CatalogBrand.Brand
            </dd>

            <dt>
                Type
            </dt>

            <dd>
                @_item.CatalogType.Type
            </dd>
            <dt>
                Price
            </dt>

            <dd>
                @_item.Price
            </dd>

            <dt>
                Picture name
            </dt>

            <dd>
                @_item.PictureFileName
            </dd>

            <dt>
                Stock
            </dt>

            <dd>
                @_item.AvailableStock
            </dd>

            <dt>
                Restock
            </dt>

            <dd>
                @_item.RestockThreshold
            </dd>

            <dt>
                Max stock
            </dt>

            <dd>
                @_item.MaxStockThreshold
            </dd>

        </dl>
    </div>

    <div class="form-actions no-color esh-link-list">
        <a href="@($"/Catalog/Edit/{_item.Id}")" class="esh-link-item">
            Edit
        </a>
        |
        <a href="/" class="esh-link-item">
            Back to list
        </a>
    </div>

</div>

@code {
    private CatalogItem _item;

    [Parameter]
    public int Id { get; set; }

    protected override void OnInitialized()
    {
        Logger.LogInformation("Now loading... /Catalog/Details/{Id}", Id);

        _item = CatalogService.FindCatalogItem(Id);
    }
}

Všimněte si, že kód a revize jsou ve stejném souboru. Všechny požadované služby jsou přístupné s atributem @inject . Podle direktivy @page je tato stránka přístupná na Catalog/Details/{id} trase. Hodnota zástupného symbolu trasy {id} byla omezena na celé číslo. Jak je popsáno v oddílu směrování , na rozdíl od webových formulářů komponenta Razor explicitně uvádí svou trasu a všechny zahrnuté parametry. Mnoho ovládacích prvků Webových formulářů nemusí mít přesné protějšky v Blazor. Často existuje ekvivalentní fragment kódu HTML, který bude sloužit stejnému účelu. Ovládací prvek lze například <asp:Label /> nahradit elementem HTML <label> .

Ověření modelu v Blazor

Pokud kód webového formuláře obsahuje ověření, můžete přenést většinu toho, co máte s minimálními změnami. Výhodou spuštění Blazor je, že stejnou logiku ověřování je možné spustit bez nutnosti vlastního JavaScriptu. Datové poznámky umožňují snadné ověření modelu.

Například na stránce Create.aspx je formulář pro zadávání dat s ověřením. Příklad fragmentu kódu by vypadal takto:

<div class="form-group">
    <label class="control-label col-md-2">Name</label>
    <div class="col-md-3">
        <asp:TextBox ID="Name" runat="server" CssClass="form-control"></asp:TextBox>
        <asp:RequiredFieldValidator runat="server" ControlToValidate="Name" Display="Dynamic"
            CssClass="field-validation-valid text-danger" ErrorMessage="The Name field is required." />
    </div>
</div>

V Blazorsouboru Create.razor je k dispozici ekvivalentní kód:

<EditForm Model="_item" OnValidSubmit="@...">
    <DataAnnotationsValidator />

    <div class="form-group">
        <label class="control-label col-md-2">Name</label>
        <div class="col-md-3">
            <InputText class="form-control" @bind-Value="_item.Name" />
            <ValidationMessage For="(() => _item.Name)" />
        </div>
    </div>

    ...
</EditForm>

Kontext EditForm zahrnuje podporu ověřování a lze jej zabalit kolem vstupu. Datové poznámky představují běžný způsob, jak přidat ověření. Tuto podporu ověřování je možné přidat prostřednictvím DataAnnotationsValidator komponenty. Další informace o tomto mechanismu najdete v tématu ASP.NET základních Blazor formulářů a ověřování.

Migrace konfigurace

V projektu webových formulářů se konfigurační data nejčastěji ukládají do souboru web.config . Ke konfiguračním datům se přistupuje pomocí ConfigurationManager. Služby se často vyžadovaly k analýze objektů. S rozhraním .NET Framework 4.7.2 byla do konfigurace přidána kompozitovatelnost prostřednictvím ConfigurationBuilders. Tito tvůrci povolili vývojářům přidat různé zdroje pro konfiguraci, která se pak vytvořila za běhu, aby získali potřebné hodnoty.

ASP.NET Core zavedl flexibilní konfigurační systém, který umožňuje definovat zdroj konfigurace nebo zdroje používané vaší aplikací a nasazením. ConfigurationBuilder Infrastruktura, kterou můžete používat v aplikaci Web Forms, byla modelována po konceptech používaných v konfiguračním systému ASP.NET Core.

Následující fragment kódu ukazuje, jak projekt eShop webových formulářů používá web.config k ukládání hodnot konfigurace:

<configuration>
  <configSections>
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <connectionStrings>
    <add name="CatalogDBContext" connectionString="Data Source=(localdb)\MSSQLLocalDB; Initial Catalog=Microsoft.eShopOnContainers.Services.CatalogDb; Integrated Security=True; MultipleActiveResultSets=True;" providerName="System.Data.SqlClient" />
  </connectionStrings>
  <appSettings>
    <add key="UseMockData" value="true" />
    <add key="UseCustomizationData" value="false" />
  </appSettings>
</configuration>

Tajné kódy, jako jsou databázové připojovací řetězec, se běžně ukládají v souboru web.config. Tajné kódy se nutně uchovávají v nezabezpečených umístěních, jako je například správa zdrojového kódu. U Blazor ASP.NET Core se předchozí konfigurace založená na JAZYCE XML nahradí následujícím kódem JSON:

{
  "ConnectionStrings": {
    "CatalogDBContext": "Data Source=(localdb)\\MSSQLLocalDB; Initial Catalog=Microsoft.eShopOnContainers.Services.CatalogDb; Integrated Security=True; MultipleActiveResultSets=True;"
  },
  "UseMockData": true,
  "UseCustomizationData": false
}

JSON je výchozí formát konfigurace; ale ASP.NET Core podporuje mnoho dalších formátů, včetně XML. Existuje také několik formátů podporovaných komunitou.

Ke konfiguračním hodnotám se dostanete z tvůrce v Program.cs:

if (builder.Configuration.GetValue<bool>("UseMockData"))
{
    builder.Services.AddSingleton<ICatalogService, CatalogServiceMock>();
}
else
{
    builder.Services.AddScoped<ICatalogService, CatalogService>();
    builder.Services.AddScoped<IDatabaseInitializer<CatalogDBContext>, CatalogDBInitializer>();
    builder.Services.AddSingleton<CatalogItemHiLoGenerator>();
    builder.Services.AddScoped(_ => new CatalogDBContext(builder.Configuration.GetConnectionString("CatalogDBContext")));
}

Ve výchozím nastavení jsou proměnné prostředí, soubory JSON (appsettings.json a appsettings.{ Environment}.json) a možnosti příkazového řádku jsou registrovány jako platné zdroje konfigurace v objektu konfigurace. Ke zdrojům konfigurace lze přistupovat prostřednictvím Configuration[key]. Pokročilejší technikou je vytvoření vazby konfiguračních dat k objektům pomocí vzoru možností. Další informace o konfiguraci a vzoru možností najdete v tématu Konfigurace v modelu ASP.NET Core a Options v ASP.NET Core.

Migrace přístupu k datům

Přístup k datům je důležitým aspektem každé aplikace. Projekt eShop ukládá informace o katalogu do databáze a načítá data pomocí Entity Frameworku (EF) 6. Vzhledem k tomu, že ef 6 je podporován v .NET 5, může projekt i nadále používat.

V eShopu byly nezbytné následující změny související s EF:

  • V rozhraní .NET Framework DbContext objekt přijímá řetězec form name=Připojení ionString a používá připojovací řetězec z ConfigurationManager.AppSettings[ConnectionString] připojit. V .NET Core se to nepodporuje. Je nutné zadat připojovací řetězec.
  • K databázi se přistupovalo synchronním způsobem. I když to funguje, může dojít ke škálovatelnosti. Tato logika by se měla přesunout do asynchronního vzoru.

I když pro vazbu datové sady není stejná nativní podpora, Blazor poskytuje flexibilitu a výkon s podporou jazyka C# na stránce Razor Page. Můžete například provádět výpočty a zobrazit výsledek. Další informace o vzorech dat naleznete v Blazorkapitole Přístup k datům.

Změny architektury

A konečně existují některé důležité architektonické rozdíly, které je potřeba vzít v úvahu při migraci na Blazor. Mnohé z těchto změn se vztahují na cokoli na základě .NET Core nebo ASP.NET Core.

Vzhledem k tomu, že Blazor je založená na .NET Core, je potřeba zvážit zajištění podpory v .NET Core. Mezi hlavní změny patří odebrání následujících funkcí:

  • Více domén AppDomains
  • Remoting
  • Zabezpečení přístupu kódu (CAS)
  • Transparentnost zabezpečení

Další informace o technikách pro identifikaci nezbytných změn podpory spouštění v .NET Core najdete v tématu Portování kódu z rozhraní .NET Framework do .NET Core.

ASP.NET Core je přeimaginovaná verze ASP.NET a má některé změny, které nemusí zpočátku vypadat jako zřejmé. Mezi hlavní změny patří:

  • Žádný kontext synchronizace, což znamená, že neexistuje žádná HttpContext.Current, Thread.CurrentPrincipalani jiné statické přístupové objekty
  • Bez stínové kopie
  • Žádná fronta požadavků

Mnoho operací v ASP.NET Core je asynchronní, což usnadňuje načítání vstupně-výstupních úloh. Je důležité nikdy neblokovat pomocí nebo Task.Wait()Task.GetResult(), což může rychle vyčerpat prostředky fondu vláken.

Závěr migrace

V tuto chvíli jste viděli mnoho příkladů, co je potřeba k přesunutí projektu Webové formuláře do Blazor. Úplný příklad najdete v projektu eShopOnBlazor .