在渲染视图之前,是否可以确定控制器中是否存在特定的视图名称?
我需要动态确定要呈现的视图的名称。如果存在具有该名称的视图,那么我需要呈现该视图。如果自定义名称没有视图,那么我需要渲染默认视图。
我想在我的控制器中执行类似于以下代码的操作:
public ActionResult Index()
{
var name = SomeMethodToGetViewName();
// The 'ViewExists' method is what I've been unable to find.
if (ViewExists(name))
{
retun View(name);
}
else
{
return View();
}
}
答案 0 :(得分:147)
private bool ViewExists(string name)
{
ViewEngineResult result = ViewEngines.Engines.FindView(ControllerContext, name, null);
return (result.View != null);
}
对于那些寻找复制/粘贴扩展方法的人:
public static class ControllerExtensions
{
public static bool ViewExists(this Controller controller, string name)
{
ViewEngineResult result = ViewEngines.Engines.FindView(controller.ControllerContext, name, null);
return (result.View != null);
}
}
答案 1 :(得分:18)
假设您只使用一个视图引擎,那么尝试以下内容会怎么样:
bool viewExists = ViewEngines.Engines[0].FindView(ControllerContext, "ViewName", "MasterName", false) != null;
答案 2 :(得分:7)
这是另一种[不一定推荐]的做法
try
{
@Html.Partial("Category/SearchPanel/" + Model.CategoryKey)
}
catch (InvalidOperationException) { }
答案 3 :(得分:2)
如果要在多个控制器操作之间重复使用它,在Dave提供的解决方案的基础上,您可以按如下方式定义自定义视图结果:
public class CustomViewResult : ViewResult
{
protected override ViewEngineResult FindView(ControllerContext context)
{
string name = SomeMethodToGetViewName();
ViewEngineResult result = ViewEngines.Engines.FindView(context, name, null);
if (result.View != null)
{
return result;
}
return base.FindView(context);
}
...
}
然后在您的操作中,只需返回自定义视图的实例:
public ActionResult Index()
{
return new CustomViewResult();
}
答案 4 :(得分:1)
ViewEngines.Engines.FindView(ViewContext.Controller.ControllerContext, "View Name").View != null
我的2美分。
答案 5 :(得分:0)
在asp.net core 2.x中,ViewEngines
属性不再存在,因此我们必须使用ICompositeViewEngine
服务。这是使用依赖注入的已接受答案的变体:
public class DemoController : Controller
{
private readonly IViewEngine _viewEngine;
public DemoController(ICompositeViewEngine viewEngine)
{
_viewEngine = viewEngine;
}
private bool ViewExists(string name)
{
ViewEngineResult viewEngineResult = _viewEngine.FindView(ControllerContext, name, true);
return viewEngineResult?.View != null;
}
public ActionResult Index() ...
}
出于好奇:基本接口IViewEngine
未注册为服务,因此我们必须注入ICompositeViewEngine
。 FindView()
提供了IViewEngine
方法,因此成员变量可以使用基本接口。
答案 6 :(得分:0)
这是在Razor for Core 2.2等中执行此操作的方法。请注意,调用是“ GetView”,而不是“ Find View”
@using Microsoft.AspNetCore.Mvc.ViewEngines
@inject ICompositeViewEngine Engine
...
@if (Engine.GetView(scriptName, scriptName, isMainPage: false).Success)
{
@await Html.PartialAsync(scriptName)
}