第二章 基础知识(7) - 配置

news/2025/2/23 22:32:31

注意

  • 客户端上的用户可以看到配置和设置文件,用户可以篡改数据。 请勿在应用的配置或文件中存储应用机密、凭据或任何其他敏感数据
  • 使用 WebAssembly 或Auto模式时,请记住所有组件代码都会编译并发送到客户端,用户可以在客户端对其进行反向编译和检查。 请勿在客户端渲染的组件中放置专用代码、应用机密或其他敏感信息

应用参数配置

一、文件配置源

1、项目默认配置文件

这里以Blazor web app Auto/Per page项目为例子,创建项目后,可以看到解决方案中会出现两个项目,一个是服务端,一个是客户端(.Client)。这两个项目中,都存在默认项目配置文件appsettings.jsonappsettings.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文件中,添加如下参数:

  • 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();
    

3、用户机密配置

在使用Visual Studio时,可以通过右键项目,选择管理用户机密,可以对secrets.json文件进行json配置。
在这里插入图片描述

secrets.json文件是针对当前开发者用户进行应用配置的私有文件,在开发环境下其配置会加载到应用中,且会覆盖appsettings.json文件的同名配置(如果有)。

其作用在于开发阶段,如果需要使用自己的本地配置,例如本地数据库连接啥的,而又不希望上传到共享项目上(git、SVG等),就可以使用secrets.json文件进行私有配置的管理,在上传项目时,secrets.json中的配置将不会被上传。

  • 试了一下,在Blazor Web App(Auto)模式下,客户端项目中的secrets.json文件是不生效的,原因应该是WebAssembly模式下,已经将相关代码和资料下载到浏览器了,此时只会将客户端appsettings.json中的配置加载

二、内存配置源

在WebAssembly客户端项目中,除了使用文件进行配置外,还可以在Program中,使用内存来进行参数配置。

  • 注意,只有WebAssembly客户端项目支持这个用法。

  • 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>
    

启动

这里只记录常用的内容,更详细的内容请查阅官方文档:https://learn.microsoft.com/zh-cn/aspnet/core/blazor/fundamentals/startup?view=aspnetcore-8.0

一、启动过程和配置

1、自动启动

Blazor 启动过程默认情况下,是通过 Blazor 内置的JS脚本 (例如blazor.web.jsblazor.server.jsblazor.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>
    

3、示例

禁用增强型导航和表单处理

  • 示例

    <script src="{BLAZOR SCRIPT}" autostart="false"></script>
    <script>
      Blazor.start({
        ssr: { disableDomPreservation: true }
      });
    </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 启动之前调用。用于自定义加载过程、日志记录级别以及其他特定于托管模型的选项。

  • 客户端 beforeStart 接收 Blazor 选项 (options) 以及在发布期间添加的任何扩展 (extensions)。 选项可以指定使用自定义启动资源加载程序。
  • 服务器端 beforeStart 接收 SignalR 线路启动选项 (options)。
  • BlazorWebView中,不会传递任何选项。

afterStarted(blazor):在 Blazor 准备好从 JS 接收调用后调用。 用于通过进行 JS 互操作调用并注册自定义元素来初始化库。 Blazor 实例作为参数blazor传递给 afterStarted

其他 .NET WebAssembly 运行时回调

onRuntimeConfigLoaded(config):在下载启动配置时调用。 允许应用在运行时启动前(参数是来自 dotnet.d.tsMonoConfig)修改参数(配置):

  • {NAME}.lib.module.js

    export function onRuntimeConfigLoaded(config) {
      // Sample: Enable startup diagnostic logging when the URL contains 
      // parameter debug=1
      const params = new URLSearchParams(location.search);
      if (params.get("debug") == "1") {
        config.diagnosticTracing = true;
      }
    }
    

onRuntimeReady({ getAssemblyExports, getConfig }):在 .NET WebAssembly 运行时启动后调用(参数是来自 dotnet.d.tsRuntimeAPI):

  • {NAME}.lib.module.js

    export function onRuntimeReady({ getAssemblyExports, getConfig }) {
      // Sample: After the runtime starts, but before Main method is called, 
      // call [JSExport]ed method.
      const config = getConfig();
      const exports = await getAssemblyExports(config.mainAssemblyName);
      exports.Sample.Greet();
    }
    

以上两个方法,都可以返回一个Promise,并会在启动程序之前等待该Promise

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);
    }
    

环境

这里只记录常用的内容,更详细的内容请查阅官方文档:https://learn.microsoft.com/zh-cn/aspnet/core/blazor/fundamentals/environments?view=aspnetcore-8.0

