将单独的模型添加到局部视图(使用Razor)

时间:2018-07-29 17:34:46

标签: c# asp.net-mvc razor

我正在开发一个带有.NET Core 2.1和Razor页面的Web应用程序。 我有一个_Layout页面,其中包含一个用于渲染部分视图(导航栏)和主体的调用。 布局页面的cshtml代码可以总结如下。

<div class="layout-wrapper layout">
  <div class="layout-inner">
    <!-- Layout navbar -->
    @await Html.PartialAsync("Shared/Partials/_LayoutNavbar")

    <!-- Layout content -->
    <div class="layout-content">
      <!-- Content -->
      <div class="container-fluid">
        @RenderBody()
      </div>
    </div>
    <!-- Layout content -->
  </div>
  <!-- / Layout container -->
</div>

此布局显然适用于许多页面,每个页面都有其自己的PageModel(请参见Microsoft description of .NET Core 2.1 Razor pages)。呈现页面Home.cshtml时,将加载模型HomeModel,并且相同的行为适用于所有需要相同布局的页面。

问题是我的导航栏需要一个单独的模型,该模型包含一个信息列表,而我显然不能将其添加到所有需要该布局的页面中。 添加指令:

@model Shared.Partials._LayoutNavbarModel

进入部分视图_LayoutNavbar.cshtml会生成错误,因为在主页上导航时,应用仍尝试将HomeModel传递给主页及其部分视图。错误是:

InvalidOperationException: The model item passed into the ViewDataDictionary
is of type 'MyApp.Pages.HomeModel', but this ViewDataDictionary instance
requires a model item of type 'MyApp.Pages.Shared.Partials._LayoutNavbarModel'.

我将_LayoutNavbar.cshtml和包含_LayoutNavbarModel PageModel的_LayoutNavbar.cshtaml.cs放在“共享/部分”文件夹中。

关于如何解决我的问题的任何建议?

编辑:我找到了一种解决方法,不是最好的方法,但这是一种解决方法。 创建类型为PageModel的_LayoutModel并在使用该导航栏的所有页面中继承它,您可以在正文中使用HomeModel,并在导航栏中的_LayoutModel中使用创建的对象。

总而言之,这是一个包含导航栏信息的类:

public class _LayoutModel: PageModel
{
    protected readonly UserManager<ApplicationUser> _userManager;
    protected readonly MyApp.Data.ApplicationDbContext _context;

    public _LayoutModel(UserManager<ApplicationUser> userManager,
        MyApp.Data.ApplicationDbContext context)
    {
        _userManager = userManager;
        _context = context;
    }

    public class NavbarModel
    {
        public string[] Names { get; set; }
    }

    [BindProperty]
    public NavbarModel Navbar { get; set; }

    public async Task<IActionResult> OnGetAsyncBase()
    {
        Navbar = new NavbarModel();

        Navbar.Names = new string[]{"me", "you", "him"};

        return Page();
    }
}

这是HomeModel的代码。它继承了_Layout模型并调用基本的OnGetAsync函数(嗯,在我的实际实现中,确实有异步要调用的东西,这只是一个例子):

public class HomeModel : _LayoutModel
{
    public HomeModel(UserManager<ApplicationUser> userManager,
        MyApp.Data.ApplicationDbContext context) : base(userManager, context)
    {
    }

    public class InputModel
    {
        [Required]
        [DataType(DataType.Text)]
        [Display(Name = "Manager Name")]
        public string ManagerName { get; set; }
    }

    [BindProperty]
    public InputModel Input { get; set; }

    public async Task<IActionResult> OnGetAsync()
    {
        await base.OnGetAsyncBase();

        Input = new InputModel();

        Input.ManagerName = "The Manager";

        return Page();
    }
} 

使用要使用的模型声明修改“布局”页面,并在PartialAsync调用中指定将模型传递给导航栏:

@model HomeModel

<div class="layout-wrapper layout">
  <div class="layout-inner">
    <!-- Layout navbar -->
    @await Html.PartialAsync("Shared/Partials/_LayoutNavbar", @Model.Navbar)

    <!-- Layout content -->
    <div class="layout-content">
      <!-- Content -->
      <div class="container-fluid">
        @RenderBody()
      </div>
    </div>
    <!-- Layout content -->
  </div>
  <!-- / Layout container -->
</div>

在导航栏中,只需在页面顶部添加模型,然后在其中调用对象即可:

@model _LayoutModel.NavbarModel

<!-- Layout navbar -->
<nav class="layout-navbar navbar">

  ...
  <span>@Model.Names[0]</span>
  ...
</nav>
<!-- / Layout navbar --> 

我希望有人知道更好的解决方案。

0 个答案:

没有答案