Uaktualnianie z programu ASP.NET Framework do platformy ASP.NET Core

Dlaczego uaktualnij do najnowszej wersji platformy .NET

ASP.NET Core to nowoczesna platforma internetowa dla platformy .NET. Chociaż ASP.NET Core ma wiele podobieństw do ASP.NET w programie .NET Framework, jest to nowa struktura, która jest całkowicie przepisana. ASP.NET aplikacje zaktualizowane do ASP.NET Core mogą korzystać z lepszej wydajności i dostępu do najnowszych funkcji i możliwości tworzenia aplikacji internetowych.

metody aktualizacji ASP.NET Framework

Większość nietrywialnych aplikacji platformy ASP.NET Framework powinna rozważyć użycie podejścia do uaktualniania przyrostowego. Aby uzyskać więcej informacji, zobacz Incremental ASP.NET to ASP.NET Core upgrade (Uaktualnianie przyrostowe do ASP.NET Core).

Aby uzyskać ASP.NET aplikacje MVC i web API, zobacz Learn to upgrade from ASP.NET MVC and Web API to ASP.NET Core MVC (Dowiedz się, jak uaktualnić interfejs ASP.NET MVC i internetowy interfejs API do usługi ASP.NET Core MVC). Aby uzyskać informacje o aplikacjach ASP.NET Framework Web Forms, zobacz Learn to upgrade from ASP.NET Web Forms to ASP.NET Core (Dowiedz się, jak uaktualnić ASP.NET Web Forms do platformy ASP.NET Core).

Niezawodne wzorce aplikacji internetowej

Aby uzyskać wskazówki dotyczące tworzenia nowoczesnej, niezawodnej, wydajnej, wydajnej, ekonomicznej i skalowalnej aplikacji ASP.NET Core, od podstaw lub refaktoryzacji istniejącej aplikacji, zobacz Niezawodny wzorzecaplikacji internetowej for.NET YouTube.

Dekodowanie identyfikatorów URI różnic między ASP.NET a ASP.NET Core

ASP.NET Core ma następujące różnice w dekodowaniu identyfikatora URI za pomocą platformy ASP.NET Framework:

ASCII Encoded ASP.NET Core ASP.NET Framework
\ %5C \ /
/ %2F %2F /

Podczas dekodowania %2F na ASP.NET Core:

  • Cała ścieżka jest niesłabna, z wyjątkiem %2F tego, że przekonwertowanie jej na / spowoduje zmianę struktury ścieżki. Nie można jej zdekodować, dopóki ścieżka nie zostanie podzielona na segmenty.

Aby wygenerować wartość parametru HttpRequest.Url, użyj polecenia new Uri(this.AspNetCoreHttpRequest.GetEncodedUrl()); , aby uniknąć Uri błędnej interpretacji wartości.

Migrowanie wpisów tajnych użytkownika z platformy ASP.NET do platformy ASP.NET Core

Zobacz ten problem z usługą GitHub.

Ten artykuł stanowi przewodnik informacyjny dotyczący migrowania aplikacji ASP.NET do platformy ASP.NET Core.

Program Visual Studio ma narzędzia ułatwiające migrowanie aplikacji ASP.NET do platformy ASP.NET Core. Aby uzyskać więcej informacji, zobacz Migrowanie z ASP.NET do ASP.NET Core w programie Visual Studio.

Asystent uaktualniania platformy .NET to narzędzie wiersza polecenia, które może ułatwić migrację z platformy ASP.NET do ASP.NET Core. Aby uzyskać więcej informacji, zobacz artykuły Omówienie asystenta uaktualniania platformy .NET i Uaktualnianie aplikacji MVC ASP.NET do platformy .NET 6 przy użyciu Asystenta uaktualniania platformy .NET.

Aby zapoznać się z kompleksowym przewodnikiem dotyczącym przenoszenia, przeczytaj e-book Przenoszenie istniejących aplikacji ASP.NET do platformy .NET 6.

