Aspnetcore: Aktivieren Sie web.config-Transformationen für AspNetCore-Projekte in VS

Erstellt am 1. Mai 2017  ·  91Kommentare  ·  Quelle: dotnet/aspnetcore

Lassen Sie mich dem voranstellen, dass ich kein Fan von web.config bin, aber die Erfahrung mit der Veröffentlichung von AspNetCore-Apps auf IIS ist wirklich schlecht.

Das Konfigurationssystem von AspNetCore dreht sich um die Variable ASPNETCORE_ENVIRONMENT, auf deren Grundlage verschiedene Konfigurationen geladen und angewendet werden können.

Das Festlegen dieser Variable für bestimmte Bereitstellungen ist ein Albtraum und es scheint eine Menge Verwirrung zu geben, wie dies zu tun ist:

Der Kern des Problems scheint sich auf 2 Probleme zu reduzieren:

1) web.config-Transformationen, wie wir sie kennen, werden in ASP.NET Core-Projekten in VS nicht unterstützt
2) Die einzige vernünftige Möglichkeit, ASPNETCORE_ENVIRONMENT zu ändern, ist die Verwendung von web.config

Das Festlegen einer globalen ASPNETCORE_ENVIRONMENT ist keine Option, da dies für jede Site auf einem einzelnen Server festgelegt wird. web.config war früher eine eigenständige Konfiguration. Diese Abhängigkeit von einer globalen env-Variablen ist im IIS-Anwendungsfall nicht gut.

Alles in allem denke ich, dass die IIS-Veröffentlichungsgeschichte Anlass zur Sorge geben sollte, da viele Entwickler wie ich, die auf AspNetCore umsteigen, ihre vorhandene Infrastruktur für Bereitstellungen nutzen und Schritt für Schritt vorgehen möchten. Derzeit ist diese Geschichte zu kompliziert und nicht vollständig.

Ein weiteres Beispiel, bei dem ich web.config-Transformationen benötige: https://github.com/aspnet/Home/issues/1701#issuecomment -298273962

Hilfreichster Kommentar

Stimme dem ersten Post voll und ganz zu. Es ist vom Design her ziemlich flexibel, aber am Ende hat sich herausgestellt, dass es sehr schwer zu automatisieren ist. Ich habe beispielsweise eine App, die ich auf einem anderen Server in IIS veröffentliche. Es läuft auch auf lokalem IIS (über Ordner veröffentlichen). Also habe ich die Entwicklungsumgebung in web.config eingestellt. Aber dann muss ich es während der Veröffentlichung auf Produktion oder was auch immer ändern. Ziemlich gewöhnliche Aufgabe, denke ich. Ich glaube, es ist unmöglich, oder? Ich muss web.config auf Remoteservern manuell bearbeiten.

Idealerweise sollte die Einstellung der Umgebung über "dotnet publish" (für jedes Veröffentlichungsziel) unterstützt werden:

dotnet publish ... -environment=Production

dotnet publish könnte nach web.%Enviroment%.config (Web.Production.config, Web.Development.config) Dateien suchen und sie mit web.config zusammenführen (transformieren). Am Ende hätten wir den korrekten Wert von ASPNETCORE_ENVIRONMENT:

    <environmentVariables>
        <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="value passed to publish" />
    </environmentVariables>         

Alle 91 Kommentare

FWI, ich stimme zu. Wir müssen nur klarstellen, dass es für IIS-Einstellungen ist. Die andere Sache ist die Tatsache, dass wir uns von der Standardeinstellung web.config in der Vorlage entfernt haben, sodass dies herausgefunden werden muss.

/cc @sayedihashimi

Ist das nur für IIS? Ich denke, der Kern des Problems ist die Verwendung der ASPNETCORE_ENVIRONMENT-Variablen Fullstop, um einer Website mitzuteilen, in welcher Umgebung sie sich befindet.

Ich denke, ein ziemlich häufiges Szenario besteht darin, dass verschiedene Staging-/QA-Umgebungen auf derselben Box in derselben IIS-Instanz gehostet werden. Es kann drei Teams geben, die alle über ihre eigenen "Umgebungen" verfügen, in denen sie ihren Code testen können (z. B. einen bestimmten Zweig bereitstellen), aber sie verwenden alle dieselbe Box.

Wenn wir einen Beispielcode dafür nehmen, wie appsettings.json pro Umgebung umgeschaltet wird:

public Startup(IHostingEnvironment env) { var builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) .AddEnvironmentVariables(); Configuration = builder.Build(); }
Das obige Szenario wird nicht funktionieren, da die Umgebungsvariable systemweit ist. Es könnte IIS, nginix usw. sein, die davor sitzen und das Vertauschen der Konfiguration wird nicht funktionieren.

Meistens habe ich das Obige gesehen, es wurden Vorschläge gemacht, Docker zu verwenden oder etwas wie Puppet/Chef zu verwenden, um die App-Konfiguration zu verwalten, sodass es keine Appsettings gibt.{env}.json, aber ich denke, das macht den Pfad vollständig Framework MVC so viel schwieriger.

@mindingdata Sie können tatsächlich die Logik steuern, die bestimmt, woher die Umgebung in Ihrem Program.cs . Die Umgebungsvariable ist nur eine Möglichkeit, dies zu deklarieren (die Hauptmethode). Wenn Sie etwas anderes basierend auf einer magischen Datei oder einer Tageszeit tun möchten, rufen Sie UseEnvironment(environmentName) auf der WebHostBuidler

Nur zur Verdeutlichung, dies ist absolut nur für die IIS-Konfiguration. Das aktuelle JSON-Konfigurationssystem für App-Einstellungen ist ziemlich gut und ich kann es uneingeschränkt empfehlen.

Um die Dinge weiter zu verwirren: Ich stelle fest, dass es einfach nicht funktioniert, wenn ich web.config verwende, um zu versuchen, die Systemumgebungseinstellung zu überschreiben. Wenn meine Systemumgebungseinstellung auf "Entwicklung" eingestellt ist und ich versuche, sie mit der web.config (wie unten) auf "Produktion" einzustellen, denkt die Anwendung immer noch, dass sie in der Entwicklung ausgeführt wird. (ASP.NET Core-App, die in IIS ausgeführt wird).

<environmentVariables>
      <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Production" />
</environmentVariables>

Ich denke, das ist der richtige Ort. Ich baue eine N-Tier-Demo und kann nicht herausfinden, wie ich IHostingEnvironment in mein Datenzugriffsschichtprojekt einfüge. Über dieses Projekt greife ich auf meine Datenbank zu und die einzige Möglichkeit, die Verbindungszeichenfolge zu dieser Ebene zu erhalten, bestand darin, die OnConfiguring-Methode mit einer magischen Zeichenfolge der Konfigurationsdatei zu überschreiben.

Ich habe mir auch Slow-Cheetah angesehen, aber das scheint die aktuelle Methode von "Debug, Release" oder "Development, Production" zu umgehen, je nachdem, ob Sie die VS-Methode oder die Umgebungsvariablen verwenden.

Es muss Informationen geben, die mir fehlen. MS kann nicht wollen, dass jeder Single-Tier-Apps erstellt.

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
           var builder = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json");

            var config = builder.Build();
            var connstr = config.GetConnectionString("connStr");            
            optionsBuilder.UseSqlServer(connstr);
        }

gibt es diesbezüglich also Fortschritte?

Wir sollten in der Lage sein, die Umgebung in der Konfiguration für eine App festzulegen, ohne auf Magie zurückgreifen zu müssen

