.Net framework v4.0, Visual Studio 2010, asp.net MVC3 프로젝트 기준으로 진행된 내역입니다.

Asp.Net MVC 중에 _Layout.cshtml에서 각 페이지 렌더링 될 때 사용될 기본적인 룰을 정리하던 도중 RenderSection처리하는 부분이 너무 번거로운 것 같아 '좀 내 입맛대로 해보자!'하는 취지에서 찾아보고 진행했던 내용입니다.

WebViewPage클래스를 상속받는 클래스 생성

RenderSection은 MSDN을 찾아보면 System.Web.WebPages.WebPageBase클래스에 구현되어 있으니 WebPageBase클래스를 상속받은 클래스를 생성해도 되지만, WebViewPage클래스에 구현되어 View 페이지(*.cshtml)에서 사용되는 유용한 속성, 메서드들은 사용할 수 없거나, 다시 구현해야 하기 때문에 WebViewPage클래스를 상속받는 클래스를 생성합니다.

클래스를 생성하는 위치는 적절하게 선택하면 되며, 여기서는 WebViewPageHandler 클래스로 진행하도록 하겠습니다.
제가 원하는 RenderSection의 기능이 <script ...></script>를 필요에 따라서 삭제하고, 추가로 jquery에서 사용되는 $(document).ready...로 시작되는 부분을 필요에 따라서 삭제할 수 있도록 하는 부분이어서 아래와 같이 구현하였습니다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using System.Web.Mvc;
using System.Web.WebPages;
using System.Text.RegularExpressions;

namespace 네임스페이스 명
{
    public abstract class WebViewPageHandler<T> : WebViewPage<T>
    {
        public override void InitHelpers()
        {
            base.InitHelpers();
        }

        /// <summary>
        /// 레이아웃 페이지에서 명명된 섹션의 콘텐츠를 렌더링하고 섹션이 필수인지를 지정합니다. 
        /// <para>또한 스크립트 블럭 테그와  Jquery의 '$(document).ready(function () {' 항목과 끝 '});' 항목을 삭제할지 지정합니다.</para>
        /// </summary>
        /// <param name="name">렌더링할 섹션입니다.</param>
        /// <param name="required">섹션을 필수로지정하려면 true이고, 그렇지 않으면 false입니다.</param>
        /// <param name="isRemoveScriptBlock">상단에 스크립트 블럭 시작Tag 와 끝Tag를 삭제하려면 true, 그렇지 않으면 false입니다.</param>
        /// <param name="isRemoveDocReady">Jquery의 '$(document).ready(function () {' 항목과 끝 '});' 항목을 삭제하려면 true, 그렇지 않으면 false입니다.</param>
        /// <returns>렌더링할 HTML 콘텐츠입니다.</returns>
        public HelperResult RenderSection(string name, bool required, bool isRemoveScriptBlock, bool isRemoveDocReady)
        {
            String renderString = NoNull.ToString(base.RenderSection(name, required), string.Empty);

            #region 객체에 대한 유효성 검사를 실시합니다. 
            if (string.IsNullOrEmpty(renderString) && !required)
            {
                // 필수지정이 되어 있지않고, 구현 된 Section 내용이 없다면 null을 리턴합니다.
                // cshtml에서는 아무런 내용도 작성되지 않습니다.
                return null;
            }
            else if (string.IsNullOrEmpty(renderString) && !required)
            {
                // 필수로 지정되어있으나 구현 된 Section 내용이 없다면 오류로 생각해야 합니다.
                // 때문에 MSDN 오류 처리에 맞춰 오류를 발생시킵니다.
                throw new HttpException("렌더링할 섹션을 찾을 수 없습니다.");
            }
            #endregion

            // 상단의 <script ...> 와</script> 항목을 삭제합니다.
            // 내용물은 삭제하지 않습니다.
            if (isRemoveScriptBlock)
            {
                renderString = Regex.Replace(renderString, @"<script[^>]*>", "");
                renderString = Regex.Replace(renderString, @"<\/script>", "");
            }

            // Jquery의 '$(document).ready(function () {' 항목과 끝 '});' 항목을 삭제합니다.
            if (isRemoveDocReady)
            {
                renderString = renderString.Replace(@"$(document).ready(function () {", "");
                int index = renderString.LastIndexOf(@"});");
                renderString = renderString.Substring(0, index);
            }

            HelperResult result = new HelperResult(__razor_helper_writer =>
            {
                // 아래 WriteLiteralTo 메서드를 써야 "나 '문자가 변환되지 않습니다.
                WriteLiteralTo(__razor_helper_writer, renderString);
            });

            return result;
        }
    }
}

Web.config 수정

Web.config 파일은 프로젝트 내에 2개가 존재하는데 여기서 수정하는 파일은 View폴더 밑에 있는 파일입니다. 내용 중에 <system.web.webPages.razor>노드 하위에 <pages>노드를 찾아 다음과 같이 수정해 줍니다.

