You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在带RenderBody的Razor .cshtml组件中读取appsettings.json数据报错

Razor布局页获取AppSettings并在JS中使用时RenderBody()报错问题

问题描述

我在Blazor Server项目的Razor布局页中使用RenderBody()渲染页面主体,尝试添加代码获取appsettings配置后,RenderBody()无法执行并抛出错误。我的需求是在页面的JavaScript代码中使用appsettings里的配置值(比如给图片设置src)。

原始布局页代码

@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Mvc.TagHelpers
@using Microsoft.Extensions.Options
@using Signumid.ESignLiteShop.Data.Models
@namespace Signumid.ESignLiteShop.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <base href="~/"/>
    <link rel="stylesheet" href="css/bootstrap/bootstrap.min.css"/>
    <link href="css/site.css" rel="stylesheet"/>
    <link href="Signumid.ESignLiteShop.styles.css" rel="stylesheet"/>
    <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" rel="stylesheet"/>
    <link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet"/>
    <link href="http://fonts.cdnfonts.com/css/open-sans" rel="stylesheet">
    <component type="typeof(HeadOutlet)" render-mode="ServerPrerendered"/>

    <title>eSign-Lite Shop</title>
</head>
<body>

导致错误的代码

添加以下代码后,RenderBody()无法正常执行并报错:

@{ 
        public static IOptions<ShopAppSettings> _config = null!;
}

包含JavaScript的完整页面代码(需使用AppSettings值)

@RenderBody()
<div id="blazor-error-ui">
    <environment include="Staging,Production">
        An error has occurred. This application may no longer respond until reloaded.
    </environment>
    <environment include="Development">
        An unhandled exception has occurred. See browser dev tools for details.
    </environment>
    <a href="" class="reload">Reload</a>
    <a class="dismiss">🗙</a>
</div>

<script src="./_framework/blazor.server.js"></script>
<script src="./_content/MudBlazor/MudBlazor.min.js"></script>
<script>