Ja, ich hätte auch gerne Fortschritte. Ich habe derzeit keine Ahnung, wie ich mit verschiedenen Umgebungsvariablen separate Projekte in derselben Box veröffentlichen soll.

Am Ende habe ich eine ziemlich einfache Lösung gefunden. In der Hauptdatei appsettings.json gebe ich meine gewünschte Umgebung an:

{
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "ActiveEnvironment": "Development"
}

In Program.CS erstelle ich dann eine IConfiguration und setze den Umgebungsnamen auf den Wert von 'ActiveEnvironment', bevor ich die umgebungsspezifische Konfigurationsdatei lade.

public static void Main(string[] args)
{
    WebHost.CreateDefaultBuilder()
    .ConfigureAppConfiguration((hostingContext, config) =>
    {
        // Get the environment from our hostContext.
        var env = hostingContext.HostingEnvironment;
        config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);

        // Build an initial configuration.
        IConfiguration Configuration = config.Build();

        // Set the environment name.
        env.EnvironmentName = Configuration.GetSection("ActiveEnvironment").Value;

        // Load the configuration file for our specific environment.
        config.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: false, reloadOnChange: true)
        .AddEnvironmentVariables();
    })
    .UseStartup<Startup>()
    .Build()
    .Run();
}

Beim Veröffentlichen in verschiedenen Umgebungen muss die 'ActiveEnvironment' natürlich entsprechend geändert werden.

@DaleMckeown Ich wollte etwas Ähnliches tun, hatte aber eine Frage zu Ihrer Implementierung. Wie ich sehe, verwenden Sie Microsoft.AspNetCore.WebHost, um die Standardkonfiguration zu erstellen. Gilt dieser Ansatz noch für eine Konsolenanwendung ohne Webkomponenten?

@Swazimodo Ich habe diese Lösung nicht im Kontext einer Konsolenanwendung ausprobiert, daher bin ich mir nicht sicher. Am besten prüfen Sie, ob es eine alternative Möglichkeit zum Festlegen der Umgebungsvariablen für Konsolenanwendungen gibt.

Wir haben uns anders darum gekümmert. Wir haben unseren Build-Agenten eingerichtet, um zu nehmen
die umgebungsspezifische Einstellungsdatei und überschreiben Sie die Stammeinstellungsdatei
damit. Unser Build erstellt eine separate ZIP-Datei für jede Umgebung, die wir
bereitstellen zu.

Am Do, 26. Oktober 2017 um 12:48 Uhr, Dale Mckeown [email protected]
schrieb:

@Swazimodo https://github.com/swazimodo Ich habe diese Lösung nicht ausprobiert
im Kontext einer Konsolenanwendung, daher bin ich mir nicht sicher. Am besten ist es zu
Sehen Sie nach, ob es eine alternative Möglichkeit gibt, die Umgebungsvariablen für . zu setzen
Konsolenanwendungen.


Sie erhalten dies, weil Sie diesen Thread abonniert haben.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/aspnet/Home/issues/2019#issuecomment-339728441 oder stumm
der Faden
https://github.com/notifications/unsubscribe-auth/AAx4bT20JSb0XSzNBIAiiubq9mTVKbW5ks5swLf6gaJpZM4NMx25
.

Es scheint, dass alle Lösungen eine Art Post-Build/Publish-Optimierung erfordern? Am Ende habe ich eine leere Textdatei im App-Stamm abgelegt und diese als Umgebung übergeben. Habe ich etwas vergessen?

Stimme dem ersten Post voll und ganz zu. Es ist vom Design her ziemlich flexibel, aber am Ende hat sich herausgestellt, dass es sehr schwer zu automatisieren ist. Ich habe beispielsweise eine App, die ich auf einem anderen Server in IIS veröffentliche. Es läuft auch auf lokalem IIS (über Ordner veröffentlichen). Also habe ich die Entwicklungsumgebung in web.config eingestellt. Aber dann muss ich es während der Veröffentlichung auf Produktion oder was auch immer ändern. Ziemlich gewöhnliche Aufgabe, denke ich. Ich glaube, es ist unmöglich, oder? Ich muss web.config auf Remoteservern manuell bearbeiten.

Idealerweise sollte die Einstellung der Umgebung über "dotnet publish" (für jedes Veröffentlichungsziel) unterstützt werden:

dotnet publish ... -environment=Production

dotnet publish könnte nach web.%Enviroment%.config (Web.Production.config, Web.Development.config) Dateien suchen und sie mit web.config zusammenführen (transformieren). Am Ende hätten wir den korrekten Wert von ASPNETCORE_ENVIRONMENT:

    <environmentVariables>
        <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="value passed to publish" />
    </environmentVariables>         

@evil-shrike schau auf https://github.com/nil4/dotnet-transform-xdt für Build/Publish Time Config Transformationen.

Ein Anwendungsfall vielleicht. Ich benötige das Schreiben von Protokollen in .\App_Data, da mein Anwendungsläufer Lese-/Schreibzugriff auf alles unter .\App_Data hat, aber alles andere unter .\ nur lesen kann. Ich verwende Web Deploy und möchte eine web.config wie diese mit dem Logs-Ordner unter App_Data bereitstellen:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <handlers>
      <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
    </handlers>
    <aspNetCore processPath=".\<assembly>.exe" stdoutLogEnabled="true" stdoutLogFile=".\App_Data\logs\stdout" />
  </system.webServer>
</configuration>

Sie könnten sich fragen, warum diese Einstellungen nicht einfach in einer web.config-Datei statt in web.release.config abgelegt werden. Nun, processPath=".\<executable>.exe" ist nicht der Ort, an dem die ausführbare Datei lebt, wenn ich lokal gegen IIS Express entwickle. Also erhalte ich den guten alten Fehler "HTTP Error 502.5 - Process Failure".

Wir automatisieren unsere Builds mit Jenkins, und unsere bisherige Methode zur Durchführung von Vars-Konfigurationen pro Umgebung in NetFramework-Projekten besteht in web.config-Transformationen. Also dachten wir, dass wir das auch in Dotnet machen können.

Es stellt sich heraus, dass msbuild immer noch mit aspnet core csproj kompatibel ist, um web.config-Transformationen durchzuführen!

Wir können die Veröffentlichungsaufgabe TransformXml im Asp.Net Core csproj hinzufügen:

<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v15.0\Web\Microsoft.Web.Publishing.Tasks.dll" />

Fügen Sie die spezifischen Transformationsziele hinzu:

<Target Name="ConfigDev">
    <TransformXml Source="web.config" Transform="web.dev.config" Destination="web.config" /></Target>

Führen Sie einige Transformationen durch, zum Beispiel an der Variablen ASPNETCORE_ENVIRONMENT in web.dev.config :

<system.webServer>
    <aspNetCore processPath="dotnet" arguments=".\Test.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" >
      <environmentVariables>
        <environmentVariable xdt:Locator="Match(name)" name="ASPNETCORE_ENVIRONMENT" value="dev" xdt:Transform="SetAttributes" />
      </environmentVariables>
    </aspNetCore>
</system.webServer>

Transformieren Sie web.config mit msbuild bevor Sie veröffentlichen:

msbuild Test.csproj /t:ConfigDev

"Ich möchte dem voranstellen, dass ich kein Fan von web.config bin, aber die Erfahrung mit der Veröffentlichung von AspNetCore-Apps auf IIS ist wirklich schlecht."

Ich kann diesem Thread nicht mehr zustimmen.

Nach der Einfachheit der Konfigurationstransformationen in regulärem ASP.Net stinkt diese ganze Abhängigkeit von einer maschinenweiten ASPNETCORE_ENVIRONMENT- Variablen.

