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

Blazor Server中_Layout引用<partial/>加载弹窗遇_Host相关报错

Blazor Server 加载完成后显示绑定模型弹窗的问题

我尝试在Blazor Server网站加载完成后,显示一个绑定模型数据的警告弹窗,但遇到了运行错误。以下是我的实现步骤:

1. 定义AlertModal模型类

public class AlertModal
{
    [Key]
    public int AlertId { get; set; }
    public string Image { get; set; }

    [Required(ErrorMessage = "This is a requierd field")]
    public string TextPar { get; set; } 
    public string TextPar1 { get; set; }
    public string TextPar2 { get; set; }

    [Required(ErrorMessage = "This is a requierd field")]
    public bool Show { get; set; }
}

2. 创建分部视图的PageModel

public class _InfoPartialModel : PageModel
{
    public AlertModal AlertModal { get; set; }
    public void OnGet()
    {
        AlertModal = new AlertModal()
        {
            TextPar = "This is a test",
            Show = true
        };
    }
}

3. 编写分部视图页面

@page
@model Tjoba.Pages.Shared._InfoPartialModel
@{}

@if (Model.AlertModal.Show)
{
    <div class="modal fade " id="IndexModal" role="dialog" tabindex="-1" aria-hidden="true">
        <div class="modal-dialog modal-dialog-centered" role="document">
            <div class="modal-content">

                <div class="modal-header">
                    <h5 class="modal-title text-black">@Model.AlertModal.TextPar </h5>
                    <button type="button" data-bs-dismiss="modal" aria-hidden="true">x</button>
                    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                        <span aria-hidden="true">&times;</span>
                    </button>
                </div>

                <div class="modal-body">
                    <div class="row">
                        <img src="/images/Vacation_volleyball.jpeg" class=" col-12 p-0 m-0 mx-auto " style="transform:none" />
                    </div>
                </div>
                <div class="modal-footer">
                    <button class="btn btn-secondary" value="1" data-bs-dismiss="modal">Sluiten</button>

                </div>
            </div>
        </div>
    </div>
    <script>
        $(document).ready(function () {

            setTimeout(function () {
                $("#IndexModal").modal('show');
            }, 4000);           

        });
    </script>
}

4. 在_Layout.cshtml中引用分部视图

<partial name="_InfoPartial" model="Model.AlertModal" />

出现的错误

启动网站时抛出异常:

An unhandled exception occurred while processing the request.
RuntimeBinderException: 'Tjoba.Pages.Pages__Host' does not contain a definition for 'AlertModal'

我的_Host.cshtml内容如下:

@page "/"
@namespace Tjoba.Pages

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers


@{
    Layout = "_Layout";

}

<component type="typeof(App)" render-mode="ServerPrerendered" />

疑问

该错误为何与_Host文件相关?我哪里操作出错了?


问题分析与解决方案

错误原因

错误关联_Host文件的核心原因:_Host.cshtml设置了Layout = "_Layout";,所以_Layout.cshtml的渲染上下文是_Host.cshtml对应的PageModel(即Pages__Host)。你在_Layout.cshtml中尝试传递Model.AlertModal给分部视图,但_Host.cshtml根本没有定义AlertModal属性,运行时找不到这个成员,因此抛出绑定异常。

操作中的错误点

  1. 错误将带路由的Razor页面作为分部视图引用:你给_InfoPartial.cshtml加了@page指令,这会让它变成一个独立的路由页面,而非普通分部视图,不能直接用<partial>标签引用。
  2. 模型传递上下文错误:即使是普通分部视图,_Layout.cshtml中的Model指向的是当前使用布局的页面的Model(这里就是_Host.cshtml的Model),但_Host.cshtml没有定义AlertModal,自然会报错。

修正方案

方案一:改为普通分部视图(适配Razor页面布局)

  1. 修改分部视图:删除_InfoPartial.cshtml中的@page指令,调整模型直接绑定AlertModal:
@model Tjoba.Models.AlertModal

