So aktualisieren Sie ein vorhandenes Projekt von ASP.NET MVC auf ASP.NET Core. Praktische Anleitung

Dieser Beitrag wurde aus unserer Erfahrung mit der Migration eines vorhandenen Projekts von ASP.NET MVC auf ASP.NET Core erstellt. Wir haben versucht, den gesamten Migrationsprozess in strukturierter Form zusammenzustellen und die verschiedenen Engpässe zu beschreiben, damit sich Entwickler weiterhin auf dieses Material verlassen und die Roadmap zur Lösung solcher Probleme befolgen können.

Ein paar Worte zu unserem Projekt. Wir sind eine Open-Source-E-Commerce-Plattform auf ASP.NET, die zum Zeitpunkt der Übertragung bereits seit 9 Jahren erfolgreich besteht. Wir haben die Migration vor 2 Jahren durchgeführt - aber unsere Hände kamen erst jetzt, um darüber zu schreiben. Zu dieser Zeit waren wir eines der ersten großen Projekte, die sich für einen solchen Schritt entschieden haben.

Warum zu ASP.NET Core wechseln?


Bevor Sie mit den Schritten zur Migration von ASP.NET MVC zu ASP.NET Core fortfahren, einige Worte zu den Vorteilen dieser Plattform.



Vorteile von ASP.NET Core
Daher ist ASP.NET Core bereits ein ziemlich bekanntes und entwickeltes Framework, das bereits mehrere wichtige Aktualisierungen erfahren hat. Dies bedeutet, dass es heute recht stabil, technologisch fortschrittlich und resistent gegen XSRF / CSRF-Angriffe ist.

Plattformübergreifend ist eines der Markenzeichen, die es ihm ermöglichen, immer beliebter zu werden. Von nun an kann Ihre Webanwendung sowohl in Windows- als auch in Unix-Umgebungen ausgeführt werden.

Modularität - ASP.NET Core wird vollständig in Form von NuGet-Paketen geliefert. Auf diese Weise können Sie die Anwendung einschließlich der ausgewählten erforderlichen Pakete optimieren. Dies verbessert die Leistung der Lösung und reduziert den Zeitaufwand für das Upgrade einzelner Teile. Dies ist die zweite wichtige Funktion, mit der Entwickler neue Funktionen flexibler in ihre Lösung integrieren können.

Die Leistung ist ein weiterer Schritt zum Erstellen einer Hochleistungsanwendung. ASP.NET Core verarbeitet 2300% mehr Anforderungen pro Sekunde als ASP.NET 4.6 und 800% mehr Anforderungen pro Sekunde als node.js. Detaillierte Leistungstests können Sie hier oder hier selbst prüfen.



Middleware ist die neue leichte modulare Hochleistungs-Pipeline für In-App-Anfragen. Jede Middleware verarbeitet eine HTTP-Anforderung und entscheidet sich dann entweder für die Rückgabe des Ergebnisses oder übergibt die nächste Middleware. Dieser Ansatz gibt dem Entwickler die vollständige Kontrolle über die HTTP-Pipeline und trägt zur Entwicklung einfacher Module für die Anwendung bei, was für ein wachsendes Open Source-Projekt wichtig ist.

ASP.NET Core MVC bietet Funktionen, die die Webentwicklung vereinfachen. NopCommerce verwendete bereits Funktionen wie die Model-View-Controller-Vorlage, die Razor-Syntax, die Modellbindung und die Validierung. Es wurden jedoch neue Tools veröffentlicht:

  • Tag Helfer. Dies ist serverseitiger Code, der zum Erstellen und Rendern von HTML-Elementen in Razor-Dateien beiträgt.
  • Komponenten anzeigen. Dies ist ein neues Tool, ähnlich wie Teilansichten, aber viel leistungsfähiger. nopCommerce verwendet Ansichtskomponenten, wenn die Wiederverwendung der Renderlogik erforderlich ist und die Aufgabe für eine Teilansicht zu komplex ist.
  • DIs Ansicht. Obwohl die meisten in den Ansichten angezeigten Daten vom Controller übergeben werden, verfügt nopCommerce über Ansichten, in denen die Abhängigkeitsinjektion bequemer ist.