Sogar Microsofts eigene Beispiele besagen, dass wir beispielsweise eine _appsettings.Production.json_-Datei verwenden können, indem wir einfach diese Zeile hinzufügen ...

            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);

...aber der NAME der gewählten Konfiguration wird nicht beachtet. Selbst wenn ich meine Produktionskonfiguration ausgewählt habe, wird immer noch versucht, appsettings.development.json zu öffnen. Und nein, ich möchte die Variable ASPNETCORE_ENVIRONMENT nicht jedes Mal manuell bearbeiten müssen, wenn ich in einer anderen Umgebung veröffentliche. Das macht nur Ärger.

Ich habe noch kein einfaches, funktionierendes Beispiel für die Verwendung von _appsettings.XXXX.json_-Dateien gesehen.
Ich kann es kaum erwarten, dass das Zeug endlich fertig ist. (Seufzen...)

Ja, bitte beheben Sie das !!

Ich habe gerade meine erste Produktions-Dotnet-Core-Site bereitgestellt und stehe nun vor dem Problem, dass ich nicht ohne weiteres eine Staging-Instanz auf demselben Server haben kann, weil ich nicht weiß, wie ich meine App auf derselben Box veröffentlichen soll, ohne dass sie die Produktionseinstellungen.

Ich denke, ich werde die @DaleMckeown- Lösung

@willapp Mein Vorschlag ist definitiv ein Workaround. Aber es funktioniert - ich habe seit einiger Zeit mehrere Versionen derselben App auf demselben Server laufen und hatte keine Probleme.

Denken Sie daran, die Einstellung "ActiveEnvironment" vor der Veröffentlichung zu ändern, und Sie sollten in Ordnung sein.

Ich stehe genau vor dem, was dkent600 erwähnt hat:

<environmentVariables>
      <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Production" />
</environmentVariables>

funktioniert nicht auf dem Produktionsserver. Die Anwendung verwendet weiterhin "appsettings.Development.json"-Werte, was letztendlich die Vorteile der XML-Transformation beim Veröffentlichen zunichte macht.

Ich werde die von DaleMckeown vorgeschlagene Problemumgehung versuchen.

die einzige vernünftige Möglichkeit, ASPNETCORE_ENVIRONMENT zu ändern, ist die Verwendung von web.config

Nicht wirklich. Wenn Sie mehrere Instanzen derselben Site auf demselben Computer ausführen müssen, ist dies ein viel einfacherer Weg

  • MyCoreSite

    • Behälter

    • Protokolle

  • env.Was auch immer

Richten Sie Ihre IIS-App auf bin und in program.cs

.UseEnvironment(ReadEnvExtensionFromParentFolder())

Das ist es. Sie können so viele Sites haben, wie Sie möchten, in bin bereitstellen, ohne sich um die Transformation kümmern zu müssen, und sogar die Umgebung wechseln, indem Sie env.Whenver umbenennen.

Ich befürworte das. Ich habe URL-Rewrites für den Produktionsserver konfiguriert, die in der Testumgebung nicht funktionieren. Ich habe für die Veröffentlichung keine Möglichkeit gefunden, die richtige web.config-Datei für die Bereitstellung auszuwählen, ich muss sie manuell kopieren.

Gibt es diesbezüglich Fortschritte? Es sind 13 Monate seit dem ersten Bericht vergangen, 2.1.0 ist jetzt da, und die Dinge sind immer noch ziemlich schlecht mit traditionellem IIS-Hosting. Die Dinge funktionieren wunderbar, wenn Sie Azure verwenden, aber das ist derzeit keine Option für einen Großteil der Sites, die ich hoste.

Es scheint, dass es für traditionelles IIS-Hosting von Vorteil wäre, die gewünschte Umgebung auf der Befehlszeile (wie @evil-shrike oben dargelegt) und auch in allen .pubxml Veröffentlichungsprofilen festzulegen. Wie @davidfowl sagte, müsste klar sein, dass dies nur mit web.config und IIS funktionieren würde, aber das deckt sicherlich immer noch einen erheblichen Teil der Installationsbasis ab.

Im Moment habe ich eine sehr spröde Lösung mit Microsoft.DotNet.Xdt.Tools und web.config Übersetzung, aber es erfordert eine Build-Konfiguration pro Umgebung, um zu funktionieren, und ist gerade nach dem Update auf v2.1.0 kaputt gegangen.

Es wäre schön zu hören, ob es in diesem Bereich Pläne gibt und wenn ja, welche? Wenn es keine Pläne gibt oder sie in weiter Ferne liegen, dann gibt es doch sicher eine bessere Zwischenlösung als die spröde/semi-manuelle Vorgehensweise, die wir derzeit anwenden müssen? Insbesondere für die Bereitstellung in QA und Staging möchte ich in VS nur einen Knopf drücken und wissen, dass das Richtige passiert, und nicht auf Kopfwissen und manuelle Prozesse angewiesen sein.

Wir haben derzeit keine Pläne, aber dieses Tool https://github.com/nil4/xdt-samples/ von @nil4 sieht ziemlich gut aus.

@svallis hast du es probiert?

Ist die Hauptsache, die die Leute wollen, die Umgebung?

@davidfowl Ja, meine aktuelle Lösung verwendet das von Ihnen verlinkte Tool, aber für ein Projekt mit mehreren Zielen zum Veröffentlichen ist eine Build-Konfiguration pro Umgebung erforderlich. Sie benötigen die verschiedenen Build-Konfigurationen, um sich im csproj Setup zu verriegeln, und für meine Zwecke ist es im Allgemeinen eine 1-zu-1-Beziehung zu Ihren Umgebungen. Beispielsweise:

  • Build-Konfiguration: Debug = Umgebung: Entwicklung
  • Build-Konfiguration: Staging = Umgebung: Staging
  • Build-Konfiguration: Release = Umgebung: Produktion

Für die letzten beiden habe ich dann die entsprechenden web.{Build configuration}.config und appsettings.{Environment}.json , und das web.{Build configuration}.config ist buchstäblich nur ein XDT, um den web.config mitzuteilen, dass sie mit dem enden sollen entsprechende Umgebungsvariable ASPNETCORE_ENVIRONMENT . Wenn man das obige Beispiel fortsetzt, sieht web.Release.config Beispiel so aus:

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <system.webServer>
    <aspNetCore>
      <environmentVariables>
        <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Production" xdt:Transform="SetAttributes" xdt:Locator="Match(name)" />
      </environmentVariables>
    </aspNetCore>
  </system.webServer>
</configuration>

Dies funktioniert eigentlich alles ziemlich gut von der Befehlszeile aus. Das Ausführen von dotnet publish -c Staging oder was auch immer erzeugt einen Ordner mit der richtigen Ausgabe und den web.config , die wie erforderlich umgewandelt werden. Es fühlt sich jedoch so an, als ob es vereinfacht werden könnte. Wenn es einen -iisenvironment Schalter auf dotnet publish gäbe, der dies für uns erledigt, und dieser dann als einfaches Textfeld im VS-Publishing angezeigt würde, würde dies die Verwaltung von Build-Konfigurationen, XDTs, usw. manuell für traditionelle IIS-Hosting-Situationen.

Innerhalb von VS scheint es derzeit jedoch problematisch zu sein. Wir können derzeit jedoch überhaupt nicht aus VS heraus veröffentlichen, und selbst als es in v2.0.0 funktionierte, mussten wir vor der Veröffentlichung die richtige Build-Konfiguration manuell auswählen.

