2013-08-13 12 views
11

Mam układ maszynki jak:Jaka jest kolejność wykonywania w MVC Razor view/układ

@using (var context = SetUpSomeContext()) { 
    <div> 
     Some content here 
     @RenderBody(); 
    </div> 
} 

i widok jak:

@{ 
    Layout = "MyLayout.cshtml"; 
} 
<div>@SomethingThatDependsOnContextBeingSetUp()</div> 

Gdy widok sprawia, SomethingThatDependsOnContextBeingSetUp wykonuje przed SetUpSomeContext i zawiedzie. Wydaje się to dziwne, ponieważ spodziewałem się, że nie wykona się, dopóki nie zostanie wywołany RenderBody w układzie. Kiedy przełączam to, aby użyć sekcji "PageContent" zamiast RenderBody, wszystko działa zgodnie z oczekiwaniami. Czy ktoś może wyjaśnić to zachowanie?

+0

Moja odpowiedź wyjaśnia to zachowanie, co pozostało do rozwiązania? – MstfAsan

Odpowiedz

2

Kolejność wykonywania jest od najbardziej wewnętrznej do najbardziej zewnętrznej.

Twierdzę, że używanie "kontekstu" w sposobie, w jaki go używasz, nie jest najlepszym projektem - należy rozważyć przeniesienie konfiguracji do kontrolera/filtra akcji i przekazanie danych do widoków w modelu.

+0

Ale sekcje nie przestrzegają tej zasady? Ponadto, moim powodem tego podejścia jest to, że chcę włączyć niektóre wspólne funkcje renderowania bez konieczności każdej metody kontrolera, aby zmienić sposób wywołania metody View(). – ChaseMedallion

0

Jeśli potrzebujesz logiki we wszystkich swoich widokach, utwórz ViewModelBase, z której odziedziczy wszystkie twoje ViewModel.

Następnie w swoim Controller(Base) można zainicjować ViewModel.SharedContext i inne właściwości.

+0

Nie chcę tej logiki we WSZYSTKICH widokach, tylko na pełnych stronach. Czy nadal zaleca się korzystanie z ViewModelBase przez układ tego? Ponadto, w jaki sposób mogę uruchomić kod na początku i na końcu widoku przy użyciu tej techniki (np. Utworzyć kontekst, a następnie wyrzucić go)? – ChaseMedallion

+0

@ W jakim kontekście mówisz? Biorąc pod uwagę problemy, na które napotykasz, sugerowałbym rozwiązanie tego na innym poziomie, tak jak powiedziałem na przykład przy użyciu udostępnionego ViewModel. – CodeCaster

3

Pozwolę sobie wyjaśnić to przez zbadanie sytuacji, Załóżmy, że masz widok podobny;

@renderSection("Header") 
    @using (var context = SetUpSomeContext()) { 
     <div> 
      Some content here 
      @RenderBody(); 
     </div> 
    } 
    @renderSection("Footer") 

Zakładamy, że brzytwa wykonuje stronę w kolejności, jakiej się spodziewasz, co by się stało, gdybyśmy ogłosili nasz widok?

@{ 
    Layout = null; 
} 
<div>@SomethingThatDependsOnContextBeingSetUp()</div> 

Razor nie mają pojęcia, czy widok potrzebuje układ strony aż do wykonywania @RenderBody() .Również byłoby wywnioskować, że układ strony renderowane za nic, a to nie byłoby to reasonable.So nie, co tak naprawdę się dzieje.

Na żądanie jest tak naturalne, że Razor najpierw wykonuje ciało twojego widoku. Jeśli twój widok nie jest określony, jak w moim demo Razor renderuje tylko wydruk tej strony i zatrzymuje się tam. Jeśli widok ma układ określony w kodzie po przejściu do widoku, przekazuje kontrolę do strony układu. (Strona układu zaczyna się renderowanie od góry do dołu) Pozostaje więc na stronie Układu tylko umieszczanie treści. Kiedy zobaczy @RenderBody(), umieszcza tylko wynik twojego już wykonanego widoku.

