[asp.net-mvc] 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();
    }
}



답변

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


답변

하나의 뷰 엔진 만 사용한다고 가정하고 다음과 같은 것을 시도하는 것은 어떻습니까?

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


답변

[반드시 권장되는 것은 아님] 또 다른 방법이 있습니다.

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


답변

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


답변

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

내 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되므로 멤버 변수가 기본 인터페이스를 사용할 수 있습니다.


답변

다음은 Core 2.2 용 Razor에서 수행하는 방법입니다. 호출은 “Find View”가 아니라 “GetView”입니다.

@using Microsoft.AspNetCore.Mvc.ViewEngines
@inject ICompositeViewEngine Engine
...
@if (Engine.GetView(scriptName, scriptName, isMainPage: false).Success)
{
    @await Html.PartialAsync(scriptName)
}