如何检查 ViewComponent 视图是不是存在?
Posted
技术标签:
【中文标题】如何检查 ViewComponent 视图是不是存在?【英文标题】:How to check whether ViewComponent View exists?如何检查 ViewComponent 视图是否存在? 【发布时间】:2021-09-23 06:29:15 【问题描述】:有没有办法在尝试渲染之前检查 ViewComponent 的 View 是否真的存在?
我知道有 FindView 和 GetView 方法可用于搜索视图,例如控制器,我正在为 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);
...由于缺少视图文件,会导致未处理的异常。
【问题讨论】:
【参考方案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 自己会这样做。但是为了避免每次都写组件的名称,我认为您可以创建一个继承自 ViewComponent
的 BaseViewComponent
类,并在创建新的 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):
【讨论】:
以上是关于如何检查 ViewComponent 视图是不是存在?的主要内容,如果未能解决你的问题,请参考以下文章
.NET CORE 从控制器调用 ViewComponent