Natürlich hat ASP.NET Core viel mehr Funktionen, aber wir haben gerade die interessantesten untersucht.

Lassen Sie uns nun darüber sprechen, was Sie beim Portieren Ihrer Anwendung auf eine neue Plattform beachten sollten.

Die Migration


Der Text enthält eine Vielzahl von Links zur offiziellen ASP.NET Core-Dokumentation, um detailliertere Informationen zum Thema zu erhalten. Besonders relevant für Entwickler, die zum ersten Mal vor einer ähnlichen Aufgabe stehen.

Schritt 1. Vorbereitung der Werkzeuge


Als erstes müssen Sie Visual Studio 2017 auf Version 15.3 oder höher aktualisieren. Installieren Sie die neueste Version des .NET Core SDK.

Bevor Sie mit der Migration beginnen, wird empfohlen, das Portability Analysis-Tool .NET .Net Portability Analyzer zu verwenden. Dies ist ein guter Ausgangspunkt, um zu verstehen, wie mühsam der Übergang von einer Plattform zur anderen sein wird. Aber dieses Tool löst natürlich nicht alle Probleme, und dabei gibt es viele Fallstricke. Als nächstes werden die Hauptphasen beschrieben, die bestanden werden müssen, und die in unserem Projekt verwendeten Lösungen werden gezeigt.

Als erstes müssen Sie die Links zu den im Projekt verwendeten Bibliotheken aktualisieren, die .NET Standard unterstützen würden.

Schritt 2. Kompatibilitätsanalyse von NuGet-Paketen zur Unterstützung von .Net Standard


Wenn Sie NuGet-Pakete in Ihrem Projekt verwenden, müssen Sie überprüfen, ob sie mit .NET Core kompatibel sind. Eine Möglichkeit hierfür ist die Verwendung des NuGetPackageExplorer- Tools.

Schritt 3. .NET Core verwendet das neue csproj-Dateiformat


Es ist wichtig, den neuen Ansatz zum Hinzufügen von in .NET Core eingeführten Links von Drittanbietern zu verwenden: Wenn der Lösung eine neue Klassenbibliothek hinzugefügt wird, sollten Sie die Hauptprojektdatei öffnen und deren Inhalt durch Folgendes ersetzen:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>netcoreapp2.2</TargetFramework> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.AspNetCore.App" Version="2.2.6" /> ... </ItemGroup> ... </Project> 

Links aus verbundenen Bibliotheken werden automatisch heruntergeladen. Weitere Informationen zur Zuordnung zwischen den Eigenschaften project.json und CSPROJ finden Sie in der offiziellen Dokumentation hier und hier .

Schritt 4. Aktualisieren des Namespace


Sie müssen alle Verwendungen von System.Web entfernen und durch Microsoft.AspNetCore ersetzen.

Schritt 5. Sie müssen die Datei Startup.cs konfigurieren. anstatt global.asax zu verwenden


ASP.NET Core verfügt über einen neuen Mechanismus zum Laden der Anwendung. Der Einstiegspunkt in die Anwendung wird zu Startup , und die Abhängigkeit von der Datei Global.asax verschwindet. Startup die Middleware-Suite in der Anwendung registriert. Startup muss die Configure Methode enthalten. Configure die erforderliche Middleware zur Pipeline hinzu.