Wymagania wstępne

Zestaw .NET Core SDK 2.2 lub nowszy

Platformy docelowe

Projekty platformy ASP.NET Core oferują deweloperom możliwości elastycznego wyboru platformy docelowej: .NET Core, .NET Framework lub obydwu. Zobacz artykuł Wybieranie między platformą .NET Core i .NET Framework dla aplikacji serwera, aby określić, która platforma docelowa najlepiej Ci odpowiada.

Jeśli platforma docelowa to .NET Framework, projekty muszą odwoływać się do indywidualnych pakietów NuGet.

Wybór platformy .NET Core jako docelowej umożliwia eliminowanie wielu jawnych odwołań do pakietów dzięki metapakietowi platformy ASP.NET Core. Zainstaluj metapakiet Microsoft.AspNetCore.App w projekcie:

<ItemGroup>
   <PackageReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>

Jeśli używasz metapakietu, żadne pakiety, do których się on odwołuje, nie są wdrażane w aplikacji. Wszystkie te zasoby można znaleźć w magazynie środowiska uruchomieniowego platformy .NET Core. Są one również wstępnie skompilowane tak, aby zwiększać wydajność. Więcej szczegółowych informacji można znaleźć w artykule Metapakiet Microsoft.AspNetCore.App dla platformy ASP.NET Core.

Różnice dotyczące struktury projektu

Format pliku .csproj został uproszczony na platformie ASP.NET Core. Oto niektóre zmiany, na które warto zwrócić uwagę:

  • Aby pliki były traktowane jako część projektu, nie trzeba ich jawnie uwzględniać. Zmniejsza to ryzyko powstawania konfliktów scalania plików XML w przypadku pracy z większymi zespołami.

  • Brak opartych na identyfikatorze GUID odwołań do innych projektów ułatwia odczytywanie plików.

  • Plik można edytować bez zwalniania go w programie Visual Studio:

    Edit CSPROJ context menu option in Visual Studio 2017]

Zamiennik pliku Global.asax

Na platformie ASP.NET Core wprowadzono nowy mechanizm uruchomienia aplikacji. Punktem wejścia dla aplikacji ASP.NET jest plik Global.asax. Zadania, takie jak konfigurowanie i filtrowanie tras oraz rejestracje obszarów, są obsługiwane w pliku Global.asax.

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
    }
}

Takie podejście łączy aplikację i serwer, na którym ją wdrożono, w sposób ingerujący w implementację. Aby je odłączyć, wprowadzono interfejs OWIN, dzięki któremu można łatwiej używać wielu struktur jednocześnie. Interfejs OWIN udostępnia potok służący do dodawania wyłącznie potrzebnych modułów. Środowisko hostingu używa funkcji uruchamiania do konfigurowania usług oraz potoku żądań dotyczących aplikacji. Startup rejestruje zestaw oprogramowania pośredniczącego przy użyciu aplikacji. W przypadku każdego żądania aplikacja wywołuje poszczególne składniki oprogramowania pośredniczącego ze wskaźnikiem nagłówka połączonej listy ustawionym na istniejący zestaw procedur obsługi. Każdy składnik oprogramowania pośredniczącego może dodać co najmniej jedną procedurę obsługi do potoku obsługującego żądanie. Ten cel można osiągnąć, zwracając odwołanie do programu obsługi, który jest nowym nagłówkiem listy. Każda procedura obsługi odpowiada za zapamiętywanie i wywoływanie następnej procedury obsługi na liście. Na platformie ASP.NET Core punkt wejścia do aplikacji to Startup, a zależność od pliku Global.asax już nie istnieje. W przypadku korzystania z interfejsu OWIN w programie .NET Framework użyj potoku podobnego do następującego:

using Owin;
using System.Web.Http;