"use strict";
function purchaseComplete() {
    window.postMessage({ type: "SIGNATOR_BILLING_PURCHASE_COMPLETED" }, "*");
    //TODO: Add tooltip
}
function purchaseClosed() {
    //TODO: Add tooltip 
}
var BillingComponent = (function () {
    function BillingComponent(mobilePhone, organizationId) {
        this.mobilePhone = mobilePhone;
        this.organizationId = organizationId;
    }
    BillingComponent.prototype.buyAndOpenCheckout = function (productId, quantity) {
        window.Paddle.Checkout.open({
            product: productId,
            passthrough: { phoneNumber: this.mobilePhone, organizationId: this.organizationId },
            quantity: quantity,
            allowQuantity: false,
            disableLogout: true,
            successCallback: purchaseComplete,
            closeCallback: purchaseClosed,
        });
    };
    BillingComponent.prototype.renderBillingModal = function () {
        var _this = this;
        document.head.appendChild(styleSheet);
        var getDrawerElement = document.getElementById("shop-billing-container");
        //create modal content div element
        var modalContent = document.createElement("div");
        modalContent.classList.add("billing-modal-content");
        var modalContentBodyContent = document.createElement("div");
        modalContentBodyContent.classList.add("billing-modal-content-body-content");
        //create new package
        //package ONE
        var newPackageOneCard = document.createElement("div");
        newPackageOneCard.classList.add("signator-billing-package-card");
        newPackageOneCard.onclick = function () { return _this.buyAndOpenCheckout("32227"); };
        var newPackageOneCardImgBox = document.createElement("div");
        newPackageOneCardImgBox.classList.add("signatorCardImgBox");
        var newPackageOneCardImg = document.createElement("img");
        newPackageOneCardImg.classList.add("signator-package-image");
        newPackageOneCardImg.src = "";
        var newPackageOneCardContentBox = document.createElement("div");
        newPackageOneCardContentBox.classList.add("signator-billing-package-card-content-box");
        var newPackageOneCardContentTitle = document.createElement("div");
        newPackageOneCardContentTitle.classList.add("signator-billing-package-card-h3");
        newPackageOneCardContentTitle.textContent = "10 credits";
        var newPackageOneCardContentTitleTwo = document.createElement("div");
        newPackageOneCardContentTitleTwo.classList.add("signator-billing-package-card-h2");
        newPackageOneCardContentTitleTwo.textContent =
            /*i18next.t("price_label")*/ "Price:" + @_config.Value.Test;
        var newPackageOneCardContentBuyButton = document.createElement("a");
        newPackageOneCardContentBuyButton.classList.add("signator-billing-package-card-buy-button");
        newPackageOneCardContentBuyButton.textContent = "Buy";
        newPackageOneCardImgBox.appendChild(newPackageOneCardImg);
        newPackageOneCardContentBox.appendChild(newPackageOneCardContentTitle);
        newPackageOneCardContentBox.appendChild(newPackageOneCardContentTitleTwo);
        newPackageOneCardContentBox.appendChild(newPackageOneCardContentBuyButton);
        newPackageOneCard.appendChild(newPackageOneCardImgBox);
        newPackageOneCard.appendChild(newPackageOneCardContentBox);
        //package TWO
        var newPackageTwoCard = document.createElement("div");
        newPackageTwoCard.classList.add("signator-billing-package-card");
        newPackageTwoCard.onclick = function () { return _this.buyAndOpenCheckout("32228"); };
        var newPackageTwoCardImgBox = document.createElement("div");
        newPackageTwoCardImgBox.classList.add("signatorCardImgBox");
        var newPackageTwoCardImg = document.createElement("img");
        newPackageTwoCardImg.classList.add("signator-package-image");
        newPackageTwoCardImg.src = "";
        var newPackageTwoCardContentBox = document.createElement("div");
        newPackageTwoCardContentBox.classList.add("signator-billing-package-card-content-box");
        var newPackageTwoCardContentTitle = document.createElement("div");
        newPackageTwoCardContentTitle.classList.add("signator-billing-package-card-h3");
        newPackageTwoCardContentTitle.textContent = "50 credits";
        var newPackageTwoCardContentTitleTwo = document.createElement("div");
        newPackageTwoCardContentTitleTwo.classList.add("signator-billing-package-card-h2");
        newPackageTwoCardContentTitleTwo.textContent = "Price:";
        var newPackageTwoCardContentBuyButton = document.createElement("a");
        newPackageTwoCardContentBuyButton.classList.add("signator-billing-package-card-buy-button");
        newPackageTwoCardContentBuyButton.textContent = "Buy";
        newPackageTwoCardImgBox.appendChild(newPackageTwoCardImg);
        newPackageTwoCardContentBox.appendChild(newPackageTwoCardContentTitle);
        newPackageTwoCardContentBox.appendChild(newPackageTwoCardContentTitleTwo);
        newPackageTwoCardContentBox.appendChild(newPackageTwoCardContentBuyButton);
        newPackageTwoCard.appendChild(newPackageTwoCardImgBox);
        newPackageTwoCard.appendChild(newPackageTwoCardContentBox);
        //package THREE
        var newPackageThreeCard = document.createElement("div");
        newPackageThreeCard.classList.add("signator-billing-package-card");
        var newPackageThreeCardImgBox = document.createElement("div");
        newPackageThreeCardImgBox.classList.add("signatorCardImgBox");
        var newPackageThreeCardImg = document.createElement("img");
        newPackageThreeCardImg.classList.add("signator-package-image");
        newPackageThreeCardImg.src = "";
        var newPackageThreeCardContentBox = document.createElement("div");
        newPackageThreeCardContentBox.classList.add("signator-billing-package-card-content-box");
        var newPackageThreeCardContentTitle = document.createElement("div");
        newPackageThreeCardContentTitle.classList.add("signator-billing-package-card-h3");
        newPackageThreeCardContentTitle.textContent = "100 credits";
        var newPackageThreeCardContentTitleTwo = document.createElement("div");
        newPackageThreeCardContentTitleTwo.classList.add("signator-billing-package-card-h2");
        newPackageThreeCardContentTitleTwo.textContent = "Price:";
        var newPackageThreeCardContentBuyButton = document.createElement("a");
        newPackageThreeCardContentBuyButton.classList.add("signator-billing-package-card-buy-button");
        newPackageThreeCardContentBuyButton.textContent = "Buy";
        newPackageThreeCardImgBox.appendChild(newPackageThreeCardImg);
        newPackageThreeCardContentBox.appendChild(newPackageThreeCardContentTitle);
        newPackageThreeCardContentBox.appendChild(newPackageThreeCardContentTitleTwo);
        newPackageThreeCardContentBox.appendChild(newPackageThreeCardContentBuyButton);
        newPackageThreeCard.appendChild(newPackageThreeCardImgBox);
        newPackageThreeCard.appendChild(newPackageThreeCardContentBox);
        //create modal footer with button
        var modalContentFooter = document.createElement("div");
        modalContentFooter.classList.add("billing-modal-content-footer");
        modalContent.appendChild(modalContentBodyContent);
        modalContentBodyContent.appendChild(newPackageOneCard);
        modalContentBodyContent.appendChild(newPackageTwoCard);
        modalContentBodyContent.appendChild(newPackageThreeCard);
        modalContent.appendChild(modalContentFooter);
        if (getDrawerElement) {
            getDrawerElement.appendChild(modalContent);
        }
        else {
            setTimeout(function () {
                var getDrawerElementAfterTimeout = document.getElementById("shop-billing-container");
                getDrawerElementAfterTimeout === null || getDrawerElementAfterTimeout === void 0 ? void 0 : getDrawerElementAfterTimeout.appendChild(modalContent);
            }, 500);
        }
    };
    return BillingComponent;
}());

