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)
}