@davidfowl Aus meiner Sicht möchte ich idealerweise die Umgebung als Teil des Veröffentlichungsprofils festlegen, wenn ich Web Deploy verwende.

Ich würde das an zweiter Stelle setzen, eine Option zur Veröffentlichung wäre ideal. Ich verwende nicht einmal die von @svallis beschriebene

@willapp Die von mir verwendete Lösung funktioniert in Visual Studio, aber ich habe andere Probleme mit der Lösung, mit der ich csproj , die sowohl die Befehlszeile als auch VS respektieren sollten.

Endlich habe ich das von ausprobiert und es funktioniert! 👍

Folgen Sie einfach den Anweisungen hier https://github.com/nil4/dotnet-transform-xdt im Abschnitt "Tool auf Projektebene" (da ich noch nicht auf 2.1.0 bin). Ich musste selbst eine Standard-Web.config erstellen, da ich sie nicht hatte (nur kopierte sie von der, die VS bei der Bereitstellung generiert), dann eine Web.Debug.config mit einer Transformation erstellt, um ASPNETCORE_ENVIRONMENT auf Entwicklung zu setzen, und hey presto! Es stellt die transformierte Konfiguration bereit und die Site wird jetzt ordnungsgemäß gestartet.

Wäre schön, wenn die Unterstützung dafür offiziell gemacht würde, aber im Moment macht dies den Job.

@davidfowl Der Link, auf den Sie verwiesen haben, erfordert die Veröffentlichung über die Befehlszeile. Ich möchte mit dem VS GUI-Tool veröffentlichen. Ich möchte nicht, dass meine Entwickler CLI-Tools installieren müssen, um das Projekt zu veröffentlichen. Es macht keinen Sinn, ASPNETCORE_ENVIRONMENT in web.config anzugeben, wenn Transformationen nicht unterstützt werden. Wenn man sieht, wie viele positive Stimmen dieses Problem hat, sollte es in den Backlog gehen.

@orobert91 VS ist nur eine GUI, die um die Befehlszeilentools gewickelt ist. Ich verwende erfolgreich https://github.com/nil4/xdt-samples/, um web.config während der Veröffentlichung aus VS heraus zu transformieren. Wenn Sie es für Ihr Projekt richtig konfigurieren, wird es sowohl über die Befehlszeile als auch in Ihrer IDE korrekt transformiert.

@svallis In der Tat, die Dokumente falsch gelesen. Ich habe mein Problem mit einer einfachen Kopieraufgabe gelöst:

  <Target Name="CopyFiles" AfterTargets="Publish">  
      <Copy SourceFiles="web.$(Configuration).config" DestinationFiles="web.config" />  
  </Target>   

Es gibt eine msbuild-Eigenschaft, die Auszeichnungen für den Umgebungsnamen veröffentlicht -

$(Umgebungsname)

(https://github.com/aspnet/websdk/blob/d7d73e75918ec3168bd3e5d519d0decc04675faf/src/Publish/Microsoft.NET.Sdk.Publish.Targets/netstandard1.0/TransformTargets/Microsoft.NET.Sdk ).

Wenn diese Eigenschaft jetzt festgelegt ist, erstellen wir nur appsettings.$(EnvironmentName).json und fügen die Verbindungszeichenfolge-Informationen zu dieser Datei hinzu (falls angefordert).

Wenn diese Eigenschaft während der Veröffentlichung festgelegt wird, können wir in Zukunft auch die veröffentlichte web.config aktualisieren, sodass sie auch den folgenden Eintrag enthält:

<environmentVariables>
      <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="$(EnvironmentName)" />
</environmentVariables>

Würde dies für die meisten der hier erwähnten Szenarien funktionieren?

Für die Szenarien außerhalb des Setzens der EnvironmentVariable werden wir uns die Machbarkeit der Portierung der web.config-Transformationen ( Xdt ) für Kernprojekte

Ich habe eine Lösung gefunden, die die von mir benötigten Szenarien abzudecken scheint - ich wollte sie hier posten, falls sie für andere hilfreich ist.

In meinem Fall habe ich meine Entwicklungsumgebung lokal und sowohl meine Staging- als auch meine Produktionsumgebung auf einem Remoteserver (gleicher Server). Ich konnte die Anwendungs-URL aus IApplicationBuilder und diese in einer switch Anweisung verwenden, um den EnvironmentName Wert festzulegen.

Es scheint viel weniger "workaround-ish" zu sein als einige der anderen angebotenen Lösungen, aber es kommt sicherlich auf die Präferenz an.

In Startup.cs :

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            env.DetectAndSet(app);

            ... other config method stuff here ...
        }

Die obige Methode ist eine Erweiterung, die ich basierend auf der Eigenschaftensammlung innerhalb von IApplicationBuilder . Die Erweiterungsmethode (und Klasse) sieht so aus:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Hosting.Server.Features;
using System.Linq;

namespace MyRootNamespace.Common.Extensions
{
    public static class IHostingEnvironmentExtensions
    {
        /// <summary>
        /// Detects the current hosting url and sets the <see cref="IHostingEnvironment.EnvironmentName"/> accordingly.
        /// </summary>
        /// <param name="env">The <see cref="IHostingEnvironment"/> to set.</param>
        /// <param name="app">The <see cref="IApplicationBuilder"/> used to retrieve the current app url.</param>
        public static void DetectAndSet(this IHostingEnvironment env, IApplicationBuilder app)
        {
            var _appUrl = string.Empty;

            try
            {
                _appUrl = ((FeatureCollection)app.Properties["server.Features"]).Get<IServerAddressesFeature>()?.Addresses?.FirstOrDefault();
            }
            catch { }

            switch (_appUrl)
            {
                case "https://www.myurl.com":
                case "http://www.myurl.com":
                    env.EnvironmentName = EnvironmentName.Production;
                    break;
                case "https://staging.myurl.com":
                case "http://staging.myurl.com":
                    env.EnvironmentName = EnvironmentName.Staging;
                    break;
                default:
                    env.EnvironmentName = EnvironmentName.Development;
                    break;
            }
        }
    }
}

Ich hoffe, dies kann den Leuten von Nutzen sein (in den Fällen, in denen eine web.config Transformation nicht wünschenswert ist).

Beifall!

Ich markiere dieses Problem als Diskussion, da derzeit keine diesbezüglichen Funktionen/Korrekturen geplant sind. Wenn Leute immer noch spezielle Funktionswünsche haben, melden Sie diese bitte und wir werden Prioritäten setzen.

Ich war mit den Workarounds, die ich in diesem Thread gesehen habe, nicht wirklich zufrieden, also habe ich einen anderen Ansatz gewählt. Ich bin über diesen Thread Stack Overflow gestolpert: https://stackoverflow.com/questions/31049152/publish-to-iis-setting-environment-variable/36836533#36836533. Es spricht davon, ApplicationHost.config auf dem Server zu ändern, um die Variable ASPNETCORE_ENVIRONMENT zu speichern.

Unsere internen IIS-Server werden von unserem Betriebsteam verwaltet, sodass die Entwickler in unserer Organisation diese Sites sowieso nicht erstellen. Das Betriebsteam verwendet ein PowerShell-Skript, um diese Websites zu erstellen. Ich habe sie nur gebeten, dieses Skript so zu ändern, dass es zum Zeitpunkt der Bereitstellung der Site auch die relevanten Änderungen an ApplicationHost.config vornimmt. Jetzt kann ich einfach dort bereitstellen und muss mich nicht um die Verwaltung der .NET Core-Umgebung kümmern. Hat für unsere Situation gut funktioniert.

