ASP.NET MVC中是否存在视图?

时间:2009-06-03 20:21:11

标签: asp.net-mvc

在渲染视图之前,是否可以确定控制器中是否存在特定的视图名称?

我需要动态确定要呈现的视图的名称。如果存在具有该名称的视图,那么我需要呈现该视图。如果自定义名称没有视图,那么我需要渲染默认视图。

我想在我的控制器中执行类似于以下代码的操作:

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

7 个答案:

答案 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未注册为服务,因此我们必须注入ICompositeViewEngineFindView()提供了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)
}