Does a view exist in ASP.NET MVC?

前端 未结 7 706
粉色の甜心
粉色の甜心 2020-11-28 09:59

Is it possible to determine if a specific view name exists from within a controller before rendering the view?

I have a requirement to dynamically determine the name

相关标签:
7条回答
  • 2020-11-28 10:37

    In asp.net core 2.x the ViewEngines property no longer exists so we have to use the ICompositeViewEngine service. This a variant of the accepted answer using dependency injection:

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

    For the curious: The base interface IViewEngine is not registered as a service so we must inject ICompositeViewEngine instead. The FindView() method however is provided by IViewEngine so the member variable may use the base interface.

    0 讨论(0)
  • 2020-11-28 10:38
     private bool ViewExists(string name)
     {
         ViewEngineResult result = ViewEngines.Engines.FindView(ControllerContext, name, null);
         return (result.View != null);
     }
    

    For those looking for a copy/paste extension method:

    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);
        }
    }
    
    0 讨论(0)
  • 2020-11-28 10:41

    What about trying something like the following assuming you are using only one view engine:

    bool viewExists = ViewEngines.Engines[0].FindView(ControllerContext, "ViewName", "MasterName", false) != null;
    
    0 讨论(0)
  • 2020-11-28 10:41
    ViewEngines.Engines.FindView(ViewContext.Controller.ControllerContext, "View Name").View != null
    

    My 2 cents.

    0 讨论(0)
  • 2020-11-28 10:50

    If you want to re-use this across multiple controller actions, building on the solution given by Dave, you can define a custom view result as follows:

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

    Then in your action simply return an instance of your custom view:

    public ActionResult Index()
    { 
        return new CustomViewResult();
    }
    
    0 讨论(0)
  • 2020-11-28 10:56

    Here's how to do it in Razor for Core 2.2 etc. Note that the call is "GetView", not "Find View)

    @using Microsoft.AspNetCore.Mvc.ViewEngines
    @inject ICompositeViewEngine Engine
    ...
    @if (Engine.GetView(scriptName, scriptName, isMainPage: false).Success) 
    {
        @await Html.PartialAsync(scriptName)
    }
    
    0 讨论(0)
提交回复
热议问题