ASP.NET Core 5.0 MVC:使用 Html.RenderAction 时出现 CS1061 错误
ASP.NET Core 5.0 MVC : CS1061 error using Html.RenderAction
我正在开发一个使用 ASP.NET Core 5.0 构建 Web 应用程序 (MVC) 的项目。我尝试使用 Html.RenderAction
扩展方法,但出现以下错误。
编译错误:
Html.RenderAction CS1061: IHtmlHelper<dynamic> does not contain a definition for 'RenderAction'
我做错了什么?
为了提供更多上下文,我想使用直接从数据库加载的数据在 _Layout.cshtml
中呈现部分视图。
这是我_Layout.cshtml
的内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384- EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
<link rel="stylesheet" href="~/dist/css/main.css" media="all" />
<title>@ViewData["Title"]: my webpage</title>
</head>
<body id="body">
<!-- Header -->
<header id="header">
<!-- Navigation -->
<nav id="nav">
<partial name="../Shared/Components/_navBar.cshtml" />
<partial name="../Shared/Components/_headerSearchBar.cshtml" />
</nav>
@{ Html.RenderAction("GetCategories"); }
</header>
<!-- Main -->
<main role="main" class="main-wrapper">
<div class="home main-content">
@RenderBody()
</div>
</main>
<!-- Footer -->
<footer class="footer">
<partial name="../Shared/Components/_footer.cshtml" />
</footer>
<script src="~/js/script.js" asp-append-version="true"></script>
@*<script src="~/js/scriptanim.js" asp-append-version="true"></script>*@
@await RenderSectionAsync("Scripts", required: false)
</body>
</html>
这是控制器中将数据加载到局部视图的操作方法
public async Task<IActionResult> GetCategories()
{
var categories = await _fashionBuyRepository.GetAllCategoriesAsync();
return PartialView("_productCategoriesHeader", categories);
}
据我所知,在 .NET 5 中,@Html.RenderAction
不再有效。
我相信你可以使用
@await Html.PartialAsync("GetCategories")
或
@await Html.RenderPartialAsync("GetCategories")
而不是它。可能还有其他选项,请查看 .NET 文档。
有几种方法可以做到这一点。其中之一使用组件。但它需要一些 javascript 代码才能使用它
另一种更简单的新手方法,您必须创建一个基础视图模型,您必须将其用于所有使用此布局的视图
using Microsoft.AspNetCore.Mvc.Rendering;
public interface IBaseViewModel
{
int CategoryId { get; set; }
List<Category> Categories{ get; set; }
}
public class BaseViewModel : IBaseViewModel
{
public int CategoryId { get; set; }
public List<Category> Categories { get; set; }
}
动作
public async Task<IActionResult> Index()
{
var baseViewModel=new BaseViewModel();
baseViewModel.Categories= await _fashionBuyRepository.GetAllCategoriesAsync();
return View(baseViewModel);
}
在局部视图中使用此模型
@model BaseViewModel
布局
@model IBaseViewModel // you can omit it but I like to have it explicitly
@if(Model!=null && Model.Categories!=null && Model.Categories.Count > 0)
{
<partial name="_productCategoriesHeader" />
}
对于另一个视图,您可以创建此操作代码
public IActionResult MyAction()
var myActionViewModel= new MyActionViewModel {
..... your init code
}
InitBaseViewModel(myActionViewModel);
return View(myActionViewModel)
}
public class MyActionViewModel : BaseViewModel
//or
public class MyActionViewModel : IBaseViewModel
{
public .... {get; set;}
}
我采用了@Michael 建议的 ViewComponent 方法来解决这个问题,这对我来说是最佳的。
我在 Components 文件夹中创建了一个 CategoriesViewComponent,如下所示:
using eFashionBuy.Repository;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace eFashionBuy.Components
{
public class CategoriesViewComponent : ViewComponent
{
private readonly IFashionBuyRepository _fashionBuyRepository;
public CategoriesViewComponent(IFashionBuyRepository fashionBuyRepository)
{
_fashionBuyRepository = fashionBuyRepository;
}
public async Task<IViewComponentResult> InvokeAsync()
{
var categories = await _fashionBuyRepository.GetAllCategoriesAsync();
return View(categories);
}
}
}
与此组件关联的视图在位置 /Shared/Components/Categories/Default.cshtml 中称为 Default.cshtml(局部视图),如下所示:
@model IEnumerable<Category>;
@* Product Categories mobile menu *@
@foreach (var category in Model)
{
<li class="categories__item">
<a class="categories-link"
asp-controller="Catgeories"
asp-action="Category"
asp-route-id="@category.CategoryID"
asp-route-category="@category.CategoryName">
<span>@category.CategoryName</span>
</a>
</li>
}
组件现在可以使用了。我只是简单地在我想使用它的地方如下调用它
<ul class="categories__items">
<!-- This is how I call the component using TagHelper -->
<vc:categories />
</ul>
这帮助我避免了 RenderAction 的大部分细微差别,这是我最初的方法。我将利用这些知识来简化未来的设计。
我正在开发一个使用 ASP.NET Core 5.0 构建 Web 应用程序 (MVC) 的项目。我尝试使用 Html.RenderAction
扩展方法,但出现以下错误。
编译错误:
Html.RenderAction CS1061: IHtmlHelper<dynamic> does not contain a definition for 'RenderAction'
我做错了什么?
为了提供更多上下文,我想使用直接从数据库加载的数据在 _Layout.cshtml
中呈现部分视图。
这是我_Layout.cshtml
的内容<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384- EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
<link rel="stylesheet" href="~/dist/css/main.css" media="all" />
<title>@ViewData["Title"]: my webpage</title>
</head>
<body id="body">
<!-- Header -->
<header id="header">
<!-- Navigation -->
<nav id="nav">
<partial name="../Shared/Components/_navBar.cshtml" />
<partial name="../Shared/Components/_headerSearchBar.cshtml" />
</nav>
@{ Html.RenderAction("GetCategories"); }
</header>
<!-- Main -->
<main role="main" class="main-wrapper">
<div class="home main-content">
@RenderBody()
</div>
</main>
<!-- Footer -->
<footer class="footer">
<partial name="../Shared/Components/_footer.cshtml" />
</footer>
<script src="~/js/script.js" asp-append-version="true"></script>
@*<script src="~/js/scriptanim.js" asp-append-version="true"></script>*@
@await RenderSectionAsync("Scripts", required: false)
</body>
</html>
这是控制器中将数据加载到局部视图的操作方法
public async Task<IActionResult> GetCategories()
{
var categories = await _fashionBuyRepository.GetAllCategoriesAsync();
return PartialView("_productCategoriesHeader", categories);
}
据我所知,在 .NET 5 中,@Html.RenderAction
不再有效。
我相信你可以使用
@await Html.PartialAsync("GetCategories")
或
@await Html.RenderPartialAsync("GetCategories")
而不是它。可能还有其他选项,请查看 .NET 文档。
有几种方法可以做到这一点。其中之一使用组件。但它需要一些 javascript 代码才能使用它
另一种更简单的新手方法,您必须创建一个基础视图模型,您必须将其用于所有使用此布局的视图
using Microsoft.AspNetCore.Mvc.Rendering;
public interface IBaseViewModel
{
int CategoryId { get; set; }
List<Category> Categories{ get; set; }
}
public class BaseViewModel : IBaseViewModel
{
public int CategoryId { get; set; }
public List<Category> Categories { get; set; }
}
动作
public async Task<IActionResult> Index()
{
var baseViewModel=new BaseViewModel();
baseViewModel.Categories= await _fashionBuyRepository.GetAllCategoriesAsync();
return View(baseViewModel);
}
在局部视图中使用此模型
@model BaseViewModel
布局
@model IBaseViewModel // you can omit it but I like to have it explicitly
@if(Model!=null && Model.Categories!=null && Model.Categories.Count > 0)
{
<partial name="_productCategoriesHeader" />
}
对于另一个视图,您可以创建此操作代码
public IActionResult MyAction()
var myActionViewModel= new MyActionViewModel {
..... your init code
}
InitBaseViewModel(myActionViewModel);
return View(myActionViewModel)
}
public class MyActionViewModel : BaseViewModel
//or
public class MyActionViewModel : IBaseViewModel
{
public .... {get; set;}
}
我采用了@Michael 建议的 ViewComponent 方法来解决这个问题,这对我来说是最佳的。
我在 Components 文件夹中创建了一个 CategoriesViewComponent,如下所示:
using eFashionBuy.Repository;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace eFashionBuy.Components
{
public class CategoriesViewComponent : ViewComponent
{
private readonly IFashionBuyRepository _fashionBuyRepository;
public CategoriesViewComponent(IFashionBuyRepository fashionBuyRepository)
{
_fashionBuyRepository = fashionBuyRepository;
}
public async Task<IViewComponentResult> InvokeAsync()
{
var categories = await _fashionBuyRepository.GetAllCategoriesAsync();
return View(categories);
}
}
}
与此组件关联的视图在位置 /Shared/Components/Categories/Default.cshtml 中称为 Default.cshtml(局部视图),如下所示:
@model IEnumerable<Category>;
@* Product Categories mobile menu *@
@foreach (var category in Model)
{
<li class="categories__item">
<a class="categories-link"
asp-controller="Catgeories"
asp-action="Category"
asp-route-id="@category.CategoryID"
asp-route-category="@category.CategoryName">
<span>@category.CategoryName</span>
</a>
</li>
}
组件现在可以使用了。我只是简单地在我想使用它的地方如下调用它
<ul class="categories__items">
<!-- This is how I call the component using TagHelper -->
<vc:categories />
</ul>
这帮助我避免了 RenderAction 的大部分细微差别,这是我最初的方法。我将利用这些知识来简化未来的设计。