如何在 Asp.net 核心的 ViewComponent 之间共享 ViewData

How share ViewData between ViewComponent in Asp.net core

我有两个 ViewComponent,我想使用 ViewData 或其他技术在它们之间共享一些数据,然后在主视图中使用这些数据,但这不是方法,并且当满足 if 条件时,每个 ViewComponent 的 ViewData 为 null两个 ViewComponent.

public class OneViewComponent : ViewComponent
{
    public async Task<IViewComponentResult> InvokeAsync(Page page, Zone zone)
    {
        //some operation

        string text = "one";

        if(ViewData["data"] != null)
        {
            ViewData["data"] = ViewData["data"].ToString() + text;
        }
        else
        {
            ViewData["data"] = text;
        }

        return View();
    }
}

public class TwoViewComponent : ViewComponent
{
    public async Task<IViewComponentResult> InvokeAsync(Page page, Zone zone)
    {
        //some operation

        string text = "two";

        if(ViewData["data"] != null)
        {
            ViewData["data"] = ViewData["data"].ToString() + text;
        }
        else
        {
            ViewData["data"] = text;
        }

        return View();
    }
}

ViewData 就像 ViewBag。仅当您要将数据从 Controller 传输到 View 时才使用它。为此,我总是更喜欢视图模型。

要跨组件传输数据,您有以下两种选择:

使用TempData字典代替ViewData字典:您需要安装以下包

Install-Package Microsoft.AspNetCore.Mvc.ViewFeatures

在您的 Startup class 中,添加此行

services.AddSingleton<ITempDataProvider, CookieTempDataProvider>();

到您的 ConfigureServices 方法。我使用 CookieTempDataProvider 作为 ITempDataProvider 的实现,但您可以使用 SessionStateTempDataProvider.

要将数据存储到 TempData 字典中,您可以使用以下代码:

this.TempData["data"] = "my value";

要从 TempData 检索数据,您可以使用此代码:

var data = this.TempData["data"];

要在您的组件视图中使用它:

@this.TempData["data"]

使用HttpContext.Items字典:没有要安装的包。在您的视图组件 class 中,将您的数据存储在 HttpContext.Items 字典中,如下所示:

this.HttpContext.Items["data"] = "my value"; 

并访问存储的数据:

var data = this.HttpContext.Items["data"];

在您的组件视图中,您可以通过这样做来获取存储的数据:

@this.Context.Items["data"]

TempDataHttpContext.Items的区别:HttpContext.ItemsTempData字典的主要区别是:

  • HttpContext.Items请求结束时清空
  • 默认TempData读取数据时清零。要保留您需要显式调用 TempData.Keep()
  • 的数据
  • 当你使用 TempData 时,你可以很容易地测试你的视图组件,因为它是一个类型 ITempDataDictionary 的接口,可以毫无困难地模拟。

恕我直言,这表明 ViewComponent 不适合您的用例。您应该改用部分视图。

部分视图在其父视图操作的上下文中执行,另外您可以将模型传递给部分视图,即产品列表中的产品。

@Html.Partial("PartialName", customViewData)

在上面的示例中,您将提供 "one""two" 作为局部模型参数 @Html.Partial("PartialName", "one")@Html.Partial("PartialName", "two")

ViewComponents 更像是可重用的逻辑块 和 view,它们的行为类似于控制器 + 操作。 但与控制器 + 操作不同,ViewComponent 可以在多个地方重复使用。

ViewComponents 应该是自给自足的,不依赖于它们之外的数据。

这也进一步表明您正在尝试将与应用程序相关的逻辑从操作移动到视图,并且来自控制器操作的数据没有为视图使用做好充分准备。

控制器的操作只有 3 个简单的任务:验证用户输入、调用底层应用程序代码(通常称为服务)并准备服务结果供视图使用。也就是说,更好的解决方案可能是在您的操作中使用视图模型(而不是 ViewData 未类型化),准备您需要的所有数据,然后让视图只显示该数据。