Probleme mit Startup.cs

  1. Middleware für MVC- und WebAPI-Anforderungen konfigurieren
  2. Konfigurationseinstellungen für:


 //add basic MVC feature var mvcBuilder = services.AddMvc(); //add custom model binder provider (to the top of the provider list) mvcBuilder.AddMvcOptions(options => options.ModelBinderProviders.Insert(0, new NopModelBinderProvider())); /// <summary> /// Represents model binder provider for the creating NopModelBinder /// </summary> public class NopModelBinderProvider : IModelBinderProvider { /// <summary> /// Creates a nop model binder based on passed context /// </summary> /// <param name="context">Model binder provider context</param> /// <returns>Model binder</returns> public IModelBinder GetBinder(ModelBinderProviderContext context) { if (context == null) throw new ArgumentNullException(nameof(context)); var modelType = context.Metadata.ModelType; if (!typeof(BaseNopModel).IsAssignableFrom(modelType)) return null; //use NopModelBinder as a ComplexTypeModelBinder for BaseNopModel if (context.Metadata.IsComplexType && !context.Metadata.IsCollectionType) { //create binders for all model properties var propertyBinders = context.Metadata.Properties .ToDictionary(modelProperty => modelProperty, modelProperty => context.CreateBinder(modelProperty)); return new NopModelBinder(propertyBinders, EngineContext.Current.Resolve<ILoggerFactory>()); } //or return null to further search for a suitable binder return null; } } 



 app.UseMvc(routes => { routes.MapRoute("areaRoute", "{area:exists}/{controller=Admin}/{action=Index}/{id?}"); routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); 

Gleichzeitig sollte der Ordner mit dem Namen Bereich, in dem sich der Admin-Ordner befindet, im Stammverzeichnis der Anwendung abgelegt werden. Jetzt wird das Attribut [Area("Admin")] [Route("admin")] verwendet, um den Controller mit diesem Bereich zu verbinden.
Es müssen nur noch Ansichten für alle in der Steuerung beschriebenen Aktionen erstellt werden.


 [Area("Admin")] [Route("admin")] public class AdminController : Controller { public IActionResult Index() { return View(); } } 

Validierung

Jetzt müssen Sie IFormCollection nicht mehr an die Controller übergeben, da in diesem Fall die Servervalidierung von asp.net deaktiviert ist. MVC unterdrückt die weitere Validierung, wenn festgestellt wird, dass die IFormCollection nicht null ist. Die Lösung des Problems kann darin bestehen, diese Eigenschaft dem Modell hinzuzufügen. Dadurch wird verhindert, dass wir direkt an die Controller-Methode übergeben. Diese Regel ist nur gültig, wenn ein Modell vorhanden ist. Wenn jedoch kein Modell vorhanden ist, erfolgt keine Validierung.

Untergeordnete Eigenschaften werden nicht mehr automatisch überprüft. Es muss manuell angegeben werden.

Schritt 6. Übertragen von HTTP-Handlern und HTTP-Modulen auf Middleware


HTTP-Handler und HTTP-Module sind dem Middleware- Konzept in ASP.NET Core im Wesentlichen sehr ähnlich. Im Gegensatz zu Modulen basiert die Middleware-Reihenfolge jedoch auf der Reihenfolge, in der sie in die Anforderungspipeline eingefügt werden. Die Reihenfolge der Module basiert größtenteils auf Anwendungslebenszyklusereignissen . Die Reihenfolge der Middleware für die Antworten ist das Gegenteil der Reihenfolge der Anforderungen, und die Reihenfolge der Module für die Anforderungen und Antworten ist dieselbe. Auf dieser Grundlage können Sie mit dem Upgrade fortfahren.

Also, was bleibt noch zu aktualisieren:

  • Migration von Modulen für Middleware (AuthenticationMiddleware, CultureMiddleware usw.)
  • Handler für Middleware
  • Neue Middleware verwenden

Bei der Authentifizierung in unserem Projekt wird nicht das integrierte Anmeldeinformationssystem verwendet. Für diese Zwecke wird die Middleware AuthenticationMiddleware verwendet, die gemäß der neuen ASP.NET Core-Struktur entwickelt wurde.

 public class AuthenticationMiddleware { private readonly RequestDelegate _next; public AuthenticationMiddleware(IAuthenticationSchemeProvider schemes, RequestDelegate next) { Schemes = schemes ?? throw new ArgumentNullException(nameof(schemes)); _next = next ?? throw new ArgumentNullException(nameof(next)); } public IAuthenticationSchemeProvider Schemes { get; set; } public async Task Invoke(HttpContext context) { context.Features.Set<IAuthenticationFeature>(new AuthenticationFeature { OriginalPath = context.Request.Path, OriginalPathBase = context.Request.PathBase }); var handlers = context.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>(); foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync()) { try { if (await handlers.GetHandlerAsync(context, scheme.Name) is IAuthenticationRequestHandler handler && await handler.HandleRequestAsync()) return; } catch { // ignored } } var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync(); if (defaultAuthenticate != null) { var result = await context.AuthenticateAsync(defaultAuthenticate.Name); if (result?.Principal != null) { context.User = result.Principal; } } await _next(context); } } 

ASP.NET bietet viele eingebettete Middleware, die Sie in Ihrer Anwendung verwenden können. Beachten Sie jedoch, dass der Entwickler seine eigene Middleware erstellen und zur HTTP-Anforderungspipeline hinzufügen kann. Um diesen Mechanismus zu vereinfachen, haben wir eine spezielle Schnittstelle hinzugefügt. Jetzt reicht es aus, nur eine Klasse zu erstellen, die ihn implementiert.

 public interface INopStartup { /// <summary> /// Add and configure any of the middleware /// </summary> /// <param name="services">Collection of service descriptors</param> /// <param name="configuration">Configuration of the application</param> void ConfigureServices(IServiceCollection services, IConfiguration configuration); /// <summary> /// Configure the using of added middleware /// </summary> /// <param name="application">Builder for configuring an application's request pipeline</param> void Configure(IApplicationBuilder application); /// <summary> /// Gets order of this startup configuration implementation /// </summary> int Order { get; } } 

Hier können Sie Ihre Middleware hinzufügen und konfigurieren:

 /// <summary> /// Represents object for the configuring authentication middleware on application startup /// </summary> public class AuthenticationStartup : INopStartup { /// <summary> /// Add and configure any of the middleware /// </summary> /// <param name="services">Collection of service descriptors</param> /// <param name="configuration">Configuration of the application</param> public void ConfigureServices(IServiceCollection services, IConfiguration configuration) { //add data protection services.AddNopDataProtection(); //add authentication services.AddNopAuthentication(); } /// <summary> /// Configure the using of added middleware /// </summary> /// <param name="application">Builder for configuring an application's request pipeline</param> public void Configure(IApplicationBuilder application) { //configure authentication application.UseNopAuthentication(); } /// <summary> /// Gets order of this startup configuration implementation /// </summary> public int Order => 500; //authentication should be loaded before MVC } 

Schritt 7. Integriertes DI verwenden


Die Abhängigkeitsinjektion ist eine der Hauptfunktionen im Anwendungsentwurfsprozess in ASP.NET Core. Sie können damit lose gekoppelte Anwendungen erstellen, die testbarer, modularer und damit wartbarer sind. Möglich wurde dies durch das Prinzip der Abhängigkeitsinversion. Zum Installieren von Abhängigkeiten werden IoC-Container (Inversion of Control) verwendet. In ASP.NET Core wird ein solcher Container durch die IServiceProvider-Schnittstelle dargestellt. Dienste werden in der Anwendung in der Methode Startup.ConfigureServices() installiert.

Jeder registrierte Dienst kann mit drei Bereichen konfiguriert werden:

  • vorübergehend
  • Umfang
  • Singleton

 services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); services.AddSingleton<Isingleton,MySingleton>(); 

Schritt 8. Verwenden von WebAPI Project Compatibility Shells (Shim)


Um die Migration einer vorhandenen Web-API-Implementierung zu vereinfachen, wird empfohlen, das Microsoft.AspNetCore.Mvc.WebApiCompatShim NuGet-Paket zu verwenden. Folgende kompatible Funktionen werden unterstützt:

  • Fügt den ApiController-Typ hinzu
  • Aktiviert die Modellbindung im Web-API-Stil
  • Erweitert die Modellbindung, sodass Controller-Aktionen Parameter vom Typ HttpRequestMessage akzeptieren können.
  • Fügt Nachrichtenformatierer hinzu, mit denen Aktionen Ergebnisse vom Typ HttpResponseMessage zurückgeben können

 services.AddMvc().AddWebApiConventions(); routes.MapWebApiRoute(name: "DefaultApi", template: "api/{controller}/{id?}" ); 

Schritt 9. Anwendungskonfiguration übertragen


Zuvor wurden einige Einstellungen in der Datei web.config gespeichert. Wir verfolgen jetzt einen neuen Ansatz, der auf Schlüssel-Wert-Paaren basiert, die von Konfigurationsanbietern festgelegt wurden . Dies ist der empfohlene Mechanismus in ASP.NET Core, und wir verwenden die Datei appsettings.json.

Sie können auch das NuGet-Paket System.Configuration.ConfigurationManager wenn Sie aus irgendeinem Grund weiterhin * .config verwenden möchten. In diesem Fall müssen Sie die Möglichkeit aufgeben, die Anwendung auf Unix-Plattformen auszuführen, und sie nur unter IIS ausführen.

Wenn Sie den Azure Key Vault- Konfigurationsanbieter verwenden möchten, lesen Sie die Inhaltsmigration zu Azure Key Valut-Inhalten . In unserem Projekt war dies nicht die Aufgabe.

Schritt 10. Übertragen von statischem Inhalt auf wwwroot


Um statischen Inhalt bereitzustellen, müssen Sie dem Webhost das Stammverzeichnis des Inhalts des aktuellen Verzeichnisses mitteilen. Der Standardwert ist wwwroot. Sie können Ihr Verzeichnis zum Speichern statischer Dateien anpassen, indem Sie Middleware einrichten.



Schritt 11. Portieren von EntityFramework auf EF Core


Wenn das Projekt einige spezifische Funktionen von Entity Framework 6 verwendet , die in EF Core nicht unterstützt werden , ist es sinnvoll, die Anwendung auf dem NET Framework auszuführen. In diesem Fall müssen Sie jedoch die Multiplattform opfern. Die Anwendung funktioniert nur unter Windows und unter IIS.

Werfen wir einen Blick auf die wichtigsten Änderungen, die berücksichtigt werden müssen:

  • Der System.Data.Entity-Namespace wurde durch Microsoft.EntityFrameworkCore ersetzt
  • Die Signatur des DbContext-Konstruktors wurde geändert. Jetzt müssen Sie DbContextOptions injizieren
  • HasDatabaseGeneratedOption (DatabaseGeneratedOption.None) -Methode ersetzt durch ValueGeneratedNever ()
  • WillCascadeOnDelete (false) -Methode ersetzt durch OnDelete (DeleteBehavior.Restrict)
  • OnModelCreating (DbModelBuilder modelBuilder) -Methode ersetzt durch OnModelCreating (ModelBuilder modelBuilder)
  • Die HasOptional-Methode ist nicht mehr verfügbar
  • Die Konfiguration der Objekte wurde geändert. Jetzt müssen Sie OnModelCreating verwenden, da EntityTypeConfiguration ist nicht mehr verfügbar
  • Das ComplexType-Attribut ist nicht mehr verfügbar
  • Ersetzen der IDbSet-Schnittstelle durch DbSet
  • ComplexType - Unterstützung für komplexe Typen wurde in EF Core 2 mit dem Typ Owned Entity ( https://docs.microsoft.com/en-us/ef/core/modeling/owners-entities ) und Tabellen ohne Primärschlüssel mit QueryType in EF Core angezeigt 2.1 ( https://docs.microsoft.com/en-us/ef/core/modeling/query-types )
  • Fremdschlüssel in EF Core generieren Schatteneigenschaften mithilfe des ID-Musters [Entity], im Gegensatz zu EF6, das das _Id-Muster [Entity] verwendet. Fügen Sie der Entität daher zunächst Fremdschlüssel als reguläre Eigenschaft hinzu.
  • Um DI für DbContext zu unterstützen, konfigurieren Sie Ihren DbContex in ConfigureServices

 /// <summary> /// Register base object context /// </summary> /// <param name="services">Collection of service descriptors</param> public static void AddNopObjectContext(this IServiceCollection services) { services.AddDbContextPool<NopObjectContext>(optionsBuilder => { optionsBuilder.UseSqlServerWithLazyLoading(services); }); } /// <summary> /// SQL Server specific extension method for Microsoft.EntityFrameworkCore.DbContextOptionsBuilder /// </summary> /// <param name="optionsBuilder">Database context options builder</param> /// <param name="services">Collection of service descriptors</param> public static void UseSqlServerWithLazyLoading(this DbContextOptionsBuilder optionsBuilder, IServiceCollection services) { var nopConfig = services.BuildServiceProvider().GetRequiredService<NopConfig>(); var dataSettings = DataSettingsManager.LoadSettings(); if (!dataSettings?.IsValid ?? true) return; var dbContextOptionsBuilder = optionsBuilder.UseLazyLoadingProxies(); if (nopConfig.UseRowNumberForPaging) dbContextOptionsBuilder.UseSqlServer(dataSettings.DataConnectionString, option => option.UseRowNumberForPaging()); else dbContextOptionsBuilder.UseSqlServer(dataSettings.DataConnectionString); } 

Verwenden Sie das SQL Compare- Tool, um zu überprüfen, ob EF Core während der Migration ein ähnliches Datenbankschema wie das Entity Framework generiert.

Schritt 12. Entfernen aller HttpContext-Referenzen, Ersetzen veralteter Klassen und Ändern des Namespace


Während der Migration Ihres Projekts werden Sie feststellen, dass eine ausreichend große Anzahl von Klassen umbenannt oder verschoben wurde. Jetzt müssen Sie alles an die neuen Anforderungen anpassen. Hier ist eine Liste der wichtigsten Übergänge, auf die Sie stoßen können:

  • HttpPostedFileBase -> IFormFile
  • Der Zugriff auf HttpContext erfolgt jetzt über IHttpContextAccessor
  • HtmlHelper -> IHtmlHelper
  • ActionResult -> IActionResult
  • HttpUtility -> WebUtility
  • Anstelle von HttpSessionStateBase - ISession kann über HttpContext.Session zugegriffen werden. von Microsoft.AspNetCore.Http
  • Request.Cookies gibt IRequestCookieCollection zurück: IEnumerable <KeyValuePair <string, string >>, also anstelle von HttpCookie, KeyValuePair <string, string> von Microsoft.AspNetCore.Http

Namespace-Ersatz:

  • SelectList -> Microsoft.AspNetCore.Mvc.Rendering
  • UrlHelper -> WebUtitlity
  • MimeMapping -> FileExtensionContentTypeProvider
  • MvcHtmlString -> IHtmlString und HtmlString
  • ModelState, ModelStateDictionary, ModelError -> Microsoft.AspNetCore.Mvc.ModelBinding
  • FormCollection -> IFormCollection
  • Request.Url.Scheme -> this.Url.ActionContext.HttpContext.Request.Scheme

Sonstiges:

  • MvcHtmlString.IsNullOrEmpty (IHtmlString) -> String.IsNullOrEmpty (variable.ToHtmlString ())
  • [ValidateInput (false)] - ist im Allgemeinen nicht mehr vorhanden und wird nicht benötigt
  • HttpUnauthorizedResult -> UnauthorizedResult
  • [AllowHtml] - Es gibt keine Direktive mehr und sie wird nicht benötigt
  • TagBuilder.SetInnerText-Methode ersetzt - jetzt ist dies InnerHtml.AppendHtml
  • JsonRequestBehavior.AllowGet bei der Rückgabe von Json wird nicht mehr benötigt
  • HttpUtility.JavaScriptStringEncode. -> JavaScriptEncoder.Default.Encode
  • Request.RawUrl. Es ist erforderlich, Request.Path + Request.QueryString separat zu verbinden
  • AllowHtmlAttribute - keine Klasse mehr
  • XmlDownloadResult - jetzt können Sie einfach die Rückgabedatei (Encoding.UTF8.GetBytes (xml), "application / xml", "filename.xml") verwenden.
  • [ValidateInput (false)] - Es gibt keine Direktive mehr und sie wird nicht benötigt

Schritt 13. Aktualisieren der Authentifizierung und Autorisierung


Ich habe bereits oben geschrieben, dass in unserem Projekt die Authentifizierung nicht mithilfe des integrierten Identitätssystems implementiert wird, sondern in einer separaten Middleware-Schicht ausgeführt wird. ASP.NET Core verfügt jedoch über einen eigenen Mechanismus zum Bereitstellen von Anmeldeinformationen. Weitere Details finden Sie in der Dokumentation hier .

Zum Datenschutz verwenden wir MachineKey nicht mehr. Stattdessen verwenden wir die integrierte Datenschutzfunktion. Standardmäßig werden Schlüssel beim Start der Anwendung generiert. Das Data Warehouse kann sein:

  • Dateisystem - Dateisystem-basierter Keystore
  • Azure Storage - Datenschutzschlüssel im Azure Blob-Speicher
  • Redis - Datenschutzschlüssel im Redis-Cache
  • Registrierung - muss verwendet werden, wenn die Anwendung keinen Zugriff auf das Dateisystem hat
  • EF Core - Schlüssel werden in der Datenbank gespeichert

Wenn die integrierten Mechanismen nicht geeignet sind, können Sie Ihren eigenen Schlüsselspeichermechanismus angeben, indem Sie ein benutzerdefiniertes IXmlRepository bereitstellen .

Schritt 14. Aktualisieren von JS / CSS


Die Arbeitsweise mit statischen Ressourcen hat sich geändert: Jetzt sollten alle im Stammordner des wwwroot- Projekts gespeichert werden, sofern natürlich keine anderen Einstellungen angegeben sind.

Wenn Sie integrierte Javascript-Blöcke verwenden, wird empfohlen, diese an das Ende der Seite zu verschieben. Verwenden Sie einfach das Attribut asp-location = "Footer" für Ihre Tags. Die gleiche Regel gilt für js-Dateien.

Verwenden Sie die BundlerMinifier- Erweiterung als Ersatz für System.Web.Optimization. Auf diese Weise können Sie JavaScript und CSS beim Erstellen des Projekts binden und minimieren. Link zur Dokumentation.

Schritt 15. Ansichten migrieren


Untergeordnete Aktionen werden nicht mehr verwendet. Stattdessen bietet ASP.NET Core ein neues leistungsstarkes Tool - ViewComponents , das asynchron aufgerufen wird.

So erhalten Sie eine Zeichenfolge von ViewComponent:

 /// <summary> /// Render component to string /// </summary> /// <param name="componentName">Component name</param> /// <param name="arguments">Arguments</param> /// <returns>Result</returns> protected virtual string RenderViewComponentToString(string componentName, object arguments = null) { if (string.IsNullOrEmpty(componentName)) throw new ArgumentNullException(nameof(componentName)); var actionContextAccessor = HttpContext.RequestServices.GetService(typeof(IActionContextAccessor)) as IActionContextAccessor; if (actionContextAccessor == null) throw new Exception("IActionContextAccessor cannot be resolved"); var context = actionContextAccessor.ActionContext; var viewComponentResult = ViewComponent(componentName, arguments); var viewData = ViewData; if (viewData == null) { throw new NotImplementedException(); } var tempData = TempData; if (tempData == null) { throw new NotImplementedException(); } using (var writer = new StringWriter()) { var viewContext = new ViewContext( context, NullView.Instance, viewData, tempData, writer, new HtmlHelperOptions()); // IViewComponentHelper is stateful, we want to make sure to retrieve it every time we need it. var viewComponentHelper = context.HttpContext.RequestServices.GetRequiredService<IViewComponentHelper>(); (viewComponentHelper as IViewContextAware)?.Contextualize(viewContext); var result = viewComponentResult.ViewComponentType == null ? viewComponentHelper.InvokeAsync(viewComponentResult.ViewComponentName, viewComponentResult.Arguments): viewComponentHelper.InvokeAsync(viewComponentResult.ViewComponentType, viewComponentResult.Arguments); result.Result.WriteTo(writer, HtmlEncoder.Default); return writer.ToString(); } } 

Es ist nicht mehr erforderlich, HtmlHelper zu verwenden - ASP.NET Core verfügt über eine große Anzahl integrierter Helper-Tag-Funktionen ( Tag-Helfer ). Wenn die Anwendung ausgeführt wird, werden sie von der Razor-Engine auf der Serverseite verarbeitet und schließlich in Standard-HTML-Elemente konvertiert. Dies vereinfacht die Anwendungsentwicklung erheblich. Und natürlich können Sie Ihre eigenen Tag-Helfer implementieren.

Wir haben begonnen, die Abhängigkeitsinjektion in Ansichten zu verwenden, anstatt Einstellungen und Dienste mithilfe von EngineContext .

Die wichtigsten Punkte zur Migration von Ansichten:

  • Konvertieren Sie Views/web.config Views/_ViewImports.cshtml - wird zum Importieren von Namespaces und Views/web.config Views/_ViewImports.cshtml Abhängigkeiten verwendet. Diese Datei unterstützt keine anderen Razor Funktionen wie Funktions- und Abschnittsdefinitionen.
  • Konvertieren Sie namespaces.add in @using
  • Übertragen Sie alle Einstellungen in die Hauptanwendungskonfiguration
  • Scripts.Render und Styles.Render nicht vorhanden. Ersetzen Sie libman oder BundlerMinifier Links zur Ausgabe

Abschließend


Wir haben aus unserer Erfahrung gesehen, dass der Prozess der Migration einer großen Webanwendung eine sehr zeitaufwändige Aufgabe ist, die ohne Fallstricke kaum ausgeführt werden kann. Wir hatten vor, auf ein neues Framework umzusteigen, sobald die erste stabile Version veröffentlicht wurde, konnten es jedoch nicht sofort fertigstellen: Es gab einige wichtige Funktionen, die zu diesem Zeitpunkt noch nicht auf .NET Core übertragen worden waren, insbesondere im Zusammenhang mit EntityFramework. Daher mussten wir zuerst die nächste Version mit einem gemischten Ansatz veröffentlichen - der .NET Core-Architektur mit den .NET Framework-Abhängigkeiten.

Wir konnten das Projekt nach der Veröffentlichung von .NET Core 2.1 vollständig anpassen, da zu diesem Zeitpunkt bereits eine stabile Lösung für die neue Architektur vorhanden war. Es mussten lediglich einige Pakete ersetzt und die Arbeit mit EF Core neu geschrieben werden. Die vollständige Migration auf das neue Framework dauerte daher mehrere Monate.

Weitere Informationen zu unserem Projekt finden Sie in unserem Repository auf GitHub .

Source: https://habr.com/ru/post/de472738/


All Articles