@if (Model.Show)
{
    <div class="modal fade " id="IndexModal" role="dialog" tabindex="-1" aria-hidden="true">
        <div class="modal-dialog modal-dialog-centered" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title text-black">@Model.TextPar </h5>
                    <button type="button" data-bs-dismiss="modal" aria-hidden="true">x</button>
                    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                        <span aria-hidden="true">&times;</span>
                    </button>
                </div>
                <div class="modal-body">
                    <div class="row">
                        <img src="/images/Vacation_volleyball.jpeg" class=" col-12 p-0 m-0 mx-auto " style="transform:none" />
                    </div>
                </div>
                <div class="modal-footer">
                    <button class="btn btn-secondary" value="1" data-bs-dismiss="modal">Sluiten</button>
                </div>
            </div>
        </div>
    </div>
    <script>
        $(document).ready(function () {
            setTimeout(function () {
                $("#IndexModal").modal('show');
            }, 4000);           
        });
    </script>
}
  1. 删除多余的PageModel:删掉_InfoPartialModel.cs文件,普通分部视图不需要独立的PageModel。
  2. 给_Host添加Model并初始化数据:
    • 创建HostModel.cs:
      public class HostModel : PageModel
      {
          public AlertModal AlertModal { get; set; }
      
          public void OnGet()
          {
              AlertModal = new AlertModal()
              {
                  TextPar = "This is a test",
                  Show = true
              };
          }
      }
      
    • 修改_Host.cshtml引用该Model:
      @page "/"
      @namespace Tjoba.Pages
      @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
      @model Tjoba.Pages.HostModel
      
      @{
          Layout = "_Layout";
      }
      
      <component type="typeof(App)" render-mode="ServerPrerendered" />
      
  3. 修正_Layout中的分部视图引用:保持之前的代码即可,现在Model.AlertModal就能从HostModel中获取到数据。

方案二:使用Blazor组件实现(更推荐,贴合Blazor生态)

Blazor Server优先使用Blazor组件而非Razor页面分部视图,避免上下文混淆:

  1. 创建AlertModal Blazor组件:
@inject IJSRuntime JSRuntime
@model Tjoba.Models.AlertModal

@if (Model.Show)
{
    <div class="modal fade " id="IndexModal" role="dialog" tabindex="-1" aria-hidden="true">
        <div class="modal-dialog modal-dialog-centered" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title text-black">@Model.TextPar </h5>
                    <button type="button" data-bs-dismiss="modal" aria-hidden="true">x</button>
                    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                        <span aria-hidden="true">&times;</span>
                    </button>
                </div>
                <div class="modal-body">
                    <div class="row">
                        <img src="/images/Vacation_volleyball.jpeg" class=" col-12 p-0 m-0 mx-auto " style="transform:none" />
                    </div>
                </div>
                <div class="modal-footer">
                    <button class="btn btn-secondary" value="1" data-bs-dismiss="modal">Sluiten</button>
                </div>
            </div>
        </div>
    </div>
}

@code {
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender && Model.Show)
        {
            await Task.Delay(4000);
            await JSRuntime.InvokeVoidAsync("$('#IndexModal').modal('show')");
        }
    }
}
  1. 在Blazor组件中引用:
    比如在MainLayout.razor中添加引用,这样所有页面加载后都会显示弹窗:
@inherits LayoutComponentBase

<div class="page">
    <div class="sidebar">
        <NavMenu />
    </div>

    <main>
        <div class="top-row px-4">
            <a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
        </div>

        <article class="content px-4">
            @Body
        </article>
    </main>
</div>

<AlertModal Model="@new AlertModal { TextPar = "This is a test", Show = true }" />

这种方式使用Blazor的生命周期方法OnAfterRenderAsync触发弹窗,通过IJSRuntime调用JS,更符合Blazor Server的开发规范,也避免了Razor页面和Blazor组件混合的上下文问题。


内容的提问来源于stack exchange,提问作者Gerald

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 20:57:03