namespace WebApi
{
    // Note: By default all requests go through this OWIN pipeline. Alternatively you can turn this off by adding an appSetting owin:AutomaticAppStartup with value “false”. 
    // With this turned off you can still have OWIN apps listening on specific routes by adding routes in global.asax file using MapOwinPath or MapOwinRoute extensions on RouteTable.Routes
    public class Startup
    {
        // Invoked once at startup to configure your application.
        public void Configuration(IAppBuilder builder)
        {
            HttpConfiguration config = new HttpConfiguration();
            config.Routes.MapHttpRoute("Default", "{controller}/{customerID}", new { controller = "Customer", customerID = RouteParameter.Optional });

            config.Formatters.XmlFormatter.UseXmlSerializer = true;
            config.Formatters.Remove(config.Formatters.JsonFormatter);
            // config.Formatters.JsonFormatter.UseDataContractJsonSerializer = true;

            builder.UseWebApi(config);
        }
    }
}

Spowoduje to skonfigurowanie tras domyślnych i ustawienie opcji domyślnej na XmlSerialization zamiast JSON. W razie potrzeby dodaj inne oprogramowanie pośredniczące do tego potoku (usługi ładowania, ustawienia konfiguracji, pliki statyczne itp.).

Podobne podejście jest używane na platformie ASP.NET Core, ale nie zakłada się, że interfejs OWIN będzie obsługiwać wpis. W zamian to zadanie jest wykonywane za pośrednictwem metody Program.csMain (podobnej do aplikacji konsoli) oraz następuje załadowanie elementu Startup.

using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;

namespace WebApplication2
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateWebHostBuilder(args).Build().Run();
        }

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>();
    }
}

Element Startup musi zawierać metodę Configure. W obszarze Configure dodaj niezbędne oprogramowanie pośredniczące do potoku. W poniższym przykładzie (z domyślnego szablonu witryny internetowej) metody rozszerzenia konfigurują potok za pomocą następujących elementów:

  • Strony błędów
  • HTTP Strict Transport Security
  • Przekierowanie protokołu HTTP do HTTPS
  • ASP.NET Core MVC
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseMvc();
}

Host i aplikacja zostały rozłączone, dzięki czemu masz możliwość elastycznego przeniesienia na inną platformę w przyszłości.

Uwaga

Bardziej szczegółowe informacje na temat oprogramowania pośredniczącego i uruchamiania aplikacji na platformie można znaleźć w artykule Uruchamianie aplikacji na platformie ASP.NET Core.

Konfiguracje przechowywania

Platforma ASP.NET obsługuje ustawienia przechowywania. Służą one na przykład do obsługi środowiska, w którym wdrożono aplikacje. Powszechnie stosowaną praktyką było przechowywanie wszystkich niestandardowych par klucz-wartość w sekcji <appSettings> pliku Web.config:

<appSettings>
  <add key="UserName" value="User" />
  <add key="Password" value="Password" />
</appSettings>

Aplikacje odczytują te ustawienia przy użyciu kolekcji ConfigurationManager.AppSettings w przestrzeni nazw System.Configuration:

string userName = System.Web.Configuration.ConfigurationManager.AppSettings["UserName"];
string password = System.Web.Configuration.ConfigurationManager.AppSettings["Password"];

Platforma ASP.NET Core może przechowywać dane konfiguracji dla aplikacji w dowolnym pliku i ładować je podczas procesu uruchomienia oprogramowania pośredniczącego. Domyślny plik używany w szablonach projektu to appsettings.json:

{
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  },
  "AppConfiguration": {
    "UserName": "UserName",
    "Password": "Password"
  }
}

Ładowanie tego pliku do wystąpienia elementu IConfiguration wewnątrz aplikacji odbywa się w pliku Startup.cs:

public Startup(IConfiguration configuration)
{
    Configuration = configuration;
}

public IConfiguration Configuration { get; }

Aplikacja odczytuje element Configuration, aby pobrać ustawienia:

string userName = Configuration.GetSection("AppConfiguration")["UserName"];
string password = Configuration.GetSection("AppConfiguration")["Password"];