Dla sekcji; nie są wykonywane po wykonaniu treści widoku, po przejściu widoku na stronę układu, strona układu jawnie wywołuje wykonanie sekcji w kolejności, w jakiej zostały zadeklarowane.

również zauważyć, że określasz swój tytuł strony w organizmie widok i to jest renderowany w układzie tagu tytułu (ViewBag.Title) .Po widok roli organu wszystkie zmienne, które są zadeklarowane w widoku ciała są dostępne w strona układu.

Suma: kolejność renderowania jest od góry do dołu, ale kolejność wykonywania jest inna.

do sytuacji: "SomethingThatDependsOnContextBeingSetUp wykonuje przed SetUpSomeContext a nie". Tak jak powiedziałem, że jest to naturalne zachowanie cyklu wykonywania maszynki Razor, zobacz treść wykonaną przed wykonaniem strony układu. Po utworzeniu sekcji; view body wykonywane najpierw, ale sekcje nie są wykonywane przed stroną layout.View body przekazuje kontrolę do strony layoutu, a strona Layout zaczyna renderować od góry do dołu i jeśli widzi @RenderSection, wywołuje wykonanie sekcji.So w tym przypadku wykonywany jest SetUpSomeContext przed wykonaniem SomethingThatDependsOnContextBeingSetUp.

+0

To nie jest odpowiedź i należy ją przenieść, aby była częścią pytania. – krillgar

+0

Myślę, że wyjaśnia każdy szczegół, który pytający musi się nauczyć – MstfAsan

+0

Wydaje się to przydatne, ale nie przypomina * odpowiedzi *, bardziej przypomina ogólny samouczek. –

5

maszynki rurociąg jest:

  1. Najpierw Razor ocenia, jeśli występuje, _ViewStart.cshtml że zawiera jedynie oświadczenia ostrzami (C# lub VB) dla przypisać układ lub inny inicjalizacji powinien nigdy nie ma tagów HTML wewnątrz.

  2. Następnie analizuje i analizuje plik cshtml "Widok".

  3. Następnie, analizowania i ocenia, jeśli występuje, Układ, a gdy ocenia metodę pliku layoutu cshtml @RenderBody, zastępuje go skryptu HTML, wynikające z oceny „Widok” pliku cshtml.

  4. Wreszcie, tworzy obiekty graficzne html kontrolne układu i przeglądać pliki html.


Więc, nie można nie zależy żadnych przedmiotów „Razor” z widokiem na operacjach układu, ale raczej można umieścić w _ViewStart.cshtml Twój inicjalizacji obiektów widocznych na widoku.


Można sobie wyobrazić widoki cs (VB) html jako statyczny załadowanego gdy Controller.View wywoływana jest metoda.

W tym momencie załadowana zawartość cshtml jest analizowana przez maszynkę Razor, która ocenia wyrażenia (przypisuje właściwości (jako układ), gałęzie, pętle) i tworzy rodzaj drzewa binarnego lub wykresu obiektów "HtmlControls" w obiekcie ActionResult zwracane przez metodę View.

Następnie ActionResult jest renderowany jako html z Asp.Net i zwracany do klienta jako odpowiedź http.

Aby to zrobić, Razor analizuje pliki cshtml i wykonuje ich kod wewnątrz części, zaczynając od "_ViewStart.cshtml" (także więcej, jeśli występuje w łańcuchu pod-folderów związanych z kontrolerem oryginalu), po czym następuje cshtml plik załadowany przez konwencje (nazwa widoku jest równa nazwie akcji w ścieżce Widoki/[nazwa kontrolera] /) lub wyrażona nazwa widoku jako parametr podczas wywoływania metody View, a na końcu, ostateczny plik układu połączony z widokiem przez Layout własność.

Powiązane problemy