Asp.net mvc ASP.NET MVC中是否存在视图?
在呈现视图之前,是否可以确定控制器中是否存在特定的视图名称 我需要动态确定要渲染的视图的名称。如果存在具有该名称的视图,则需要渲染该视图。如果没有自定义名称的视图,则需要渲染默认视图 我想在控制器中执行类似于以下代码的操作:Asp.net mvc ASP.NET MVC中是否存在视图?,asp.net-mvc,Asp.net Mvc,在呈现视图之前,是否可以确定控制器中是否存在特定的视图名称 我需要动态确定要渲染的视图的名称。如果存在具有该名称的视图,则需要渲染该视图。如果没有自定义名称的视图,则需要渲染默认视图 我想在控制器中执行类似于以下代码的操作: public ActionResult Index() { var name = SomeMethodToGetViewName(); // The 'ViewExists' method is what I've been unable to find.
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();
}
}
假设您只使用一个视图引擎,那么尝试以下方法如何:
bool viewExists = ViewEngines.Engines[0].FindView(ControllerContext, "ViewName", "MasterName", false) != 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);
}
}
如果要在多个控制器操作中重复使用此功能,请基于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();
}
这里有另一种(不一定推荐)方法
try
{
@Html.Partial("Category/SearchPanel/" + Model.CategoryKey)
}
catch (InvalidOperationException) { }
我的2美分。在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
提供的,因此成员变量可以使用基本接口。以下是如何在Razor for Core 2.2等中执行此操作。请注意,调用是“GetView”,而不是“Find View”)
这可能更好。我不知道ViewEngines集合本身有一个FindView方法。但是如何检查其他控制器是否存在该视图?有点旁敲侧击:我们的一位工程师(后来)构建了一个自定义视图引擎(称为MultiTenantViewEngine,因此您可以了解它的用途)这实现了FindView,如果找不到给定的视图,就会抛出一个HttpException(404)。这是一个好的实践吗?我不知道。但是如果有其他类似的实现,也不会感到惊讶。因为在执行这段代码时,您不知道视图引擎的内部工作,所以您可能想要抛出一个catch{return false;}为了安全起见,在这只小狗周围。@SOReader,我没有测试过,但是,IController controller=new HomeController();然后controller.ControllerContext将提供您可以传递给findview方法的内容。感谢您的回答。它帮助我解决了另一个问题。我需要检查我的视图是否为部分视图,并且由于我的所有部分名称都以下划线开头,现在我可以使用解决方案检查“result.view!”无效的“看起来这张照片是在被接受的答案3分钟前贴出来的,但是没有爱情?!”+1从我这里。@TrevordeKoekkoek…hmmm…+1这用于测试.cshtml文件中是否存在部分视图。这并不是这个问题的答案,而是另一个问题,这里的链接被错误地关闭了,所以我把我的答案留在这里,这实际上是供我使用的,因为我正在寻找一种使用特定于文化的局部视图的方法。所以我只是用特定于区域性的视图名来调用它,然后在catch中调用默认视图。我是在一个实用函数中做这件事的,所以我无法访问
ControllerContext
,因为FindView
方法需要它。仅仅阅读这个标题,它似乎是一个非常深刻的哲学问题。
ViewEngines.Engines.FindView(ViewContext.Controller.ControllerContext, "View Name").View != null
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() ...
}
@using Microsoft.AspNetCore.Mvc.ViewEngines
@inject ICompositeViewEngine Engine
...
@if (Engine.GetView(scriptName, scriptName, isMainPage: false).Success)
{
@await Html.PartialAsync(scriptName)
}