[asp.net-mvc-3] 계단식 섹션이있는 Razor 중첩 레이아웃

Razor를 뷰 엔진으로 사용하는 MVC3 사이트가 있습니다. 내 사이트를 스키닝 ​​할 수 있기를 원합니다. 가능한 대부분의 스킨은 공유 마스터 레이아웃에서 파생 될 수있을 정도로 유사합니다.

따라서이 디자인을 고려하고 있습니다.

계획된보기 다이어그램

그러나 RenderSection맨 아래 레이어에서을 호출 _Common.cshtml하고 맨 위 레이어에 정의 된 섹션을 렌더링하도록하고 싶습니다 Detail.cshtml. 이것은 작동하지 않습니다. RenderSection분명히 다음 레이어에 정의 된 섹션 만 렌더링합니다.

물론 각 스킨의 각 섹션을 정의 할 수 있습니다. 예를 들어에 정의 된 섹션 _Common을 호출해야하는 경우 각 RenderSection("hd")섹션에 Detail배치하면 다음 _Skin과 같이 작동합니다.

@section hd {
    @RenderSection("hd")
}

이로 인해 코드가 일부 중복되고 (이제 각 스킨에 동일한 섹션이 있어야하므로) 일반적으로 지저분하게 느껴집니다. 나는 아직 Razor를 처음 사용하고 있으며 분명한 것을 놓친 것 같습니다.

디버깅 할 때 WebViewPage.SectionWritersStack에서 정의 된 섹션의 전체 목록을 볼 수 있습니다. 포기하기 전에 전체 목록을 살펴 보도록 RenderSection에 지시 할 수 있다면 필요한 섹션을 찾을 수 있습니다. 아아, SectionWritersStack은 비공개입니다.

또는 레이아웃 페이지의 계층 구조에 액세스하고 서로 다른 컨텍스트에서 RenderSection 실행을 시도 할 수 있다면 필요한 섹션을 찾을 수 있습니다. 나는 아마도 뭔가를 놓치고 있지만 이것을 할 방법이 없다고 생각합니다.

이미 설명한 방법 외에이 목표를 달성 할 수있는 방법이 있습니까?



답변

이것은 실제로 공개 API를 사용하여 가능하지 않습니다 (섹션 재정의 접근 방식을 사용하는 경우 제외). 사적인 성찰을 사용하면 운이 좋을 수도 있지만 당연히 깨지기 쉬운 접근 방식입니다. 다음 버전의 Razor에서이 시나리오를 더 쉽게 만드는 방법을 살펴 보겠습니다.

그 동안 내가 주제에 대해 작성한 몇 가지 블로그 게시물이 있습니다.


답변

@helper ForwardSection( string section )
{
   if (IsSectionDefined(section))
   {
       DefineSection(section, () => Write(RenderSection(section)));
   }
}

이것이 일을할까요?


답변

MVC 3에서 이것이 가능한지 확실하지 않지만 MVC 5에서는 다음 트릭을 사용하여 성공적으로 수행 할 수 있습니다.

다음 ~/Views/Shared/_Common.cshtml과 같은 일반적인 HTML 코드를 작성하십시오.

<!DOCTYPE html>
<html lang="fa">
<head>
    <title>Skinnable - @ViewBag.Title</title>
</head>
<body>
@RenderBody()
</body>
</html>

에서 ~/Views/_ViewStart.cshtml:

@{
    Layout = "~/Views/Shared/_Common.cshtml";
}

이제 당신이해야 할 사용하는 것입니다 _Common.cshtml은 AS를 Layout모든 스킨. 예를 들어 ~/Views/Shared/Skin1.cshtml:

@{
    Layout = "~/Views/Shared/_Common.cshtml";
}

<p>Something specific to Skin1</p>

@RenderBody()

이제 컨트롤러에서 스킨을 레이아웃으로 설정하거나 기준에 따라 볼 수 있습니다. 예를 들면 :

    public ActionResult Index()
    {
        //....
        if (user.SelectedSkin == Skins.Skin1)
            return View("ViewName", "Skin1", model);
    }

위의 코드를 실행하면 내용 Skin1.cshtml과 내용이 모두 포함 된 HTML 페이지가 표시됩니다._Common.cshtml

간단히 말해 (스킨) 레이아웃 페이지의 레이아웃을 설정합니다.


답변

이것이 도움이 될지는 확실하지 않지만, 부분 내에서 섹션을 “버블 업”하는 데 도움이되는 몇 가지 확장 메서드를 작성했습니다. 이는 중첩 된 레이아웃에서도 작동합니다.

Razor View Engine을 사용하여 부분보기 ASP.NET MVC 3에서 특정 섹션에 콘텐츠 삽입

자식 레이아웃 /보기 / 일부 선언

@using (Html.Delayed()) {
    <b>show me multiple times, @Model.Whatever</b>
}

모든 부모에서 렌더링

@Html.RenderDelayed();

반복되는 뷰에서 선언 된 경우에도 하나의 지연된 블록 만 렌더링하거나 특정 지연된 블록을 렌더링하는 등 더 많은 사용 사례에 대해서는 답변 링크를 참조하십시오.


답변