Does a view exist in ASP.NET MVC?

asp.net Mvc

asp.net Mvc Problem Overview


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 of the view to render. If a view exists with that name then I need to render that view. If there is no view by the custom name then I need to render a default view.

I'd like to do something similar to the following code within my controller:

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 Solutions


Solution 1 - asp.net Mvc

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

Solution 2 - asp.net Mvc

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;

Solution 3 - asp.net Mvc

Here's another [not necessarily recommended] way of doing it

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

Solution 4 - asp.net Mvc

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

Solution 5 - asp.net Mvc

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.

Solution 6 - asp.net Mvc

ViewEngines.Engines.FindView(ViewContext.Controller.ControllerContext, "View Name").View != null

My 2 cents.

Solution 7 - asp.net Mvc

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAndrew HansonView Question on Stackoverflow
Solution 1 - asp.net MvcDave CluderayView Answer on Stackoverflow
Solution 2 - asp.net MvcLance HarperView Answer on Stackoverflow
Solution 3 - asp.net MvcSimon_WeaverView Answer on Stackoverflow
Solution 4 - asp.net MvcDSOView Answer on Stackoverflow
Solution 5 - asp.net MvcidilovView Answer on Stackoverflow
Solution 6 - asp.net MvctynarView Answer on Stackoverflow
Solution 7 - asp.net MvcphilwView Answer on Stackoverflow