Personalizzare le stringhe di connessione usando manifesti .NET Aspire

Completato

Gli strumenti di distribuzione come Visual Studio o Azure Developer CLI creano file manifesto che descrivono il contenuto di una soluzione .NET Aspire. Se si vuole personalizzare la distribuzione, è possibile apportare modifiche direttamente al file manifesto.

Nel rivenditore di attrezzature all'aperto si è deciso di usare un'istanza di Cache di Azure per Redis esistente per ospitare la cache di output per il microservizio dell'app Web. Si vuole assicurarsi che il servizio app Web si connetta all'istanza corretta di Cache di Azure per Redis.

In questa unità si apprenderà come modificare le stringhe di connessione ai servizi di backup nel file manifesto .NET Aspire.

Generare un file manifesto usando l'interfaccia della riga di comando di .NET

Durante lo sviluppo e il debug locali, .NET Aspire non crea un file manifesto. Quando arriva il momento della distribuzione, .NET deve descrivere il contenuto della soluzione .NET Aspire, inclusi i relativi microservizi, i servizi di backup e la configurazione. Il file manifesto serve a questo scopo. Descrive la soluzione in formato JSON.

Per creare il file manifesto, sia Visual Studio che Azure Developer CLI eseguono un comando dell'interfaccia della riga di comando di .NET run con una destinazione specifica. È possibile eseguire manualmente lo stesso comando per creare un file manifesto personalizzato come il seguente:

dotnet run --project eShop.AppHost\eShop.AppHost.csproj `
    --publisher manifest `
    --output-path ../aspire-manifest.json

Nota

Assicurarsi di specificare il progetto host dell'app con l'opzione --project.

Il comando genera un output simile a questo testo:

Building...
info: Aspire.Hosting.DistributedApplication[0]
      Aspire version: 8.0.1+a6e341ebbf956bbcec0dda304109815fcbae70c9
info: Aspire.Hosting.Publishing.ManifestPublisher[0]
      Published manifest to: C:\repos\eShop\aspire-manifest.json

È anche possibile usare un profilo di avvio per eseguire il comando dotnet. Un profilo di avvio è un gruppo di impostazioni che configura un progetto .NET durante l'esecuzione. Ad esempio, il modello .NET Aspire Starter crea questi profili di avvio:

"profiles": {
  "https": {
    "commandName": "Project",
    "dotnetRunMessages": true,
    "launchBrowser": true,
    "applicationUrl": "https://localhost:17170;http://localhost:15281",
    "environmentVariables": {
      "ASPNETCORE_ENVIRONMENT": "Development",
      "DOTNET_ENVIRONMENT": "Development",
      "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21147",
      "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22239"
    }
  },
  "http": {
    "commandName": "Project",
    "dotnetRunMessages": true,
    "launchBrowser": true,
    "applicationUrl": "http://localhost:15281",
    "environmentVariables": {
      "ASPNETCORE_ENVIRONMENT": "Development",
      "DOTNET_ENVIRONMENT": "Development",
      "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19197",
      "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20233"
    }
  }
}

Aggiungere un profilo di avvio per creare un file manifesto con codice JSON simile al testo seguente:

"profiles": {
  "generate-manifest": {
    "commandName": "Project",
    "launchBrowser": false,
    "dotnetRunMessages": true,
    "commandLineArgs": "--publisher manifest --output-path aspire-manifest.json"
  }
}

In Visual Studio è quindi possibile scegliere il profilo generate-manifest all'avvio del debug. Usare l'opzione --launch-profile dalla riga di comando:

dotnet run --launch-profile generate-manifest

Formato del file manifesto

Il manifesto è un file JSON con un singolo elemento di primo livello denominato resources. All'interno di tale oggetto si trova un oggetto per ogni microservizio e servizio di backup. Per ognuno di questi oggetti, le impostazioni includono stringhe di connessione, variabili di ambiente e nomi di immagini del contenitore.

Di seguito è riportato un esempio di manifesto per il modello .NET Aspire Starter senza modifiche. La soluzione usa una cache Redis:

{
  "resources": {
    "cache": {
      "type": "container.v0",
      "connectionString": "{cache.bindings.tcp.host}:{cache.bindings.tcp.port}",
      "image": "docker.io/library/redis:7.2",
      "bindings": {
        "tcp": {
          "scheme": "tcp",
          "protocol": "tcp",
          "transport": "tcp",
          "targetPort": 6379
        }
      }
    },
    "apiservice": {
      "type": "project.v0",
      "path": "AspireStarter.ApiService/AspireStarter.ApiService.csproj",
      "env": {
        "OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES": "true",
        "OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES": "true",
        "OTEL_DOTNET_EXPERIMENTAL_OTLP_RETRY": "in_memory",
        "ASPNETCORE_FORWARDEDHEADERS_ENABLED": "true"
      },
      "bindings": {
        "http": {
          "scheme": "http",
          "protocol": "tcp",
          "transport": "http"
        },
        "https": {
          "scheme": "https",
          "protocol": "tcp",
          "transport": "http"
        }
      }
    },
    "webfrontend": {
      "type": "project.v0",
      "path": "AspireStarter.Web/AspireStarter.Web.csproj",
      "env": {
        "OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES": "true",
        "OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES": "true",
        "OTEL_DOTNET_EXPERIMENTAL_OTLP_RETRY": "in_memory",
        "ASPNETCORE_FORWARDEDHEADERS_ENABLED": "true",
        "ConnectionStrings__cache": "{cache.connectionString}",
        "services__apiservice__http__0": "{apiservice.bindings.http.url}",
        "services__apiservice__https__0": "{apiservice.bindings.https.url}"
      },
      "bindings": {
        "http": {
          "scheme": "http",
          "protocol": "tcp",
          "transport": "http",
          "external": true
        },
        "https": {
          "scheme": "https",
          "protocol": "tcp",
          "transport": "http",
          "external": true
        }
      }
    }
  }
}

Stringhe di connessione e riferimenti di associazione

L'esempio di manifesto include tre risorse:

  • webfrontend: questa risorsa è il microservizio che presenta un'interfaccia Web ai clienti.
  • apiservice: questa risorsa è l'API REST chiamata da webfrontend. Nel modello, questa chiamata consente di ottenere dati meteo.
  • cache: questa risorsa è la cache Redis, usata per ottimizzare le prestazioni del microservizio webfrontend.

Si noti che ognuna delle tre risorse include una sezione bindings che specifica i protocolli che è possibile usare per connettersi a tale risorsa.

Nel fileProgram.cs dell'host dell'app il progetto webfrontend dipende sia dalla cache che da apiservice:

var cache = builder.AddRedis("cache");

var apiService = builder.AddProject<Projects.AspireStarter_ApiService>("apiservice");

builder.AddProject<Projects.AspireStarter_Web>("webfrontend")
    .WithExternalHttpEndpoints()
    .WithReference(cache)
    .WithReference(apiService);

Nel file manifesto queste dipendenze vengono espresse come variabili di ambiente:

"env": {
  "ConnectionStrings__cache": "{cache.connectionString}",
  "services__apiservice__http__0": "{apiservice.bindings.http.url}",
  "services__apiservice__https__0": "{apiservice.bindings.https.url}"
}

Diagramma che mostra il modo in cui le dipendenze in un progetto .NET Aspire generano riferimenti in un file manifesto.

Le dipendenze usano stringhe segnaposto che fanno riferimento alla struttura del file manifesto. Ad esempio, la terza dipendenza fa riferimento all'associazione HTTPS del servizio API:

Diagramma che mostra come vengono costruiti i segnaposto in un file manifesto .NET Aspire.

Altre informazioni