.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 -->
...
참고 페이지