Ich würde denken, dass Sie in einer echten DevOps-Umgebung wahrscheinlich sowieso Azure verwenden würden, was es sehr einfach macht, die Umgebungsvariable festzulegen.

Mit dem neuesten SDK können Sie einfach die msbuild-Eigenschaft $(EnvironmentName) und das Tooling kümmert sich darum, ASPNETCORE_ENVIRONMENT auf diesen Wert zu setzen.

zB: Wenn EnvironmentName auf staging gesetzt ist, dann hat web.config den folgenden Eintrag:

      <aspNetCore processPath="dotnet" arguments=".\WebApplication242.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout">
        <environmentVariables>
          <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Staging" />
        </environmentVariables>
      </aspNetCore>

PR mit dem Fix:
https://github.com/aspnet/websdk/pull/377

@vijayrkn Sieht nach einem vielversprechenden Start aus. Wird dies schließlich in VS WebDeploy/publish-Profile usw. integriert sein?

Im Moment haben wir in VS keine Benutzeroberfläche, um diese Umgebungsnamensauswahl vorzunehmen, aber wenn dies der Projektdatei oder der pubxml hinzugefügt wird, wird dies sowohl für die Veröffentlichung von VS als auch für die Befehlszeile berücksichtigt.

Wir werden uns auch darum bemühen, die UI-Unterstützung dafür hinzuzufügen.

@vijayrkn Dies ist nur eine Lösung für diejenigen, die mit einer web.config -Datei veröffentlichen - ist das richtig?

@vijayrkn Ja, die Unterstützung im pubxml Format wäre der Moment, in dem dies für unseren Anwendungsfall nützlich wäre. An diesem Punkt könnten wir den ganzen XML-Transformationskram löschen und einfach die entsprechenden Umgebungsstrings in jedem pubxml angeben. Die UI-Unterstützung könnte zu einem späteren Zeitpunkt folgen, aber das wäre nur das i-Tüpfelchen.

@challamzinniagroup - Nein, Sie benötigen keine web.config für diese Funktionalität.
Alles, was Sie tun müssen, ist, der pubxml-Datei Folgendes hinzuzufügen, und die Veröffentlichungstools erledigen den Rest.

<EnvironmentName>YourCustomEnvironment</EnvironmentName>

@challamzinniagroup , @vijayrkn

Sofern Sie keine Konfiguration haben, die nur in web.config vorgenommen werden kann und zwischen Umgebungen umgewandelt werden muss, lassen Sie andernfalls web.config in Ruhe. Mit 2 Codezeilen können Sie Umgebungsvariablen von überall aus lesen. Und Sie müssen weder das Veröffentlichungsprofil noch den veröffentlichten Code anpassen, sondern nur eine Liste der passenden Appsettings.XYZ.json

@ThisNoName

Sie meinen wie Datenbankverbindungszeichenfolgen, Dienstendpunkte, Anmeldeinformationen oder eine beliebige Anzahl anderer Dinge, die sich von dev->staging->production ändern würden.

Wenn Sie mehrere Instanzen in derselben Umgebung ausführen ( sehr häufig außerhalb der Cloud), benötigen Sie unbedingt die Flexibilität von web.config-Transformationen. Es ist ziemlich lächerlich, dass Microsoft diese Anforderung nicht sofort mit dem Dotnet-Kern erfüllt hat, sondern einfach davon ausgegangen ist, dass jeder in Azure hostet und eine 1:1-Beziehung zwischen Instanz und Umgebung besteht.

Umgebungsvariablen saugen tatsächlich außerhalb der Cloud, da Sie am Ende eine Konfiguration haben, die von Ihrer App getrennt ist, was es schwieriger macht, Bereitstellungen vollständig zu verwalten.

Die wichtigste Änderung besteht darin, dass diese Geheimnisse niemals in der Quellcodeverwaltung gespeichert werden sollten, sondern stattdessen in der Umgebung selbst konfiguriert werden sollten. Transforms verstößt gegen bewährte Verfahren, da davon ausgegangen wird, dass Sie das Bereitstellungsziel zum Zeitpunkt der Veröffentlichung verstehen, was nicht immer der Fall ist (insbesondere wenn Sie über mehrere Umgebungen verfügen). Müssen Sie wirklich eine erneute Bereitstellung durchführen, wenn Sie eine Konfigurationseinstellung für eine dieser N Bereitstellungen ändern?

Der bedauerliche Teil ist nun, dass bei IIS Umgebungsvariablen in der Konfigurationsdatei eingerichtet werden müssen, damit der App-Pool sie sehen kann. Ich glaube nicht, dass wir jemals beabsichtigt haben, dass Leute eine maschinenweite Konfiguration auf Zielmaschinen einrichten (obwohl ich das gesehen habe).

@willapp Warum verwendest du nicht appsettings.json ?

@willapp

M$ hat die perfekte Lösung, aber die meisten Leute bleiben beim Konzept der web.config-Transformation.

So können Sie mehrere Sites nebeneinander haben. Sie müssen nur Ihren Umgebungswert irgendwo außerhalb des IIS-Binärverzeichnisses werfen und ihn aus program.cs lesen/festlegen

  • IISRoot

    • MySiteDEV

    • Behälter



      • appsettings.json


      • appsettings.DEV.json


      • appsettings.PROD.json


      • web.config



    • Protokolle

    • env.DEV

    • MySitePROD

    • Behälter



      • appsettings.json


      • appsettings.DEV.json


      • appsettings.PROD.json


      • web.config



    • Protokolle

    • env.PROD

@davidfowl

Sagen Sie den Leuten, dass es bedauerlich ist, dass ASP.NET Core nicht gut mit IIS funktioniert? Als Microsoft .NET Core-Architekt?

Der Paradigmenwechsel bei allem Core ist hier Multi-Plattform. IIS ist eindeutig ein Windows-Dienstprogramm - und daher ist mit einigen Wachstumsschwierigkeiten zu rechnen. Problemumgehungen sollten in einem solchen Fall erwartet und im weiteren Verlauf akzeptiert werden. Absichtliche Designentscheidungen in Core zu treffen, um eine Windows-Funktion zu unterstützen, wäre imo nicht intuitiv gewesen.

Bearbeiten um hinzuzufügen:
Dies ist eine Überlegung, ob Core standardmäßig eine bessere Unterstützung für IIS bieten sollte. Die Diskussion über die Verwendung von Umgebungsvariablen ist eine gute Alternative, ungeachtet ...

@davidfowl

Und genau das ist der Unterschied zwischen Unternehmensarchitektur und KMU. Ich arbeite für einen FTSE100 und ja, es ist sinnvoll, Bereitstellung und Code zu trennen, aber ich betreibe auch mehrere Sites unabhängig voneinander und es ist einfach einfacher und kostengünstiger, einen einzigen Server zu haben, auf dem ich alle meine Sites hoste. Die Verwendung von Web Deploy + Transforms ist ein bewährter Mechanismus für Änderungen des Bereitstellungscodes, er funktioniert einfach. Ich sage nicht, dass es in einigen Fällen keine besseren Alternativen gibt, aber Microsoft hätte die Transformationen weiterhin unterstützen sollen, da die meisten Benutzer wissen, dass sie bei der Migration von .net-Framework auf Core vertraut sind.

Ich habe meine Lösung jetzt von früher in diesem Thread, also bin ich glücklich genug. Ich denke nur, dass sie den Ball ein wenig fallen gelassen haben, ohne dies als Standard einzubeziehen.

@willapp

Ich denke, transform basiert auf der Idee, aus dem Quellcode zu kompilieren und für jede Umgebung separat zu veröffentlichen. Ich bin froh, dass M$ es fallen gelassen hat, weil die Alternative so viel eleganter ist.

