注意
客户端上的用户可以看到配置和设置文件,用户可以篡改数据。 请勿在应用的配置或文件中存储应用机密、凭据或任何其他敏感数据。
使用交互式 WebAssembly 或交互式自动渲染模式时,请记住所有组件代码都会编译并发送到客户端,用户可以在客户端对其进行反向编译和检查。 请勿在客户端渲染的组件中放置专用代码、应用机密或其他敏感信息。
应用参数配置
一、文件配置源
1、项目默认配置文件
这里以Blazor web app Auto/Per page项目为例子,创建项目后,可以看到解决方案中会出现两个项目,一个是服务端,一个是客户端(.Client)。这两个项目中,都存在默认项目配置文件appsettings.json
和appsettings.Development.json
。
配置文件的加载规则
既然存在两个默认配置文件,那么当应用运行时,具体是用哪一个配置文件中的数据呢?
首相,在生产环境下,也就是进行了发布、托管部署后,是直接使用各自项目中的appsettings.json
文件的。
如果是在调试环境下(VS中),appsettings.json
是必定加载的,至于appsettings.Development.json
加载还是不加载,要看一下launchSettings.json
文件中,运行服务的配置。如果选择的运行服务环境配置为Development
那么会把appsettings.Development.json
也加载进来,反之则不加载。
默认情况下,在本地运行应用时,环境默认为 Development
。 发布应用时,环境默认为 Production
。
加载配置文件后,就可以直接使用IConfiguration
服务来直接获取。
如果两个配置文件都加载了,则会先到appsettings.Development.json
中寻找对应参数,如果没有,再到appsettings.json
中查找。
作用区域
如果是在服务端的项目配置文件中配置了参数,那么当组件进行预渲染或服务端交互渲染时,可以读取到,当组件客户端交互渲染时则无法读取。
如果是在客户端的项目配置文件中配置了参数,那么当组件进行预渲染或服务端交互渲染时,读取不到,当组件进行客户端交互渲染时可以读取到。
例如,在服务端的appsettings.json
文件中,添加如下参数:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"MyData": "TestData"
}
然后在客户端项目中,添加Auto渲染模式的组件:
ConfigTest.razor
@page "/config-test"
@rendermode InteractiveAuto
@inject IConfiguration Configuration
<h3>ConfigTest</h3>
<p>
@if (@Configuration["MyData"] is object)
{
@:预渲染或服务端交互渲染,读取到参数 MyData:@Configuration["MyData"]
}
else
{
@:客户端交互渲染,无法读取到参数
}
</p>
例子中,使用了Auto渲染模式,一开始会进行预渲染、服务端交互渲染,然后会进行客户端交互渲染,所以只有刚开始出现页面时能访问到数据,过一会切换到客户端交互渲染后,就访问不到了。
2、静态资源配置文件
上面的所使用的是项目的默认json配置文件,一般情况下,项目配置文件多用来进行一些较为关键的参数配置,例如日志、数据库连接字符串等等。如果有额外的参数需要配置,建议在wwwroot
文件夹下,创建新的json配置文件,进行参数的配置。
newDataConfig.json
{
"MyData1": "DataTest1",
"MyData2": {
"Name": "Schuyler",
"Age": 23
},
"MyData3": [
{
"Name": "Schuyler1",
"Age": 24
},
{
"Name": "Schuyler2",
"Age": 25
}
]
}
客户端安全限制阻止通过用户代码直接访问文件,包括配置文件。 若除了appsettings.json
/appsettings.Development.json
之外,还要将 wwwroot
文件夹中的配置文件加载到IConfiguration
服务中,则需要使用HttpClient
来进行文件的访问。
- 注意,以客户端为例,除了
appsettings.json
/appsettings.Development.json
会自动加载外,不管是想使用自己项目中的wwwroot
文件夹下的配置文件还是服务端项目中的wwwroot
文件夹下的配置文件,最好都用HttpClient
来进行加载。
示例-客户端项目的Program.cs
var builder = WebAssemblyHostBuilder.CreateDefault(args);
var http = new HttpClient()
{
BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)
};
builder.Services.AddScoped(sp => http);
using var response = await http.GetAsync("newDataConfig2.json");
using var stream = await response.Content.ReadAsStreamAsync();
builder.Configuration.AddJsonStream(stream);
await builder.Build().RunAsync();
二、内存配置源
除了使用文件进行配置外,还可以在Program
中,使用内存来进行参数配置。
Program.cs
var builder = WebAssemblyHostBuilder.CreateDefault(args);
//内存参数配置
var vehicleData = new Dictionary<string, string?>()
{
{ "color", "blue" },
{ "type", "car" },
{ "wheels:count", "3" },
{ "wheels:brand", "Blazin" },
{ "wheels:brand:type", "rally" },
{ "wheels:year", "2008" },
};
var memoryConfig = new MemoryConfigurationSource { InitialData = vehicleData };
builder.Configuration.Add(memoryConfig);
await builder.Build().RunAsync();
将IConfiguration
实例注入到组件中来访问配置数据。
ConfigTest.razor
@page "/config-test"
@rendermode InteractiveAuto
@inject IConfiguration Configuration
<h3>ConfigTest</h3>
<p>
@if (@Configuration["color"] is object)
{
@:读取到参数 color:@Configuration["color"]
}
else
{
@:无法读取到参数
}
</p>
启动
一、启动过程和配置
1、自动启动
Blazor 启动过程默认情况下,是通过 Blazor 内置的JS脚本 (例如blazor.web.js
、blazor.server.js
、blazor.webassembly.js
等) 自动异步完成的,不同托管方式的Blazor脚本的引入位置如下(后面一律称为 Blazor<script>
标记):
- Blazor Web 应用,Blazor 脚本位于
Components/App.razor
文件中<script src="_framework/blazor.web.js"></script>
- Blazor Server 应用,Blazor 脚本位于
Pages/_Host.cshtml
文件中<script src="_framework/blazor.server.js"></script>
- Blazor WebAssembly 应用,Blazor 脚本内容位于
wwwroot/index.html
文件中<script src="_framework/blazor.webassembly.js"></script>
后面的关于不同应用的内置启动JS脚本的路径,都用{BLAZOR SCRIPT}
进行表示了,不然太冗余。
2、手动启动
有时候需要在Blazor启动时,做一些自定义的初始化操作,Blazor Web App可以通过如下步骤来实现:
- 将
autostart="false"
属性和值添加到 Blazor<script>
标记中 - 将调用
Blazor.start()
的Js脚本放置在 Blazor启动脚本的</script>
标记之后并放在结束的</body>
标记内。 - 将静态服务器端渲染(静态 SSR)选项置于
ssr
属性中。(如果需要设置) - 将服务器端 Blazor-SignalR 线路选项置于
circuit
属性中。(如果需要设置) - 将客户端 WebAssembly 选项置于
webAssembly
属性中。(如果需要设置)
示例
<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
...
Blazor.start({
ssr: {
...
},
circuit: {
...
},
webAssembly: {
...
}
});
//如果不需要进行设置,那么直接Start
//Blazor.start();
...
</script>
当然了,如果是单独的Blazor Server或者是Blazor WebAssembly只需要设置自己对应的选项就好。
手动启动后执行JS代码
如果希望再Blazor启动后执行一些JS任务,可以链式调用then()
方法。
- 建议使用JS 初始值设定项(详看下文),而不是
then()
示例
<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
Blazor.start().then(function () {
...
});
</script>
文档准备就绪后再初始化 Blazor
示例
<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
document.addEventListener("DOMContentLoaded", function() {
Blazor.start();
});
</script>
二、JavaScript 初始值设定项
JavaScript 初始值设定项在 Blazor 应用加载之前或之后执行逻辑。 JS 初始值设定项在以下场景中很有用:
- 自定义 Blazor 应用的加载方式。
- 在 Blazor 启动之前初始化库。
- 配置 Blazor 设置。
JS 初始值设定项是在生成过程中检测并自动进行导入的,不需要再去手动触发脚本。如果要定义 JS 初始值设定项,需要在项目的根目录中,默认情况下即 wwwroot
文件夹下,添加{NAME}.lib.module.js
文件,其中{NAME}
占位符表示当前程序集名称。
1、初始化回调方法
Blazor Web 应用
beforeWebStart(options)
:在 Blazor Web 应用启动之前调用,用于自定义加载过程、日志记录级别和其他选项。 Blazor Web 选项对象作为options
参数传递给beforeWebStart
afterWebStarted(blazor)
:在所有beforeWebStart
解决后调用,可用于注册 Blazor 事件侦听器和自定义事件类型。 Blazor 实例作为参数blazor
传递给afterWebStarted
。beforeServerStart(options, extensions)
:在启动第一个服务器运行时之前调用。 接收 SignalR 路线启动选项 (options
) 以及在发布期间添加的任何扩展 (extensions
)。afterServerStarted(blazor)
:在启动第一个交互式服务器运行时之后调用。beforeWebAssemblyStart(options, extensions)
:在启动交互式 WebAssembly 运行时之前调用。 接收 Blazor 选项 (options
) 以及在发布期间添加的任何扩展 (extensions
)。选项可以指定使用自定义启动资源加载程序。afterWebAssemblyStarted(blazor)
:在启动交互式 WebAssembly 运行时之后调用。
Blazor Server、Blazor WebAssembly 和 Blazor Hybrid 应用
beforeStart(options, extensions)
:在 Blazor 启动之前调用。用于自定义加载过程、日志记录级别以及其他特定于托管模型的选项。afterStarted(blazor)
:在 Blazor 准备好从 JS 接收调用后调用。 用于通过进行 JS 互操作调用并注册自定义元素来初始化库。 Blazor 实例作为参数blazor
传递给afterStarted
。
2、导入其他模块
如果要在JS初始值设定项中使用其他JS文件,可以通过import
语句导入
additionalModule.js
export function logMessage() {
console.log('logMessage is logging');
}
{NAME}.lib.module.js
import { logMessage } from "/additionalModule.js";
export function beforeStart(options, extensions) {
...
logMessage();
}
3、示例
确保加载JS库的顺序
以下示例在 script2.js 之前加载 script1.js,在 script4.js 之前加载 script3.js
export function beforeWebStart(options, extensions) {
var customScript1 = document.createElement('script');
customScript1.setAttribute('src', 'script1.js');
document.head.appendChild(customScript1);
var customScript2 = document.createElement('script');
customScript2.setAttribute('src', 'script2.js');
document.head.appendChild(customScript2);
}
export function afterWebStarted(blazor) {
var customScript1 = document.createElement('script');
customScript1.setAttribute('src', 'script3.js');
document.head.appendChild(customScript1);
var customScript2 = document.createElement('script');
customScript2.setAttribute('src', 'script4.js');
document.head.appendChild(customScript2);
}
环境
在本地运行应用时,环境默认为 Development
。 发布应用时,环境默认为 Production
。
建议使用以下约定
- 始终使用
Development
环境名称进行本地开发。 这是因为,在为应用的本地开发运行配置应用和工具时,ASP.NET Core 框架确切需要该名称。 - 对于测试、暂存和生产环境,请始终发布和部署应用。 可以使用希望用于已发布应用的任何环境命名方案,但始终使用应用设置文件名,环境段的大小写应与环境名称完全匹配。 对于暂存,请使用“
Staging
”(大写“S”)作为环境名称,并命名要匹配的应用设置文件 (appsettings.Staging.json
)。 对于生产,请使用“Production
”(大写“P”)作为环境名称,并命名要匹配的应用设置文件 (appsettings.Production.json
)。
一、组件中读取环境
在客户端组件中,如果想要获取应用的环境信息,可以通过注入IWebAssemblyHostEnvironment
并读取 Environment
属性来得到。
@page "/read-environment"
@using Microsoft.AspNetCore.Components.WebAssembly.Hosting
@inject IWebAssemblyHostEnvironment Env
<h1>Environment example</h1>
<p>Environment: @HostEnvironment.Environment</p>
需要注意的是,对于Blazor Web App Auto应用,IWebAssemblyHostEnvironment
仅在客户端项目(.Client
)中进行了服务的注册,如果客户端项目中的组件允许预渲染,那么当组件在服务器上预渲染时,会由于找不到IWebAssemblyHostEnvironment
而在注入该服务时出现异常。
针对这个问题,可以在服务器项目上创建IWebAssemblyHostEnvironment
的自定义服务,然后进行注册:
ServerHostEnvironment.cs
public class ServerHostEnvironment(IWebHostEnvironment env, NavigationManager nav) : IWebAssemblyHostEnvironment
{
public string Environment => env.EnvironmentName;
public string BaseAddress => nav.BaseUri;
}
Program.cs
......
builder.Services.TryAddScoped<IWebAssemblyHostEnvironment, ServerHostEnvironment>();
......
二、启动时读取客户端环境
在启动过程中,WebAssemblyHostBuilder
会通过HostEnvironment
属性公开 IWebAssemblyHostEnvironment
,因此可以在客户端项目的Program中,通过builder.HostEnvironment
来获取环境信息。
if (builder.HostEnvironment.Environment == "Development")
{
...
};
类似HostEnvironmentEnvExtensions
为IHostEnvironment
(服务端项目中Program.cs
所使用的主机环境类型)提供了一系列便捷的扩展方法一样,WebAssemblyHostEnvironmentExtensions
则是为IWebAssemblyHostEnvironment
(客户端项目中Program.cs
所使用的主机环境类型)提供了一系列便捷的扩展方法,可在当前环境中检查 Development
、Production
、Staging
和自定义环境名称
bool IsDevelopment()
bool IsProduction()
bool IsStaging()
bool IsEnvironment(envName)
if (builder.HostEnvironment.IsStaging())
{
...
};
if (builder.HostEnvironment.IsEnvironment("Custom"))
{
...
};