问题描述
有没有办法在尝试渲染之前检查 ViewComponent 的视图是否确实存在?
我知道有 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);
}
}
... 会因为缺少视图文件而导致未处理的异常。
解决方法
如您所见,here ViewComponentResult.ViewComponent
方法使用在类顶部声明的硬编码值构建所需视图的路径。
因此,在内部,对 ViewEngine.FindView
的调用将作为视图名称传递到所需视图的相对路径,即 Components/{ComponentName}/{ViewName}
。然后,视图引擎使用您在示例中看到的路径作为基础搜索此路径。
要回答你的问题,你应该编辑你的代码来做同样的事情,所以它应该是
ViewEngine.FindView(ViewContext,"Components/ViewComponentName/SomeView",false);
Example 用于放置在 /Views/Shared/Components/Navigation/Default.cshtml
中的视图。
您可以将 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");
}
}