在本地使用Debug模式运行应用时,环境默认为 Development。 发布应用时,环境默认为 Production

建议使用以下约定

  • 始终使用Development环境名称进行本地开发。 这是因为,在为应用的本地开发运行配置应用和工具时,ASP.NET Core 框架需要该名称
  • 对于测试、暂存和生产环境,请始终发布和部署应用,不要直接运行源码
  • 命名自由但建议规范:测试 → Test;预发布 → Staging;生产 → Production;同时配置文件必须严格匹配,如:Stagingappsettings.Staging.jsonProductionappsettings.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")
{
    ......
};

类似HostEnvironmentEnvExtensionsIHostEnvironment(服务端项目中Program.cs所使用的主机环境类型)提供了一系列便捷的扩展方法一样,WebAssemblyHostEnvironmentExtensions则是为IWebAssemblyHostEnvironment(客户端项目中Program.cs所使用的主机环境类型)提供了一系列便捷的扩展方法,可在当前环境中检查 DevelopmentProductionStaging 和自定义环境名称

  • bool IsDevelopment()
  • bool IsProduction()
  • bool IsStaging()
  • bool IsEnvironment(envName)
if (builder.HostEnvironment.IsStaging())
{
    ......
};

if (builder.HostEnvironment.IsEnvironment("Custom"))
{
    ......
};

http://www.niftyadmin.cn/n/5863831.html

相关文章

算法系列之贪心算法

在算法中&#xff0c;贪心算法&#xff08;Greedy Algorithm&#xff09;是一种常见的解决优化问题的算法。贪心算法的核心思想是&#xff1a;在每一步选择中都采取当前状态下最优的选择&#xff0c;即贪心的做出局部最优的决策&#xff0c;从而希望最终能够得到全局最优解。尽…

AI革命下的多元生态:DeepSeek、ChatGPT、XAI、文心一言与通义千问的行业渗透与场景重构

前言 人工智能技术的爆发式发展催生了多样化的AI模型生态&#xff0c;从通用对话到垂直领域应用&#xff0c;从数据挖掘到创意生成&#xff0c;各模型凭借其独特的技术优势与场景适配性&#xff0c;正在重塑全球产业格局。本文将以DeepSeek、ChatGPT、XAI&#xff08;可解释人…

JAVAWeb之Servlet学习

认识 Servlet 就是 Sun 公司开发动态 Web 的一门技术 Sun 在这些 API &#xff08;Application Programming Interface&#xff0c;应用程序接口&#xff09;中提供一个接口叫做&#xff1a;Servlet&#xff0c;如果你想开发一个Servlet程序&#xff0c;只需要完成两个小步骤…

多门店协同管理困难重重,管理系统如何破局?

在零售业的快速发展中&#xff0c;越来越多的企业选择通过多门店的方式扩展市场。然而&#xff0c;随着门店数量的增加&#xff0c;企业在日常运营中的管理难度也逐渐加大&#xff0c;尤其是在协调各个门店之间的资源、信息和流程时&#xff0c;往往面临诸多挑战。如何在多门店…

Windows逆向工程入门之结构体类特性分析

公开视频 -> 链接点击跳转公开课程博客首页 -> ​​​链接点击跳转博客主页 目录 基本特性 构造函数 静态成员 常量成员 继承构造 继承(单) 继承(多) 继承(菱) 多态(单) 多态(多) 虚表(单) 虚表(多) 纯虚 基本特性 #include <iostream> #include &l…

红队内网攻防渗透:内网渗透之内网对抗:实战项目VPC1打靶PHP-RCE三层代理路由防火墙上线密码喷射域控提权

红队内网攻防渗透 实战网络攻防靶场记录1.靶机配置详情讲解1.1 入口点靶机:Windows Server 20121.2 第一层靶机:Windows 7 + Windows 101.3 第二层靶机:Windows 2012 R21.4 第三层靶机:Windows 2016 web +Windows 2016 AD域1.5 攻击者系统 :Kali-linux2.靶场渗透完整流程2…

算法-栈和队列篇04-滑动窗口最大值

滑动窗口最大值 力扣题目链接 题目描述 给你一个整数数组 nums&#xff0c;有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动窗口中的最大值 。 解题思路 这道题目一开始我是直…

Orcale、MySQL中参数类型的详解和运用场景(带示例)

Oracle 中的参数类型及运用场景 1. 数值类型 NUMBER(p, s) 详解&#xff1a;p 表示精度&#xff08;即数字的总位数&#xff09;&#xff0c;s 表示小数位数。例如&#xff0c;NUMBER(5, 2) 可以存储最大为 999.99 的数字。运用场景&#xff1a;适用于需要精确计算的财务数据…