To podejście można rozszerzyć, aby zwiększyć niezawodność procesu, na przykład używając wstrzykiwania zależności do ładowania usługi z tymi wartościami. Zastosowanie podejścia ze wstrzykiwaniem zależności oferuje silnie typizowany zestaw obiektów konfiguracji.

// Assume AppConfiguration is a class representing a strongly-typed version of AppConfiguration section
services.Configure<AppConfiguration>(Configuration.GetSection("AppConfiguration"));

Uwaga

Bardziej szczegółowe informacje dotyczące konfiguracji platformy ASP.NET Core można znaleźć w artykule Konfiguracja w ASP.NET Core.

Natywne wstrzykiwanie zależności

Ważnym celem podczas kompilowania dużych i skalowalnych aplikacji jest możliwość dowolnego łączenia składników i usług. Wstrzykiwanie zależności to popularna technika, która umożliwia osiągnięcie tego celu. Jest to również natywny składnik platformy ASP.NET Core.

W przypadku aplikacji ASP.NET deweloperzy zakładają, że biblioteka innej firmy jest odpowiedzialna za zaimplementowanie wstrzykiwania zależności. Jedną z takich bibliotek jest aparat Unity udostępniany przez firmę Microsoft Patterns & Practices.

Przykład konfigurowania wstrzykiwania zależności przy użyciu biblioteki Unity to implementowanie mechanizmu IDependencyResolver opakowującego kontener UnityContainer:

using Microsoft.Practices.Unity;
using System;
using System.Collections.Generic;
using System.Web.Http.Dependencies;

public class UnityResolver : IDependencyResolver
{
    protected IUnityContainer container;

    public UnityResolver(IUnityContainer container)
    {
        if (container == null)
        {
            throw new ArgumentNullException("container");
        }
        this.container = container;
    }

    public object GetService(Type serviceType)
    {
        try
        {
            return container.Resolve(serviceType);
        }
        catch (ResolutionFailedException)
        {
            return null;
        }
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        try
        {
            return container.ResolveAll(serviceType);
        }
        catch (ResolutionFailedException)
        {
            return new List<object>();
        }
    }

    public IDependencyScope BeginScope()
    {
        var child = container.CreateChildContainer();
        return new UnityResolver(child);
    }

    public void Dispose()
    {
        Dispose(true);
    }

    protected virtual void Dispose(bool disposing)
    {
        container.Dispose();
    }
}

Utwórz wystąpienie kontenera UnityContainer, zarejestruj usługę i ustaw mechanizm rozpoznawania zależności w konfiguracji HttpConfiguration na nowe wystąpienie mechanizmu UnityResolver dla swojego kontenera:

public static void Register(HttpConfiguration config)
{
    var container = new UnityContainer();
    container.RegisterType<IProductRepository, ProductRepository>(new HierarchicalLifetimeManager());
    config.DependencyResolver = new UnityResolver(container);

    // Other Web API configuration not shown.
}

Przeprowadź wstrzykiwanie repozytorium IProductRepository w wymaganych miejscach:

public class ProductsController : ApiController
{
    private IProductRepository _repository;

    public ProductsController(IProductRepository repository)  
    {
        _repository = repository;
    }

    // Other controller methods not shown.
}

Ponieważ wstrzykiwanie zależności jest częścią platformy ASP.NET Core, możesz dodać usługę w metodzie ConfigureServices pliku Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    // Add application services.
    services.AddTransient<IProductRepository, ProductRepository>();
}

Repozytorium można wstrzyknąć w dowolnym miejscu (działa to również w przypadku biblioteki Unity).

Uwaga

Aby uzyskać więcej informacji na temat wstrzykiwania zależności, zobacz artykuł Wstrzykiwanie zależności.

Obsługa plików statycznych

