Blazor WASM/PWA - Configurazione AppSettings per più clienti
Obiettivo
Gestire pubblicazioni diverse della stessa app Blazor WebAssembly/PWA per più clienti, evitando di modificare manualmente appsettings.json dopo la pubblicazione.
Nelle app Blazor WASM/PWA i file pubblicati vengono gestiti anche dal service worker e dal manifest degli asset:
service-worker-assets.js
Se si modifica manualmente un file statico dopo la pubblicazione, ad esempio appsettings.json, si possono creare problemi di cache, integrità o caricamento della PWA.
La soluzione corretta è:
1. mantenere un appsettings.json comune
2. creare un file appsettings per ogni cliente
3. tenere i file cliente fuori da wwwroot
4. usare un profilo di pubblicazione per cliente
5. fare copiare al .csproj solo il file del cliente pubblicato
1. Struttura cartelle consigliata
Nel progetto Blazor WASM, ad esempio Soluziona.Apps.Magazzino, usare questa struttura:
Soluziona.Apps.Magazzino
├── SettingClienti
│ ├── Comside
│ │ └── appsettings.Comside.json
│ └── Demo
│ └── appsettings.Demo.json
│
├── Properties
│ └── PublishProfiles
│ ├── Comside.pubxml
│ └── Demo.pubxml
│
└── wwwroot
├── appsettings.json
├── appsettings.Development.json
├── index.html
├── manifest.webmanifest
├── service-worker.js
└── ...
Regola
Dentro wwwroot devono rimanere solo:
appsettings.json
appsettings.Development.json
I file dei clienti devono stare fuori da wwwroot, dentro:
SettingClienti\<NomeCliente>\appsettings.<NomeCliente>.json
Esempio:
SettingClienti\Comside\appsettings.Comside.json
SettingClienti\Demo\appsettings.Demo.json
Non mettere dentro wwwroot:
appsettings.Comside.json
appsettings.Demo.json
altrimenti rischiano di essere pubblicati tutti insieme.
2. appsettings.json comune
Il file:
wwwroot\appsettings.json
deve contenere solo i valori comuni a tutti i clienti.
Esempio:
{
"App": {
"NomeApp": "Liste di Carico",
"SottoTitoloApp": "Gestione preparazione ordini",
"Versione": "1.0.6",
"Build": "2026.09.09.006",
"Ambiente": "Production",
"PaginaIniziale": "/calendario"
},
"Api": {
"TimeoutSecondi": 30
},
"Offline": {},
"SyncListeDiCarico": {
"IntervalloSecondi": 30,
"GiorniIndietro": 15,
"GiorniAvanti": 15,
"EseguiAllAvvio": true
}
}
Nota
In questo file può mancare:
"BaseUrl"
perché viene valorizzato dal file cliente, ad esempio:
appsettings.Comside.json
A runtime Blazor caricherà:
appsettings.json
+
appsettings.Comside.json
3. appsettings.Development.json
Il file:
wwwroot\appsettings.Development.json
viene usato per lo sviluppo locale.
Esempio:
{
"App": {
"IdApplicazione": "17630f17-7626-416f-961b-486fbd64fd4f",
"CodiceApplicazione": "APPLISTEDICARICO",
"CodiceAzienda": "3",
"Ambiente": "Development"
},
"Api": {
"BaseUrl": "https://localhost:7021/",
"TimeoutSecondi": 30
}
}
Questo file non deve essere pubblicato in produzione.
4. AppSettings per cliente
Demo
Percorso:
SettingClienti\Demo\appsettings.Demo.json
Contenuto:
{
"App": {
"IdApplicazione": "17630f17-7626-416f-961b-486fbd64fd4f",
"CodiceApplicazione": "APPLISTEDICARICO",
"CodiceAzienda": "3",
"Ambiente": "Production"
},
"Api": {
"BaseUrl": "https://soluzionacoreapi.soluziona.cloud:443/",
"TimeoutSecondi": 30
}
}
Comside
Percorso:
SettingClienti\Comside\appsettings.Comside.json
Contenuto:
{
"App": {
"IdApplicazione": "90208117-20b4-446c-a771-42bce3fb63c5",
"CodiceApplicazione": "ListeDiCarico",
"CodiceAzienda": "59",
"Ambiente": "Production"
},
"Api": {
"BaseUrl": "https://192.168.232.122:4433/",
"TimeoutSecondi": 30
}
}
5. Modifica del .csproj
Aprire il file .csproj del progetto Blazor WASM, ad esempio:
Soluziona.Apps.Magazzino.csproj
5.1
La configurazione deve:
1. escludere SettingClienti dagli item automatici del SDK
2. escludere eventuali appsettings ambiente da wwwroot
3. copiare il file cliente corretto dentro wwwroot prima della build/publish
4. includere esplicitamente il file copiato come Content
5.1 Esclusione file cliente e appsettings ambiente
Nel primo PropertyGroup aggiungere:
<DefaultItemExcludes>$(DefaultItemExcludes);SettingClienti\**\*;wwwroot\appsettings.*.json</DefaultItemExcludes>
Esempio:
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<OverrideHtmlAssetPlaceholders>true</OverrideHtmlAssetPlaceholders>
<ServiceWorkerAssetsManifest>service-worker-assets.js</ServiceWorkerAssetsManifest>
<!-- Esclude i file cliente dagli item automatici del .NET SDK -->
<DefaultItemExcludes>$(DefaultItemExcludes);SettingClienti\**\*;wwwroot\appsettings.*.json</DefaultItemExcludes>
</PropertyGroup>
Questa riga impedisce al SDK Blazor di trattare automaticamente i file cliente come asset statici.
5.2 Non usare Content Include diretto
Non usare questa forma:esclude:
<ContentSettingClienti\...
Include="SettingClienti\Comside\wwwroot\appsettings.Demo.json
wwwroot\appsettings.Comside.json"json
/>wwwroot\appsettings.Development.json
perché può generare errori del tipo:
More than one compatible asset found for target path 'appsettings.Comside#[.{fingerprint}]?.json'