【问题标题】:Does a view exist in ASP.NET MVC?ASP.NET MVC 中是否存在视图?
【发布时间】:2010-10-31 03:00:57
【问题描述】:

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

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

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

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

【问题讨论】:

  • 光看这个标题,似乎是一个很深奥的哲学问题。

标签: asp.net-mvc


【解决方案1】:
 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);
    }
}

【讨论】:

  • 这可能更好。我不知道 ViewEngines 集合本身有一个 FindView 方法。
  • 但是如何检查其他控制器的视图是否存在?
  • 顺便说一句:我们的一位工程师(此后继续前进)构建了一个自定义视图引擎(称为 MultiTenantViewEngine,因此您可以了解它的用途),该引擎实现 FindView 以抛出 HttpException (404)如果它找不到给定的视图。这是好习惯吗?我不知道。但是,如果有其他类似的实现,也不会感到惊讶。由于在执行此代码时您不会知道视图引擎的内部工作原理,因此您可能需要抛出 catch { return false; 。 } 围绕这只小狗,只是为了安全。
  • @SOReader,我已经测试过了,但是,IController controller = new HomeController();然后 controller.ControllerContext 会给你可以传递给 findview 方法的东西。
  • 感谢您的回答。它帮助我解决了另一个问题。我需要检查我的视图是否是部分视图,因为我的所有部分名称都以下划线开头,现在我可以使用我的解决方案检查“result.View!= null”
【解决方案2】:

假设您只使用一个视图引擎,尝试以下类似的方法会怎样:

bool viewExists = ViewEngines.Engines[0].FindView(ControllerContext, "ViewName", "MasterName", false) != null;

【讨论】:

  • 看起来这个是在接受答案前 3 分钟发布的,但没有爱?!来自我的 +1。
  • @TrevordeKoekkoek ...嗯...+1
【解决方案3】:

这是另一种 [不一定推荐] 的做法

 try
 {
     @Html.Partial("Category/SearchPanel/" + Model.CategoryKey)
 }
 catch (InvalidOperationException) { }

【讨论】:

  • 这是为了测试 .cshtml 文件中部分视图的存在。这不是这个问题的真正答案,但另一个问题是此处的链接被错误关闭,所以我将答案留在这里
  • 这实际上是供我使用的,因为我正在寻找一种方法来使用特定于文化的局部视图。所以我只是用特定于文化的视图名称来调用它,然后在 catch 中调用默认视图。而且我是在实用程序函数中执行此操作的,因此我无法访问 ControllerContext 作为 FindView 方法需要的权限。
【解决方案4】:

如果您想在多个控制器操作中重复使用它,基于 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();
}

【讨论】:

    【解决方案5】:
    ViewEngines.Engines.FindView(ViewContext.Controller.ControllerContext, "View Name").View != null
    

    我的 2 美分。

    【讨论】:

      【解决方案6】:

      在 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 提供,因此成员变量可以使用基接口。

      【讨论】:

        【解决方案7】:

        这是在 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)
        }
        

        【讨论】:

          猜你喜欢
          • 2023-04-04
          • 1970-01-01
          • 2018-05-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-01-23
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多