【问题标题】:How to check whether ViewComponent View exists?如何检查 ViewComponent 视图是否存在?
【发布时间】:2021-09-23 06:29:15
【问题描述】:

有没有办法在尝试渲染之前检查 ViewComponent 的 View 是否真的存在?

我知道有 FindViewGetView 方法可用于搜索视图,例如控制器,我正在为 ViewComponents 寻找类似的东西。

ViewComponent 内部,有一个 ViewEngine,但是当我尝试使用它时...

ViewEngine.FindView(ViewContext, "SomeView", false);

... 结果的 SearchedLocations 不是在寻找 ViewComponents:

[0]: "/Views/Home/SomeView.en-US.cshtml"
[1]: "/Views/Home/SomeView.en.cshtml"
[2]: "/Views/Home/SomeView.cshtml"
[3]: "/Views/Shared/SomeView.en-US.cshtml"
[4]: "/Views/Shared/SomeView.en.cshtml"
[5]: "/Views/Shared/SomeView.cshtml"
[6]: "/Pages/Shared/SomeView.en-US.cshtml"
[7]: "/Pages/Shared/SomeView.en.cshtml"
[8]: "/Pages/Shared/SomeView.cshtml"

注意: 问这个问题是因为 try-catch 块没有捕捉到缺少视图时发生的异常,例如...

public IViewComponentResult Invoke()
{      
    try
    {
        return View();
    }
    catch (Exception e)
    {
        return Content(string.Empty);
    }
}

...由于缺少视图文件,会导致未处理的异常。

【问题讨论】:

    标签: c# asp.net-core-2.1 view-components


    【解决方案1】:

    如您所见hereViewComponentResult.ViewComponent 方法使用在类顶部声明的硬编码值构建所需视图的路径。 所以在内部,对ViewEngine.FindView 的调用是通过将所需视图的相对路径作为视图名称传递的,即Components/{ComponentName}/{ViewName}。然后,视图引擎使用您在示例中看到的路径作为基础搜索此路径。

    要回答你的问题,你应该编辑你的代码来做同样的事情,所以它应该是

    ViewEngine.FindView(ViewContext, "Components/ViewComponentName/SomeView", false);
    

    Example 用于放置在/Views/Shared/Components/Navigation/Default.cshtml 中的视图。

    【讨论】:

    • 你说的是真的,但是......我一直在使用上面的代码和 View("SomeView") 并检查路径 Components/ViewComponentName/ 路径,因为 ViewComponents 检查默认值路径也是如此。对我来说奇怪的是 ViewEngine.FindView 根本不检查该路径。
    • 此外,由于我已经扩展了视图引擎的视图搜索路径(将一些视图文件存储在实际项目之外)并且渲染这些视图没有问题,我正在寻找类似的FindView 的解决方案。如果没有其他方法可以像上面显示的那样定义路径,我想我必须对每个 ViewComponent 进行硬编码。
    • 您是否尝试过使用services.Configure<RazorViewEngineOptions>(...来配置引擎的搜索路径行为?
    • 我做到了,而且效果很好。就像我说的,我使用 View("SomeView") 为 ViewComponent 渲染视图没有问题,因为我已经扩展了搜索引擎的搜索路径。对我来说唯一的问题是 ViewEngine.FindView 似乎忽略了该配置,因此我必须在路径中使用“Components/ViewComponentName/”。这不是一个大问题,但它不是动态的,我必须用硬编码的字符串来包装它。
    • 对不起,我不明白你已经这样做了。无论如何,我认为鉴于这种情况,至少对路径的Components/ 部分进行硬编码是不可避免的,因为 AspNetCore 自己会这样做。但是为了避免每次都写组件的名称,我认为您可以创建一个继承自 ViewComponentBaseViewComponent 类,并在创建新的 ViewComponent 时将其子类化。在那里,您可以创建一个方便的方法,该方法自动构建到 Components/{Component Name}/ 文件夹的路径并使用构建的路径调用 ViewEngine.FindView
    【解决方案2】:

    您可以将IViewComponentSelector 注入您的控制器以检查组件是否存在:

    控制器:

    private readonly IViewComponentSelector _selector;
            public HomeController(IViewComponentSelector selector)
            {
                _selector = selector;
            }
    public IActionResult Index()
            {
                if (_selector.SelectComponent("CheckBox1") != null)
                {
                    return Ok("exist");
                }
                else 
                {
                    return Ok("Not Found");
                }
            }
    

    结果(ViewComponent 名称为 CheckBox):

    【讨论】:

      猜你喜欢
      • 2023-03-23
      • 1970-01-01
      • 2014-06-08
      • 1970-01-01
      • 2011-07-17
      • 2020-03-02
      • 1970-01-01
      • 2010-11-21
      • 1970-01-01
      相关资源
      最近更新 更多