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.
Questo è importante perché nelle app Blazor WASM/PWA i file pubblicati vengono inseriti nel manifest degli asset, ad esempio:
service-worker-assets.js
Se si modifica un file statico dopo la pubblicazione, come appsettings.json, gli hash possono non corrispondere più e la PWA può generare errori di integrità/cache.
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
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
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
}
}
4. Settings 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
Aggiungere questo blocco prima di:
</Project>
<ItemGroup>
<None Include="SettingClienti\**\*.json" />
</ItemGroup>
<ItemGroup Condition="'$(WasmApplicationEnvironmentName)' != ''
and '$(WasmApplicationEnvironmentName)' != 'Development'
and Exists('SettingClienti\$(WasmApplicationEnvironmentName)\appsettings.$(WasmApplicationEnvironmentName).json')">
<Content Include="SettingClienti\$(WasmApplicationEnvironmentName)\appsettings.$(WasmApplicationEnvironmentName).json"
Link="wwwroot\appsettings.$(WasmApplicationEnvironmentName).json"
CopyToOutputDirectory="PreserveNewest"
CopyToPublishDirectory="PreserveNewest" />
</ItemGroup>
Cosa fa questo blocco
Quando si pubblica con ambiente:
Comside
il .csproj prende:
SettingClienti\Comside\appsettings.Comside.json
e lo pubblica come:
wwwroot\appsettings.Comside.json
Quando si pubblica con ambiente:
Demo
il .csproj prende:
SettingClienti\Demo\appsettings.Demo.json
e lo pubblica come:
wwwroot\appsettings.Demo.json
6. Profili di pubblicazione
I profili vanno creati da Visual Studio con:
Tasto destro sul progetto
→ Publish
→ New profile
→ Folder
Dopo la creazione, modificare i file .pubxml.
Profilo Demo
Percorso:
Properties\PublishProfiles\Demo.pubxml
Contenuto:
<?xml version="1.0" encoding="utf-8"?>
<Project>
<PropertyGroup>
<DeleteExistingFiles>true</DeleteExistingFiles>
<ExcludeApp_Data>false</ExcludeApp_Data>
<LaunchSiteAfterPublish>true</LaunchSiteAfterPublish>
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<PublishProvider>FileSystem</PublishProvider>
<PublishUrl>C:\Repos\Pubblicati\AppListeDiCarico\Demo</PublishUrl>
<WebPublishMethod>FileSystem</WebPublishMethod>
<_TargetId>Folder</_TargetId>
<WasmApplicationEnvironmentName>Demo</WasmApplicationEnvironmentName>
</PropertyGroup>
</Project>
Profilo Comside
Percorso:
Properties\PublishProfiles\Comside.pubxml
Contenuto:
<?xml version="1.0" encoding="utf-8"?>
<Project>
<PropertyGroup>
<DeleteExistingFiles>true</DeleteExistingFiles>
<ExcludeApp_Data>false</ExcludeApp_Data>
<LaunchSiteAfterPublish>true</LaunchSiteAfterPublish>
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<PublishProvider>FileSystem</PublishProvider>
<PublishUrl>C:\Repos\Pubblicati\AppListeDiCarico\Comside</PublishUrl>
<WebPublishMethod>FileSystem</WebPublishMethod>
<_TargetId>Folder</_TargetId>
<WasmApplicationEnvironmentName>Comside</WasmApplicationEnvironmentName>
</PropertyGroup>
</Project>
7. Proprietà fondamentale: WasmApplicationEnvironmentName
La riga più importante del profilo è questa:
<WasmApplicationEnvironmentName>Comside</WasmApplicationEnvironmentName>
oppure:
<WasmApplicationEnvironmentName>Demo</WasmApplicationEnvironmentName>
Questa proprietà decide quale file ambiente Blazor deve caricare.
Esempio:
WasmApplicationEnvironmentName = Comside
→ carica appsettings.json
→ carica appsettings.Comside.json
WasmApplicationEnvironmentName = Demo
→ carica appsettings.json
→ carica appsettings.Demo.json
Il valore deve combaciare esattamente con:
nome cartella cliente
nome file appsettings
Esempio corretto:
Comside
→ SettingClienti\Comside\appsettings.Comside.json
Esempio errato:
COMSIDE
→ SettingClienti\Comside\appsettings.Comside.json