[MVC3 뒷북치기-3] 레이아웃 마스터해요

안녕하세요. 지난 [MVC3 뒷북치기-2] 레이저 그 심플함이란 후 한달 이라는 시간이 흘렀네요;; 참 포스팅이 늦어요. 이제 이런 모습 보이면 안되겠죠?^^;

이번 시간은 레이아웃에 대해 알아보도록 하겠습니다. 레이아웃을 마스터페이지라고 생각하면 된다고 말씀 드렸던 것 같은데요. "레이아웃 마스터해요" 이제 시작하도록 하겠습니다.^^ 아참. 예제는 지난 시간에 했던 프로젝트에서 진행하겠습니다.

마스터 1단계

일단 레이아웃부터 살펴보겠습니다.


<!DOCTYPE html>

<html>

<head>

    <title>@ViewBag.Title</title>

    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />

    <script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>

</head>

 

<body>

    @RenderBody()

</body>

</html>


먼저 보이는 것은 @ViewBag.Title 로 이는 각 뷰페이지에서 세팅하고 있죠? 지난 시간 Index 페이지에서 봤던 @{ ViewBag.Title = “Index”; } 이 부분이 헤더의 타이틀을 설정하는 것이라고 말씀드렸습니다.^^

 

그 다음으로 보이는 것은 @RenderBody() 인데요. 이는 각 뷰페이지의 Contents 를 렌더링하는 부분입니다. 따로 설정을 하지 않아도 여기에 표시가 됩니다.

 

처음 MVC 3 가 나왔을 때는 각 뷰페이지에서 레이아웃을 설정해주었는데요. 매번 페이지마다 이 설정하는 부분이 들어가다보니 DRY 위배판정을 받게되었습니다. 그래서 이것도 따로 페이지를 둬서 빼놓게 되었습니다. 그것이 바로 _ViewStart.cshtml 입니다.

@{

    Layout = "~/Views/Shared/_Layout.cshtml";

}

 

뷰페이지를 새로 만들 때 레이아웃을 설정하지 않으면 기본적으로 이 _ViewStart 를 세팅하게 되고 _Layout 페이지를 이용하게 되는 것이죠.

 

마스터 2단계

 

거창한 소제목에 비해 내용은 참..^^;; 머 이런식으로 두서없이 스타일 없이 진행하는게 저만의 스타~일 아니겠습니까?^^


이제는 두 개의 메뉴를 만들어볼까요?

레이아웃 페이지에 Home About 링크를 건 메뉴를 만들겠습니다.
 

<!DOCTYPE html>

<html>

<head>

    <title>@ViewBag.Title</title>

    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />

    <script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>

</head>

<body>

    <div id="header">

        @Html.ActionLink("Home""Index""Home")

        @Html.ActionLink("About""About""Home")

    </div>

    <div id="main">

        @RenderBody()            

    </div>

    <div id="footer">

    </div>

</body>

</html>

 

Content 폴더의 Site.css 파일을 열어 스타일을 추가하도록 하겠습니다. 이 부분은 기본적으로 생성되는 프로젝트(빈 프로젝트 아닌거요)에서 퍼왔습니다^^;

/* 레이아웃 관련 CSS 
-----------------------------------------------------------*/
#header
{
    positionrelative;
    margin-bottom0px;
    color#000;
    padding0;
    background-color#5c87b2;
}
#header a
{
    padding10px 20px;
    font-weightbold;
    text-decorationnone;
    line-height2.8em;
    color#fff;
}
#header a:hover
{
    text-decorationnone;
}
#main
{
    padding30px 30px 15px 30px;
    background-color#fff;
    margin-bottom30px;
    _height1px/* only IE6 applies CSS properties starting 
                             with an underscore */

}
#footer
{
    color#999;
    padding10px 0;
    text-aligncenter;
    line-heightnormal;
    margin0;
    font-size.9em;
}


Home 컨트롤러에 기본 뷰를 렌더링하는 About 액션메쏘드를 만들도록 하겠습니다.

public ActionResult About()
{
    return View();
}


그리고, 뷰페이지를 생성한 후 간단한 메시지를 보여주도록 하겠습니다.

@{
    ViewBag.Title = "About";
}

<h2>About</h2>

ASP.NET MVC 3 뒷북시리즈입니다.


그래서 결과화면은 다음과 같습니다.


자~ 이제  @RenderSection 에 대해 알아보도록 하겠습니다. 일단 코드를 보며 알아볼까요?


결론부터 얘기하자면 section 이라는 놈을 렌더링 해주는 것이죠. 그럼 footer에 RenderSection을 추가해보겠습니다.

<body>
    <div id="header">
        @Html.ActionLink("Home""Index""Home")
        @Html.ActionLink("About""About""Home")
    </div>
    <div id="main">
        @RenderBody()            
    </div>
    <div id="footer">
        @RenderSection("footer")
    </div>
</body>

그리고 결과화면을 보면~



엥? 실패네요. "footer" 라는 섹션이 없다는 메시지를 주는군요. 에러를 없애려면 footer 라는 섹션을 만들어야 하겠지만 우선은 정의되지 않은 섹션을 부르려고해도 에러를 주지 않도록 만들어야겠네요.

<div id="footer">
    @RenderSection("footer"false)
</div>

false 값을 추가하였습니다. 이는 footer 섹션이 있으면 사용하는 거고 없으면 안한다 이거죠.
이제 섹션을 만들어볼까요?

@{
    ViewBag.Title = "About";
}

@section footer {
    <h3>이거슨 푸터요^^</h3>
}


<h2>About</h2>

ASP.NET MVC 3 뒷북시리즈입니다.

이제 실행을 해볼까요?


자~ 여기서 한가지 더 해보겠습니다. 좀 전처럼 footer가 없을때는 에러가 났기때문에 에러를 없애기 위해 파라미터를 하나 더 줘서 없을때는 렌더링 하지 않도록 하였습니다. 그런데 없을때도 footer를 출력하고 싶다 이거죠. 어떻게하면 될까요?

<div id="footer">
    @if (IsSectionDefined("footer"))
    { 
        @RenderSection("footer"false)
    }
    else
    {
        <h3>이거슨 디폴트 푸터~</h3> 
    }
</div>

감이 오시나요?  @IsSectionDefined 을 사용해서 해당 섹션이 있으면 @RenderSection 을 통해 렌더링을 하고 없으면 디폴트를 출력하도록 하였습니다. 그래서 이제 footer 섹션을 없애도


디폴트 푸터~를 보여주는 것을 확인할 수 있습니다.

이것으로 마치도록 하겠습니다.
감사합니다^^