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

ASP.NET Core中Index经_Layout传模型至_Header引发空引用异常

问题描述

基于ASP.NET Core 8.0的Razor Pages项目中,访问http://localhost:5###/时,尝试通过ViewData["_Header"]从Index页面经_Layout页面传递数据到_Header页面,_Header页面在get_Model()处抛出NullReferenceException。调试发现ViewData["_Header"]值正常,但执行Html.PartialAsync("_Header", ViewData["_Header"])后模型变为null。

相关代码

Index.cshtml

@page
@{
    Layout = "_Layout";
    ViewData["_Header"] = new DemoForStackOverflow.Pages.Shared.Header() {IsArriving = true};
}
<h2>some content</h2>

_Layout.cshtml

<!DOCTYPE html>
<html>
    <head>
        <title>Demo for Stack Overflow</title>
    </head>
    <body>
        <div id="header">
            @await Html.PartialAsync("_Header", ViewData["_Header"])
        </div>
        <h1>Appears on every page below header and above body</h1>
        <div id="body">
            @RenderBody()
        </div>
    </body>
</html>

_Header.cshtml

@page
@model DemoForStackOverflow.Pages.Shared.Header

@if (Model.IsArriving)
{
    <p>Hello</p>
}
else
{
    <p>Goodbye</p>
}

_Header.cshtml.cs

using Microsoft.AspNetCore.Mvc.RazorPages;

namespace DemoForStackOverflow.Pages.Shared;

public class Header : PageModel
{
    public bool IsArriving { get; set; }
}

异常信息

> Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
>
> An unhandled exception has occurred while executing the request.
>
> System.NullReferenceException: Object reference not set to an instance of an object.
>
> at AspNetCoreGeneratedDocument.Pages_Shared__Header.get_Model()  
> at AspNetCoreGeneratedDocument.Pages_Shared__Header.ExecuteAsync() in /home/RF/DemoForStackOverflow/Pages/Shared/_Header.cshtml:line 4  
> at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageCoreAsync(IRazorPage page, ViewContext context)  
> at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageAsync(IRazorPage page, ViewContext context, Boolean invokeViewStarts)  
> at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderAsync(ViewContext context)
         at Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.RenderPartialCoreAsync(String partialViewName, Object model, ViewDataDictionary viewData, TextWriter writer)
         at Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.PartialAsync(String partialViewName, Object model, ViewDataDictionary viewData)
         at AspNetCoreGeneratedDocument.Pages_Shared__Layout.<ExecuteAsync>b__8_1() in /home/RF/DemoForStackOverflow/Pages/Shared/_Layout.cshtml:line 8
         at Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperExecutionContext.SetOutputContentAsync()
         at AspNetCoreGeneratedDocument.Pages_Shared__Layout.ExecuteAsync()
         at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageCoreAsync(IRazorPage page, ViewContext context)
         at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageAsync(IRazorPage page, ViewContext context, Boolean invokeViewStarts)
         at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderLayoutAsync(ViewContext context, ViewBufferTextWriter bodyWriter)
         at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderAsync(ViewContext context)
         at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, String contentType, Nullable`1 statusCode)
         at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, String contentType, Nullable`1 statusCode)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|30_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
      --- End of stack trace from previous location ---
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
      --- End of stack trace from previous location ---
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
         at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
         at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
         at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
问题原因

_Header.cshtml中添加了@page指令,这会将该文件标记为独立的Razor Page,而非Partial View。当通过Html.PartialAsync调用时,Razor会初始化该Page的PageModel(即Header类),而忽略传入的模型参数,导致Model属性为空,最终触发NullReferenceException。

解决方案

修复现有代码

只需移除_Header.cshtml中的@page指令,将其改为Partial View:

@model DemoForStackOverflow.Pages.Shared.Header

@if (Model.IsArriving)
{
    <p>Hello</p>
}
else
{
    <p>Goodbye</p>
}

此时Html.PartialAsync传入的模型会正确绑定到Model属性,异常即可解决。

更优实现方式

方式1:使用ViewComponent

ViewComponent是Razor Pages中更适合复用组件的方案,支持独立逻辑和视图:

  1. 创建HeaderViewComponent.cs:
using Microsoft.AspNetCore.Mvc;

namespace DemoForStackOverflow.ViewComponents;

public class HeaderViewComponent : ViewComponent
{
    public IViewComponentResult Invoke(bool isArriving)
    {
        return View(isArriving);
    }
}
  1. 在Pages/Shared/Components/Header/Default.cshtml创建视图:
@model bool

@if (Model)
{
    <p>Hello</p>
}
else
{
    <p>Goodbye</p>
}
  1. 在_Layout.cshtml中调用:
<div id="header">
    @await Component.InvokeAsync("Header", new { isArriving = ViewData["_HeaderIsArriving"] })
</div>
  1. 在Index.cshtml中设置数据:
@{
    ViewData["_HeaderIsArriving"] = true;
}

方式2:直接使用ViewData传递

无需创建PageModel类,直接通过ViewData传递值:

  1. Index.cshtml中设置:
@{
    ViewData["IsArriving"] = true;
}
  1. _Header.cshtml(移除@page和@model)中直接读取:
@if ((bool)ViewData["IsArriving"])
{
    <p>Hello</p>
}
else
{
    <p>Goodbye</p>
}
  1. _Layout.cshtml中调用Partial时无需传递模型:
<div id="header">
    @await Html.PartialAsync("_Header")
</div>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 16:24:52