在开发Blazor应用时,经常需要根据不同的环境(开发、测试、Beta、生产)来设置不同的配置。理想的情况是,有一个构建产物,它可以在不同的环境中无缝迁移,而不需要任何更改。如果将Blazor应用作为静态文件托管,那么就需要为每个不同的环境更改应用设置文件。为了避免这种情况,选择了ASP.NET Core Web Hosted的方式来部署Blazor应用。
在解决方案中,有以下三个项目:
为了加载客户端应用设置,将通过内置的配置在AppSettingsExample.Server中存储和访问这些设置。为此,将添加一个包含以下值的appsettings.json文件:
{
"ClientAppSettings": {
"BaseApiUrl": "http://somesite.com/api"
}
}
接着,将在AppSettingExample.Shared项目中创建一个类来保存这些配置:
public class ClientAppSettings
{
public string BaseApiUrl { get; set; }
}
在AppSettingsExample.Server的Startup类中,将获取应用程序的配置引用,并将其存储在局部变量中:
private readonly IConfiguration _configuration;
public Startup(IConfiguration configuration)
{
_configuration = configuration;
}
这允许使用该配置从appsettings.json加载设置,并将其作为单例添加到依赖注入配置中。
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton(_configuration.GetSection("ClientAppSettings").Get
由于没有简单的方法直接将设置传递给客户端Blazor应用,因此需要客户端从服务器请求这些设置。将在AppSettingsExample.Server中创建一个ClientAppSettingsController来提供这些设置。
[Route("api/[controller]")]
[ApiController]
public class ClientAppSettingsController : ControllerBase
{
private readonly ClientAppSettings _clientAppSettings;
public ClientAppSettingsController(ClientAppSettings clientAppSettings)
{
_clientAppSettings = clientAppSettings;
}
[HttpGet]
public ClientAppSettings GetClientAppSettings()
{
return _clientAppSettings;
}
}
接下来是获取客户端设置的部分,这也是遇到最多困难的地方。需要在应用程序继续之前完全加载这些设置。如果异步加载,它会在设置加载完成之前开始运行当前页面的初始化和参数设置方法。如果尝试通过调用.Wait()强制异步Web请求同步完成,应用程序会锁定。
为了解决这个问题,可以创建一个组件来加载设置,一旦加载完成就显示其子内容。然后可以将内容包装在这个组件中,以确保它不会在设置加载完成之前开始初始化或设置参数。首先,创建AppSettingsLoader.razor:
@using AppSettingExample.Shared
@inject HttpClient http
@if (IsLoaded)
{
@ChildContent
}
@code {
[Parameter]
public RenderFragment ChildContent { get; set; }
public bool IsLoaded { get; set; }
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
if (!IsLoaded)
{
var appSettings = await http.GetJsonAsync
因为不能(或者不能)将ClientAppSettings实例加载到依赖注入中,使其在整个应用程序中可用,只是将值放在一个静态类中。
现在,在MainLayout.razor中,可以将@body用AppSettingsLoader包装起来: