2009-06-03 13 views
81

Czy ktoś wie, jak można określić, czy z poziomu kontrolera istnieje określona nazwa widoku przed renderowaniem widoku?Czy istnieje widok w Asp.Net MVC?

Mam wymóg dynamicznego określania nazwy widoku do renderowania. Jeśli widok o tej nazwie istnieje, muszę renderować ten widok. Jeśli nie ma widoku według nazwy niestandardowej, muszę renderować widok domyślny.

Chciałbym zrobić coś podobnego do następującego kodu w moim kontrolera:

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

Dzięki.

+10

Po przeczytaniu tego tytułu wydaje się, że jest to bardzo głębokie pytanie filozoficzne. –

Odpowiedz

136
private bool ViewExists(string name) 
{ 
    ViewEngineResult result = ViewEngines.Engines.FindView(ControllerContext, name, null); 
    return (result.View != null); 
} 

Dla tych, którzy poszukują metody kopiuj/wklej rozszerzenie:

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

To chyba lepiej. Nie wiedziałem, że istnieje metoda FindView z samej kolekcji ViewEngines. –

+0

Wygląda na to, że to zadziała. Dzięki, Dave. –

+1

Ale jak sprawdzić, czy widok istnieje dla innego kontrolera? – SOReader

15

co próbuje coś jak następujące Zakładając, że używasz tylko jeden widok silnika:

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

wygląda tak, jak ten został opublikowany 3 minuty przed zaakceptowaną odpowiedzią, a jednak bez miłości ?! +1 ode mnie. –

+0

@ TrevordeKoekkoek ... hmmm ... + 1 –

2

jeśli chcesz ponownie użyć tego w wielu działaniach kontrolera, korzystając z rozwiązania podanego przez Dave'a, możesz zdefiniować niestandardowy wynik widoku w następujący sposób:

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

    ... 
} 

Następnie w swoim działaniu prostu wrócić instancję niestandardowego widoku:

public ActionResult Index() 
{ 
    return new CustomViewResult(); 
} 
5

Oto kolejny [niekoniecznie zalecane] sposób to zrobić

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

jest to testowanie istnienia częściowego widoku w plik .cshtml. tak naprawdę nie jest odpowiedzią na to pytanie, ale inne pytanie, które tutaj się łączyło, zostało niepoprawnie zamknięte, więc zostawiam tutaj odpowiedź –

+1

To było naprawdę na miejscu do mojego użytku, ponieważ szukałem sposobu na wykorzystanie specyficznej kultury częściowy widok. Tak właśnie nazwałem to z nazwą widoku specyficznego dla kultury, a następnie wywołałem domyślny widok wewnątrz catch.I robiłem to w funkcji użyteczności, więc nie miałem dostępu do 'ControllerContext', jak wymaga metoda' FindView'. – awe

+4

Kontrola przepływu oparta na wyjątkach to zapach kodu ... – ErikE

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

moje 2 centy.

Powiązane problemy