window.signatorBilling =
    {
        ShowBillingModal: function (number, organizationId) {
             var x = new BillingComponent(number, organizationId);
             x.renderBillingModal();
        }
    }
</script>
<script src="https://cdn.paddle.com/paddle/paddle.js"></script>
<script type="text/javascript">
Paddle.Environment.set("sandbox");
Paddle.Setup({vendor:1234});
</script>
</body>
</html>

解决方案

错误原因

在Razor布局页的代码块中直接声明静态IOptions<ShopAppSettings>字段的方式不正确,布局页需要通过依赖注入获取配置服务,而非手动声明静态字段,这会导致页面渲染逻辑出错。

正确实现步骤

  1. 在布局页顶部注入IOptions服务
    在布局页的指令部分添加注入语句,让框架自动注入配置实例:

    @inject IOptions<ShopAppSettings> Config
    
  2. 将配置值传递给JavaScript
    可以通过两种方式传递:

    • 方式一:在页面中渲染全局JS变量,供后续代码使用
    • 方式二:直接在JS代码中嵌入Razor表达式获取配置值
  3. 修改后的完整布局页代码

@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Mvc.TagHelpers
@using Microsoft.Extensions.Options
@using Signumid.ESignLiteShop.Data.Models
@namespace Signumid.ESignLiteShop.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@inject IOptions<ShopAppSettings> Config

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <base href="~/"/>
    <link rel="stylesheet" href="css/bootstrap/bootstrap.min.css"/>
    <link href="css/site.css" rel="stylesheet"/>
    <link href="Signumid.ESignLiteShop.styles.css" rel="stylesheet"/>
    <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" rel="stylesheet"/>
    <link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet"/>
    <link href="http://fonts.cdnfonts.com/css/open-sans" rel="stylesheet">
    <component type="typeof(HeadOutlet)" render-mode="ServerPrerendered"/>

    <title>eSign-Lite Shop</title>
    <!-- 方式一:渲染全局配置变量 -->
    <script>
        window.appSettings = {
            testValue: '@Config.Value.Test',
            packageOneImgSrc: '@Config.Value.PackageOneImgSrc' // 假设appsettings中有这个配置项
        };
    </script>
</head>
<body>
@RenderBody()
<div id="blazor-error-ui">
    <environment include="Staging,Production">
        发生错误,应用可能需要重新加载才能响应。
    </environment>
    <environment include="Development">
        发生未处理的异常,请查看浏览器开发者工具获取详情。
    </environment>
    <a href="" class="reload">重新加载</a>
    <a class="dismiss">🗙</a>