<?xml version="1.0" encoding="utf-8"?>

<configuration>
  <configSections>
    <sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
      <section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
      <section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
    </sectionGroup>
  </configSections>
  
  <system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.1, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <!--<pages pageBaseType="System.Web.Mvc.WebViewPage">-->
    <pages pageBaseType="네임스페이스 명.WebViewPageHandler">  <!-- 이 부분을 상황에 맞게 수정합니다. -->
      <namespaces>
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Routing" />
      </namespaces>
    </pages>
  </system.web.webPages.razor>

_layout.cshtml 파일의 수정

_layout.cshtml에서 위에 overload된 RenderSection을 사용하는 부분입니다.

<!DOCTYPE html>
<html>
<head>
    <title>홈페이지에 오신걸 환영합니다.</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" lang="ko" />
    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE9" />

    <link href="@Url.Content("~/Content/layout.css")" rel="stylesheet" type="text/css" />
    <link href="@Url.Content("~/Content/jquery-ui/themes/flick/jquery-ui-1.10.4.flick.css")" rel="stylesheet" type="text/css" />
    <link href="@Url.Content("~/Content/menu_top.css")" rel="stylesheet" type="text/css" />
    @if (IsSectionDefined("PageDefineCssBlock")) { @RenderSection("PageDefineCssBlock") }
                                                                                        
    <script src="@Url.Content("~/Scripts/jquery-1.10.2.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery-ui-1.10.4.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/menu_top.js")" type="text/javascript"></script>
    @if (IsSectionDefined("PageDefineScriptBlock")) { @RenderSection("PageDefineScriptBlock") }
       
    <script type="text/javascript">
        $(document).ready(function () {
            $('#logOut').button().css('font-size', '0.8em');
            @RenderSection("PageDefineDocReadyBlock", false, true, true)   // overload된 RenderSection
        });

        @RenderSection("PageDefineFunctionBlock", false, true, false)    // overload된 RenderSection
    </script>
</head>

<body>

....

아래는 View 페이지 내역으로 PageDefineDocReadyBlock블럭에서는 위에서 구현한 부분과 같이 <script ...>부터 $(document).ready(function () {, </script> 부분이 제거된 상태로 _layout.cshtml파일에 삽입됩니다. 또한 PageDefineFunctionBlock블럭에서는 <script ...>, </script> 부분이 제거되어 삽입 됩니다.

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

@*@section PageDefineScriptBlock { }*@

@section PageDefineCssBlock {
    <!-- 페이지 선언 CSS Block -->
    <link href="@Url.Content("~/Content/login.css")" rel="stylesheet" type="text/css" /> 
}

@section PageDefineDocReadyBlock {
    <script type="text/javascript">
        $(document).ready(function () {
            $("#Id_user").focus();
            $("#login_form").submit(function () {
                var inputId = $("#Id_user").val();
                var inputPw = $("#Pw_user").val();

                if (inputId.length === 0) {
                    alert("ID를 입력해주세요.");
                    $("#Id_user").focus();
                    return false;
                }

                if (inputPw.length === 0) {
                    alert("비밀번호를 입력해주세요.");
                    $("#Pw_user").focus();
                    return false;
                }
            });
        });
    </script>
}

@section PageDefineFunctionBlock {
    <script type="text/javascript">
        function test() {
            alert('test function입니다.');
        }
    </script>
}
....

마지막으로 실제 실행 된 HTML의 소스 부분입니다.

<!DOCTYPE html>
<html>
<head>
    <title>홈페이지에 오신걸 환영합니다.</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" lang="ko" />
    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE9" />

    <link href="/Content/jquery-ui/themes/flick/jquery-ui-1.10.4.flick.css" rel="stylesheet" type="text/css" />

    <!-- 페이지 선언 CSS Block -->
    <link href="/Content/login.css" rel="stylesheet" type="text/css" /> 
                                                                                        
    <script src="/Scripts/jquery-1.10.2.js" type="text/javascript"></script>
    <script src="/Scripts/jquery-ui-1.10.4.js" type="text/javascript"></script>
                                                                                              
    <script type="text/javascript">
        $(document).ready(function () {
            
    
        
            $("#Id_user").focus();
            $("#login_form").submit(function () {
                var inputId = $("#Id_user").val();
                var inputPw = $("#Pw_user").val();

                if (inputId.length === 0) {
                    alert("ID를 입력해주세요.");
                    $("#Id_user").focus();
                    return false;
                }

                if (inputPw.length === 0) {
                    alert("비밀번호를 입력해주세요.");
                    $("#Pw_user").focus();
                    return false;
                }
            });
        
        });

         
    
        function test() {
            alert('test function입니다.');
        }
    

    </script>
</head>

<body>
    <!-- Content Start -->

...

참고 페이지

+ Recent posts