Mit dem neuen Setup veröffentlichen Sie Ihren Code nur einmal mit Release config. Alle laufenden Instanzen sind identische binäre Kopien des Originals. Die Bereitstellung sollte nur eine einfache Dateisynchronisierung mit der nächsten Umgebung sein DEV=>TEST=>Staging=>PROD.

Sagen Sie den Leuten, dass es bedauerlich ist, dass ASP.NET Core nicht gut mit IIS funktioniert? Als Microsoft .NET Core-Architekt?

Ich sage, dass die Leute nicht sofort daran denken, dass Umgebungsvariablen, die so verwendet werden, pro Prozess und nicht pro Maschine gelten sollen. Historisch gesehen identifizieren Benutzer unter Windows Umgebungsvariablen als maschinenweit und nicht als pro Prozess, und das hat zu Verwirrung geführt. IIS 10 hat Unterstützung für das Hinzufügen von Umgebungsvariablen pro App-Pool hinzugefügt. Das ASP.NET Core-Modul unterstützt auch das Festlegen von Umgebungsvariablen pro Prozess.

Dennoch war diese Fähigkeit vorhanden. Ich denke, hier hat hauptsächlich ein philosophischer Denkwandel stattgefunden. Wir möchten nichts tun, was es einfacher macht, Geheimnisse zur Entwicklungszeit anzugeben.

@challamzinniagroup gute Zusammenfassung

Dies ist eine Überlegung, ob Core standardmäßig eine bessere Unterstützung für IIS bieten sollte. Die Diskussion über die Verwendung von Umgebungsvariablen ist eine gute Alternative, ungeachtet ...

Richtig. Der Workflow zum Konfigurieren umgebungsspezifischer Informationen sollte sich weiterhin auf die spezifische Umgebung beziehen. Die Frage ist, wie kommt man dorthin. Ist es Teil der Bereitstellung?

Alles in allem glaube ich, dass wir dies in den Tools in 2.2 unterstützen.

cc: @vijayrkn

@davidfowl

Wenn Sie sagen "In der Vergangenheit identifizieren Benutzer unter Windows Umgebungsvariablen als maschinenweit und nicht als pro Prozess", meinen Sie Windows-Umgebungsvariablen, wie in der Befehlszeile SET?

Weil mein Verständnis von "Umgebung" im .NET-Kernkontext nur eine Variable ist. Standardmäßig liest es ASPNETCORE_ENVIRONMENT aus system oder web.config. Sie können es jedoch überschreiben und von jeder Quelle nach jeder Konvention abrufen.

Ist an diesem Ansatz grundsätzlich etwas falsch? Denn wenn die offizielle Position des Microsoft .NET-Teams lautet, tun Sie es nicht, wir müssten es ernsthaft überdenken. Aber Sie würden den Leuten am Ende sagen, dass sie .NET Core unter IIS ausführen sollen, aber leider keine einfache Möglichkeit, diese Apps zu konfigurieren. Hoffe das ist nicht der Fall.

Danke.

@ThisNoName

Wenn Sie sagen "In der Vergangenheit identifizieren Benutzer unter Windows Umgebungsvariablen als maschinenweit und nicht als pro Prozess", meinen Sie Windows-Umgebungsvariablen, wie in der Befehlszeile SET?

Ja, genau darum geht es in diesem Thread. (Siehe hier ). Wie David sagt, können dies pro Prozess sein, aber meiner Erfahrung nach gehen die meisten Dokumentationen zu Dotnet Core davon aus, dass Sie sie auf Maschinenebene festlegen. Daher haben wir dieses Problem, bei dem Sie nicht einfach mehrere App-Instanzen auf demselben Server bereitstellen können sie nehmen dieselben Umgebungswerte auf, sodass Sie nicht zwischen dev/staging/prod unterscheiden können.

Die Tatsache, dass IIS10 die Einstellung pro App-Pool unterstützt, ist großartig ... wenn Sie Server 2016 zur Verfügung haben. Ich laufe 2012, also ist dies keine Option. Auch hier ist mein Problem nicht, dass Microsoft versucht, die Dinge in eine bessere Richtung zu lenken, sondern es fühlt sich für mich wie ein Fehler an, die "Legacy" -Unterstützung für etwas einzustellen, das viele Leute bei der Bereitstellung von ASP.NET-Anwendungen für selbstverständlich hielten. Führen Sie auf jeden Fall neue Muster ein und ermutigen Sie die Leute, sie zu übernehmen, aber entfernen Sie das alte Verhalten nicht, bis Sie sicher sind, dass nur wenige Leute es brauchen. Andernfalls errichten Sie nur Barrieren für Kunden, die Dotnet-Core wollen, aber den Migrationspfad zu mühsam finden.

@willapp

Das ist nur die Standard-Out-of-the-Box-Einstellung. Sie können die Umgebung nach Belieben lesen und einstellen. Zumindest verstehe ich das so, es sei denn, jemand weist auf einen schwerwiegenden Fehler in diesem Ansatz hin?

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

        public static IWebHostBuilder CreateWebHostBuilder(string[] args)   {
               return WebHost.CreateDefaultBuilder(args)
                .UseEnvironment(ReadEnvFromWherever())
                .UseStartup<Startup>()
        }

        private string ReadEnvFromWherever() { 
              // Get and return whatever by your own convention
              return "DEV";
        }
    }

@ThisNoName