</div>

<script src="./_framework/blazor.server.js"></script>
<script src="./_content/MudBlazor/MudBlazor.min.js"></script>
<script>

"use strict";
function purchaseComplete() {
    window.postMessage({ type: "SIGNATOR_BILLING_PURCHASE_COMPLETED" }, "*");
    //TODO: Add tooltip
}
function purchaseClosed() {
    //TODO: Add tooltip 
}
var BillingComponent = (function () {
    function BillingComponent(mobilePhone, organizationId) {
        this.mobilePhone = mobilePhone;
        this.organizationId = organizationId;
    }
    BillingComponent.prototype.buyAndOpenCheckout = function (productId, quantity) {
        window.Paddle.Checkout.open({
            product: productId,
            passthrough: { phoneNumber: this.mobilePhone, organizationId: this.organizationId },
            quantity: quantity,
            allowQuantity: false,
            disableLogout: true,
            successCallback: purchaseComplete,
            closeCallback: purchaseClosed,
        });
    };
    BillingComponent.prototype.renderBillingModal = function () {
        var _this = this;
        // 原代码中styleSheet未定义,此处注释避免报错
        // document.head.appendChild(styleSheet);
        var getDrawerElement = document.getElementById("shop-billing-container");
        //create modal content div element
        var modalContent = document.createElement("div");
        modalContent.classList.add("billing-modal-content");
        var modalContentBodyContent = document.createElement("div");
        modalContentBodyContent.classList.add("billing-modal-content-body-content");
        //create new package
        //package ONE
        var newPackageOneCard = document.createElement("div");
        newPackageOneCard.classList.add("signator-billing-package-card");
        newPackageOneCard.onclick = function () { return _this.buyAndOpenCheckout("32227"); };
        var newPackageOneCardImgBox = document.createElement("div");
        newPackageOneCardImgBox.classList.add("signatorCardImgBox");
        var newPackageOneCardImg = document.createElement("img");
        newPackageOneCardImg.classList.add("signator-package-image");
        // 方式一:使用全局变量
        newPackageOneCardImg.src = window.appSettings.packageOneImgSrc;
        var newPackageOneCardContentBox = document.createElement("div");
        newPackageOneCardContentBox.classList.add("signator-billing-package-card-content-box");
        var newPackageOneCardContentTitle = document.createElement("div");
        newPackageOneCardContentTitle.classList.add("signator-billing-package-card-h3");
        newPackageOneCardContentTitle.textContent = "10 credits";
        var newPackageOneCardContentTitleTwo = document.createElement("div");
        newPackageOneCardContentTitleTwo.classList.add("signator-billing-package-card-h2");
        // 方式二:直接嵌入Razor表达式
        newPackageOneCardContentTitleTwo.textContent = "Price:" + '@Config.Value.Test';
        var newPackageOneCardContentBuyButton = document.createElement("a");
        newPackageOneCardContentBuyButton.classList.add("signator-billing-package-card-buy-button");
        newPackageOneCardContentBuyButton.textContent = "Buy";
        newPackageOneCardImgBox.appendChild(newPackageOneCardImg);
        newPackageOneCardContentBox.appendChild(newPackageOneCardContentTitle);
        newPackageOneCardContentBox.appendChild(newPackageOneCardContentTitleTwo);
        newPackageOneCardContentBox.appendChild(newPackageOneCardContentBuyButton);
        newPackageOneCard.appendChild(newPackageOneCardImgBox);
        newPackageOneCard.appendChild(newPackageOneCardContentBox);
        //package TWO
        var newPackageTwoCard = document.createElement("div");
        newPackageTwoCard.classList.add("signator-billing-package-card");
        newPackageTwoCard.onclick = function () { return _this.buyAndOpenCheckout("32228"); };
        var newPackageTwoCardImgBox = document.createElement("div");
        newPackageTwoCardImgBox.classList.add("signatorCardImgBox");
        var newPackageTwoCardImg = document.createElement("img");
相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 01:31:21