Ważną częścią tworzenia programowania aplikacji internetowych jest zdolność obsługi zasobów statycznych po stronie klienta. Najbardziej typowe przykłady plików statycznych to pliki HTML, CSS, JavaScript i obrazy. Te pliki należy zapisać w opublikowanej lokalizacji aplikacji (lub usługi CDN) i odwołać się do nich, aby żądanie mogło je załadować. Ten proces zmienił się na platformie ASP.NET Core.

Na platformie ASP.NET pliki statyczne są przechowywane w różnych katalogach i przywoływane w widokach.

Na platformie ASP.NET Core pliki statyczne są przechowywane w „internetowym katalogu głównym” (<content root>/wwwroot), o ile nie zostanie skonfigurowany inny katalog. Te pliki są ładowane do potoku żądania przez wywołanie metody rozszerzenia UseStaticFiles z poziomu elementu Startup.Configure:

Uwaga

Jeśli program docelowy to .NET Framework, zainstaluj następujący pakiet NuGet: Microsoft.AspNetCore.StaticFiles.

Na przykład zasób obrazu w folderze wwwroot/images jest dostępny w przeglądarce, w lokalizacji takiej jak http://<app>/images/<imageFileName>.

Uwaga

Bardziej szczegółowe informacje na temat obsługi plików statycznych na platformie ASP.NET Core można znaleźć w artykule Pliki statyczne.

Wielowartościowe pliki cookie

Wielowartościowe pliki cookie nie są obsługiwane na platformie ASP.NET Core. Utwórz jeden plik cookie na wartość.

Pliki cookie uwierzytelniania nie są kompresowane na platformie ASP.NET Core.

Ze względu na bezpieczeństwo pliki cookie uwierzytelniania nie są kompresowane na platformie ASP.NET Core. Deweloperzy używający plików cookie uwierzytelniania powinni minimalizować ilość uwzględnianych informacji dotyczących oświadczeń tylko do informacji, które są dla nich niezbędne.

Częściowa migracja aplikacji

Jedno z podejść do częściowej migracji aplikacji to utworzenie podrzędnej aplikacji usług IIS i przeniesienie tylko określonych tras z platformy ASP.NET 4.x do ASP.NET Core z zachowaniem struktury adresu URL aplikacji. Rozważ na przykład strukturę adresu URL aplikacji z pliku applicationHost.config:

<sites>
    <site name="Default Web Site" id="1" serverAutoStart="true">
        <application path="/">
            <virtualDirectory path="/" physicalPath="D:\sites\MainSite\" />
        </application>
        <application path="/api" applicationPool="DefaultAppPool">
            <virtualDirectory path="/" physicalPath="D:\sites\netcoreapi" />
        </application>
        <bindings>
            <binding protocol="http" bindingInformation="*:80:" />
            <binding protocol="https" bindingInformation="*:443:" sslFlags="0" />
        </bindings>
    </site>
	...
</sites>

Struktura katalogów:

.
├── MainSite
│   ├── ...
│   └── Web.config
└── NetCoreApi
    ├── ...
    └── web.config

[BIND] i moduły formatowania danych wejściowych

Poprzednie wersje platformy ASP.NET używały atrybutu [Bind] do ochrony przed atakami polegającymi na przesyłaniu dodatkowych danych. Moduły formatowania danych wejściowych działają inaczej na platformie ASP.NET Core. Atrybut [Bind] nie ma już zapobiegać przesyłaniu dodatkowych danych w przypadku użycia razem z modułami formatowania danych wejściowych do analizowania kodu JSON lub XML. Atrybuty te wpływają na powiązanie modelu, jeśli źródło danych pochodzi z danych opublikowanych przy użyciu typu zawartości x-www-form-urlencoded.

Jeśli aplikacje publikują informacje w formacie JSON i analizują dane za pomocą modułów formatowania danych wejściowych JSON, zalecamy zastąpienie atrybutu [Bind] modelem widoku, który pasuje do właściwości zdefiniowanych przy użyciu atrybutu [Bind].

Dodatkowe zasoby