Der schwerwiegende Fehler besteht darin, wie Sie die Methode "ReadEnvFromWherever" dazu bringen, einen anderen Wert zurückzugeben, wenn Sie Web Publish von VSTS verwenden, basierend auf Ihrer Lösungskonfiguration? Ich nehme an, Sie könnten Präprozessordirektiven verwenden (#if RELEASE ...), aber das fühlt sich ziemlich schmutzig an.

In der "alten Welt" (ASP.NET Full Framework) erstellen Sie ein Veröffentlichungsprofil, und ein Teil davon ist die Auswahl einer zu erstellenden Lösungskonfiguration. Basierend auf dieser Konfiguration wurde dann eine Konfigurationstransformation angewendet, die es Ihnen ermöglichte, eine andere Konfiguration anzugeben, je nachdem, ob Sie in dev/staging/prod veröffentlichen.

Ich akzeptiere, dass dieser Workflow nicht in eine moderne CI-Pipeline passt, in der Sie ein einzelnes Build-Paket nehmen und es durch jede Umgebung pushen - in diesem Fall möchten Sie, dass so etwas wie die VSTS-Release-Pipeline Einstellungen zur Bereitstellungszeit einfügt, oder Sie primen Ihre Serverinstanz mit den richtigen Umgebungsvariablen. In diesem Fall legen Sie das Paket einfach auf die Box und es funktioniert automatisch. Aber auch hier denke ich, dass viele KMU und Ein-Mann-Bands nicht an diesem Ort sind und einen Bereitstellungsprozess von Visual Studio wünschen, der das gewünschte Ergebnis liefert.

Um nur hinzuzufügen, dass dies auch für die Bereitstellung kleiner Projekte auf Shared Hosting-Plattformen wichtig ist, die auf IIS laufen und traditionell ASP.NET-Hosting angeboten werden. Sie haben keine Möglichkeit, Umgebungsvariablen pro Website über ihre Hosting-Control-Panels festzulegen, und daher besteht der einzig realistische Ansatz darin, Transformationen und web.config .

Es hört sich so an, als ob dies alles in der nächsten Version eine anständige Lösung haben wird, und mit eingebauter VS-Unterstützung, die ein wenig später folgt. Hoffentlich wird dies Menschen mit bestehenden Workflows unterstützen, die auf diese Funktionalität angewiesen sind, bis Hosting-Provider und Legacy-Systeme aktualisiert oder verbessert werden können.

@willapp

Vereinbarungs. Wenn Sie nach dem zuvor geposteten Beispiel gehen, können Sie env.DEV aus dem übergeordneten Ordner lesen und die Dateierweiterung als Umgebungsvariable verwenden. Sie können jedoch jede Konvention anwenden, z. B. Ihr App-Stammverzeichnis als MySiteDEV, MySitePROD usw. benennen und den Ordnernamen analysieren, um den Umgebungsnamen zu erhalten.

Wenn Ihr Code je nach Umgebung variiert, können Sie den Umgebungswert aus IHostingEnvironment .EnvironmentName . lesen

Dies ist kein Unterschied zum Lesen von ASPNETCORE_ENVIRONMENT von .NET Core aus der Systemvariablen oder web.config.

@ThisNoName

Aber wie bekommt man _env.DEV_ in den übergeordneten Ordner, außer es manuell hochzukopieren? Ich verstehe, was Sie sagen wollen, aber ich glaube, Sie übersehen hier den Punkt: Früher gab es eine Out-of-the-Box-Lösung, die einfach funktionierte. Das ist jetzt nicht der Fall, da die Tooling-Unterstützung dafür nicht als Teil des Dotnet-Core-Bereitstellungsprozesses berücksichtigt wurde.

Ich verstehe, _warum_ es entfernt wurde (weil es bessere Alternativen gibt, wenn Sie einen anständigen CI-Prozess haben), aber ich denke, es war ziemlich kurzsichtig, wenn viele migrierende Benutzer es immer noch wollen würden.

@willapp

Sie kopieren es einmal während der Ersteinrichtung und alle zukünftigen Bereitstellungen gehen in den bin-Ordner. Kein Neukompilieren, kein Veröffentlichen, keine Transformation. So sollte es sein, benötigt 3 zusätzliche Codezeilen, na und? Es ist M$. Bis vor 3 Monaten konnten Sie Active Directory in .NET Core nicht einmal aufrufen.

@ThisNoName Erwartest du, mit diesem M$ ? Sie wissen, dass es 2018 ist, oder?

Ihr Vorschlag macht im Kontext einer Webbereitstellung auf einer Shared Hosting-Plattform keinen Sinn. Ich bin mir nicht einmal sicher, wofür oder gegen was Sie argumentieren, die Funktionalität wird der nächsten Version von ASP.NET Core hinzugefügt, sodass eine Umgebungsvariable im Veröffentlichungsprofil angegeben werden kann, ohne dass Transformationen oder ähnliches erforderlich sind. Es sind auch keine nicht standardmäßigen Ansätze mit Ordnernamen erforderlich, die möglicherweise unter Ihrer Kontrolle stehen.

@willapp , @svallis
Die Lösung, die ich etwas weiter oben gepostet habe, funktioniert in einigen Fällen. Sie können die URL abrufen und die Umgebung basierend darauf festlegen. In jeder Hosting-Umgebung haben Sie die volle Kontrolle über Ihre URLs. Mir ist klar, dass dies immer noch "hackisch" ist und ein Workaround ist - aber es sollte im Allgemeinen die meiste Zeit funktionieren. Im Fall meines Hosting-Unternehmens war die URL, die ich erhielt, eine localhost:port- Basis ("127.0.0.1:7777") - daher stellte sich heraus, dass sie für mich nicht ideal war. Aber ich habe auch die Möglichkeit, Root-Ordnerpfade in meinen verschiedenen Umgebungen festzulegen, da ich sie als Unterdomänen eingerichtet habe - und das Ziehen des Root-App-Pfads ist auch ziemlich einfach:

        public static string DetectAndSet(this IHostingEnvironment env, ILogger logger)
        {
            switch (env.ContentRootPath)
            {
                case "h:\\root\\home\\www\\api":
                    env.EnvironmentName = EnvironmentName.Production;
                    break;
                case "h:\\root\\home\\www\\api-staging":
                    env.EnvironmentName = EnvironmentName.Staging;
                    break;
                default:
                    env.EnvironmentName = EnvironmentName.Development;
                    break;
            }

            logger.LogInformation($"Application root path discovered as '{env.ContentRootPath}'. Environment set to '{env.EnvironmentName}'");

            return env.EnvironmentName;
        }

Die Entscheidung, ob die Umgebung innerhalb des Codes, zur Bereitstellungszeit oder im Voraus direkt in der Umgebung festgelegt werden soll oder nicht, ist nicht die Diskussion, die ich angehen möchte - ich biete einfach eine vernünftige Lösung für diese KMU/ Personen, die nur über eingeschränkte Hosting-Kontrolle verfügen und eine Lösung benötigen. In meinem Fall ist dies ein Code-once-and-forget - genau das, was ich brauche.

Weiter stromabwärts kann ich leicht Konfigurationswerte aus einer appsettings.json Datei ziehen, ohne dass Transformationen erforderlich sind, indem ich einfach Folgendes einbeziehe:

"{configName}.{environmentName}": "{value}"

in der Einstellungsdatei und mit 3 Einträgen pro Konfiguration - einen für jede Umgebung. Ich habe nur eine sehr kleine Anzahl von Konfigurationen in dieser Datei und daher ist die Duplizierung keine große Sache.

Hoffe das hilft!

@challamzinniagroup Es ist einfacher, den relativen

@svallis Das gesamte Konzept besteht darin, einmal zu veröffentlichen und auf

@ThisNoName Für dich ist es vielleicht einfacher - aber

@challamzinniagroup Zustimmen . Jede Situation ist anders. Unterm Strich ist die Umgebung nur eine Variable. Sie können sie so steuern, wie Sie es für richtig halten, anstatt darauf zu warten, dass Microsoft das nächstbeste liefert. Und was auch immer sie auftauchen, ist sowieso nur eine weitere konventionsbasierte Lösung – das Lesen eines Wertes aus dem System oder der web.config und der Set-Umgebung.

Übrigens, Sie können immer noch Konventionen verwenden. Es ist nicht zu sagen, dass Appsettings ein einzelnes mittleres Wort verwenden müssen und Staging/Production keine besondere Bedeutung hat. Sie können so etwas ganz einfach tun und den passenden Ordnernamen übergeben.

appsettings.api.json
appsettings.api-staging.json

Mit einer konventionsbasierten Lösung können Sie neue Instanzen einrichten, ohne neu kompilieren und/oder neu veröffentlichen zu müssen.

@vijayrkn könnten Sie bitte näher auf die Verwendung von pubxml eingehen?
Ich habe mein SDK auf 2.1.302 (x64) aktualisiert, meine pubxml geändert, kann aber keinen Unterschied in der veröffentlichten web.config feststellen.

@wggley - Der Fix ist in 2.1.302 nicht verfügbar. Es sollte in der nächsten kommenden Version verfügbar sein.

Sie können die Vorschauversion der cli mit dem Fix von hier ausprobieren - https://dotnetcli.blob.core.windows.net/dotnet/Sdk/release/2.1.4xx/dotnet-sdk-latest-win-x64.exe

Lassen Sie es mich wissen, wenn Probleme mit der obigen Vorschauversion auftreten.

Danke @vijayrkn Ich warte auf die nächste bevorstehende Veröffentlichung und versuche, sie bei einer neuen Veröffentlichung zu verwenden.
Ich möchte darauf hinweisen, dass die @frankhoffy- Lösung für mich wie ein Zauber funktioniert hat:
https://stackoverflow.com/questions/31049152/publish-to-iis-setting-environment-variable/36836533#36836533
Suchen Sie nach der ersten Antwort (Antwort mit den meisten Stimmen).

Die Unterstützung der Webkonfigurationstransformation während der Veröffentlichung ist jetzt in der Vorschauversion 2.2 verfügbar1 https://www.microsoft.com/net/download/dotnet-core/2.2

@vijayrkn gibt es irgendwo ein grundlegendes Beispiel? Es wäre großartig, die Leute mit einer grundlegenden Transformation, die ASPNETCORE_ENVIRONMENT festlegt, auf das Hallo-Welt-Äquivalent zu verweisen.

Um ASPNETCORE_ENVIRONMENT festzulegen, können Benutzer die msbuild-Eigenschaft '$(EnvironmentName)' festlegen. Ich werde ein Beispiel hinzufügen, das zeigt, wie andere Umgebungsvariablen mithilfe von web.config-Transformationen festgelegt werden.

Hier ist ein Beispiel-Repository - https://github.com/vijayrkn/webconfigtransform

Readme enthält Details zur Funktionsweise:
https://github.com/vijayrkn/webconfigtransform/blob/master/README.md

Hoffe das hilft!

@Eilon - Wir können dieses Problem schließen. Dies ist behoben und in der neuesten Vorschau verfügbar.

@vijayrkn Es ist nicht klar, wie die Veröffentlichungseinstellungen konfiguriert werden sollen, um die Umgebung im Dialogfeld Veröffentlichungseinstellungen festzulegen? Was kann in diesem Dialogfeld tatsächlich geändert werden, um eine Staging-Site von einer Produktions-Site zu unterscheiden, wenn beide Sites auf demselben Server bereitgestellt werden?

Dieser Aspekt von .NET Core scheint sehr chaotisch zu sein. Es muss viel einfacher gemacht werden, die Umgebung pro Ordner anzugeben. Eine Umgebungsvariable für den gesamten Server kann für unsere Situation überhaupt nicht funktionieren. Nicht jeder kann seine Staging-Sites auf anderen Servern als seine Produktionsstandorte ausführen.

Die Einstellung erfolgt pro Anwendung.

Sorry, aber das beantwortet meine Frage nicht wirklich. Vielleicht verstehe ich etwas falsch.

Hier gibt es eine Pseudodokumentation https://github.com/vijayrkn/webconfigtransform/blob/master/README.md ( @vijayrkn wir müssen dies in die echten Dokumente bringen).

@vijayrkn Wie viel Unterstützung gibt es dafür im Veröffentlichungsdialog?

Derzeit bietet der Veröffentlichungsdialog keine Unterstützung für das Festlegen der Veröffentlichungsumgebungen, aber die Umgebungen können manuell im Veröffentlichungsprofil festgelegt oder bestimmte Transformationen angewendet werden.

@nmg196 - Wenn Sie nur 'ASPNETCORE_ENVIRONMENT' in der web.config festlegen möchten, müssen Sie nur den Umgebungsnamen zum Veröffentlichungsprofil hinzufügen.

Beispiel:
https://github.com/vijayrkn/webconfigtransform/blob/master/Properties/PublishProfiles/FolderProfile.pubxml#L18

Für erweiterte Szenarien (außer dem Festlegen der Umgebungsvariablen ASPNETCORE_ENVIRONMENT) können web.config-Transformationen wie in der obigen Dokumentation beschrieben angewendet werden.

@davidfowl - Angelos hat ein Element, um die Unterstützung der web.config-Transformation zu dokumentieren.

@vijayrkn Wie verwende

Sie können diese msbuild-Eigenschaft an dotnet publish übergeben.

Sie können auf dieses Beispiel hier verweisen - https://github.com/vijayrkn/webconfigtransform/blob/master/publish.cmd

Dies übergibt die CustomTransformFileName-Eigenschaft an dotnet publish

dotnet publish /p:Configuration=Release /p:EnvironmentName=Staging /p:CustomTransformFileName=custom.transform

@vijayrkn
Ich habe Ihre Dokumentation gelesen und kann die web.config nicht transformieren. Ich habe im Grunde alle Befehle ausprobiert, die Sie in der readme.md haben, und keiner von ihnen führt dazu, dass die Transformation durchgeführt wird.

Ich konnte jedoch ein Powershell-Skript schreiben, das Microsoft.Web.XmlTransform.dll verwendet, um die Transformation getrennt vom Veröffentlichungsvorgang durchzuführen.

Meine Frage ist, welche Version von msbuild und dotnet verwenden Sie?
Ich benutze:
dotnet --version 2.1.104
dotnet msbuild -version 15.6.84.34536

Danke

@stephenarsenault1
Sie müssen einen der Builds von hier installieren, damit die Funktion aufleuchtet - https://www.microsoft.com/net/download/dotnet-core/2.2

Neueste - https://www.microsoft.com/net/download/thank-you/dotnet-sdk-2.2.100-preview3-windows-x64-installer

@davidfowl schrieb:

Hier gibt es eine Pseudodokumentation https://github.com/vijayrkn/webconfigtransform/blob/master/README.md ( @vijayrkn wir müssen dies in die echten Dokumente bringen).

@vijayrkn Wie viel Unterstützung gibt es dafür im Veröffentlichungsdialog?

Wissen Sie, ob dies jemals zu den echten Dokumenten hinzugefügt wurde, wenn ja, haben Sie bitte den Link?

Wir sind jetzt dazu übergegangen, <EnvironmentName> in unseren Veröffentlichungsprofilen zu verwenden. Es wäre jedoch schön, darüber eine Benutzeroberfläche zu haben, damit sie besser sichtbar ist. Ich vermute, das kommt zu einem späteren Zeitpunkt?

Ich denke, es ist eine bahnbrechende Änderung, web.config-Transformationen standardmäßig bei Dotnet-Publishing zu aktivieren. Nach der Installation von .NET Core SDK 2.2.101 hat es unser CI/CD-Szenario durchbrochen. Unsere Pipeline ist so konfiguriert, dass sie veröffentlichte Artefakte mit dotnet publish nur einmal für jede Version erstellt ( Build-Once-Regel ), die Transformation wird automatisch auf die reale Bereitstellung angewendet (durchgeführt von Octopus). Ich konnte keine Erwähnung in der Dokumentation zu dieser Änderung finden. Verbrachte einige Zeit damit, herauszufinden, was der Grund für die doppelten Konfigurationsblöcke in web.config nach der Bereitstellung ist. Anscheinend wurde die Transformation zweimal durchgeführt: von dotnet publish und vom Release-Management-Tool.

Nach dem Deaktivieren der web.config-Transformationen mit der Einstellung <IsTransformWebConfigDisabled>true</IsTransformWebConfigDisabled> wurde auch TransformWebConfig (zusammen mit TransformXml) übersprungen, was dazu führt, dass die Variablen %LAUNCHER_PATH% und %LAUNCHER_ARGS% während des Veröffentlichungsprozesses nicht ersetzt werden. Gibt es eine Einstellung, um diese Schritte unabhängig zu steuern?

Funktioniert dies in einer Konsolen-App mit der Datei App.Config?

Können wir ein Beispiel sehen?

@dmitryshunkov Sie können $(RunXdt) auf false setzen, um die Ausführung der benutzerdefinierten XML-Transformation einfach zu überspringen.

@auserx - Wenn es sich um ein Projekt im SDK-Stil handelt, sollte es funktionieren.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen