ASP.NET MVC에 뷰가 있습니까?


95

뷰를 렌더링하기 전에 컨트롤러 내에서 특정 뷰 이름이 있는지 확인할 수 있습니까?

렌더링 할 뷰의 이름을 동적으로 결정해야합니다. 해당 이름의 뷰가 있으면 해당 뷰를 렌더링해야합니다. 사용자 정의 이름으로보기가 없으면 기본보기를 렌더링해야합니다.

컨트롤러 내에서 다음 코드와 유사한 작업을 수행하고 싶습니다.

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

14
이것의 제목을 읽는 것만으로도 매우 깊은 철학적 질문처럼 보입니다.

답변:


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

2
이것은 아마도 더 좋습니다. ViewEngines 컬렉션 자체에 FindView 메서드가 있는지 몰랐습니다.
Lance Harper

1
그러나 다른 컨트롤러에 대한 뷰가 있는지 확인하는 방법은 무엇입니까?
SOReader 2013 년

제쳐두고 : 우리 엔지니어 중 한 명이 (이전 이후) 사용자 정의 뷰 엔진 (MultiTenantViewEngine이라고 부르기 때문에 목적을 알 수 있음)을 구축하여 주어진 것을 찾을 수없는 경우 HttpException (404)을 발생시키는 FindView를 구현 전망. 이것이 좋은 습관입니까? 나는 모른다. 그러나 이와 같은 다른 구현이 있다고해도 놀라지 않을 것입니다. 이 코드가 실행될 때 뷰 엔진의 내부 동작을 알 수 없기 때문에 catch {return false; }이 강아지 주변에서 안전을 위해.
Brian Colavito 2013 년

1
@SOReader, 나는 테스트했지만 IController 컨트롤러 = new HomeController (); 그런 다음 controller.ControllerContext는 findview 메소드에 전달할 수있는 것을 제공합니다.
Vishal Sharma

이 답변에 감사드립니다. 그것은 다른 문제에서 나를 도왔습니다. 내 뷰가 부분인지 아닌지 확인해야했고 모든 부분의 이름이 밑줄로 시작하므로 이제 내 솔루션으로 "result.View! = null"인지 확인할 수 있습니다.
Deise Vicentin

19

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

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

답변이 수락되기 3 분 전에 게시되었지만 아직 사랑이없는 것 같습니다! 나에게서 +1.
Trevor de Koekkoek

@TrevordeKoekkoek ... 흠 ... + 1
이씨 샤르마

8

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

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

이것은 .cshtml 파일 내에서 부분보기의 존재 여부를 테스트하기위한 것입니다. 그것은 여기에 링크가 잘못 닫힌 정말이 질문에 대한 대답,하지만 또 다른 질문하지 내가 여기 내 대답을 떠날거야 그래서
Simon_Weaver

2
문화 별 부분보기를 사용하는 방법을 찾고 있었기 때문에 이것은 실제로 내 사용에 적합했습니다. 그래서 문화 별 뷰 이름으로 이것을 호출 한 다음 catch 내부의 기본 뷰를 호출했습니다. 그리고 유틸리티 함수에서이 작업을 수행하고 있었기 때문에 메서드에 필요한 ControllerContext대로에 액세스 할 수 없었습니다 FindView.
경외

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

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

내 2 센트.


1

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


0

다음은 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)
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.