반응형
이 포스트는 월간 마이크로소프트웨어에 기고한 원고를 재편집한 포스트입니다. 그러므로, 본의 아니게 반말로 진행되고 있습니다. 원래 싸가지가 없어서 그런 것이 아니니 무한 용서를... ^^;;
또한, .NET Framework 3.5 SP1이 적용되기 이전의 소스이므로, 현재의 개발 환경과 다를 수 있습니다. 마소에 제출한 블로그 소스는 블로그 소스 다운로드에서 다운로드하실 수있습니다.
또한, .NET Framework 3.5 SP1이 적용되기 이전의 소스이므로, 현재의 개발 환경과 다를 수 있습니다. 마소에 제출한 블로그 소스는 블로그 소스 다운로드에서 다운로드하실 수있습니다.
태그 목록 페이지(Tag.aspx) 페이지 구현
마소 3월호에서 관리자가 포스트를 작성할 경우 블로그에 관련된 태그(블로그 태그는 작성한 포스트가 가지는 특징적인 키워드를 말한다고 생각할 수 있다.)를 입력하여 데이터베이스에 저장할 수 있도록 하였다. 이 때 저장되는 태그들의 목록을 볼 수 있는 태그 목록 페이지를 만드는 방법에 대해서 설명하도록 하겠다. 우선, 태그 정보를 "BLOG_TAGS" 테이블에 추가/삭제하는 "dbo.usp_SetTagInfo" 저장 프로시저의 코드는 <리스트 5>와 같이 작성되어 있다.
CREATE PROCEDURE [dbo].[usp_SetTagInfo]
(
@command VARCHAR(6)
, @tag VARCHAR(20)
)
AS
BEGIN
SET @tag = LTRIM(@tag)
IF @command = 'create'
BEGIN
-- 기존에 입력된 태그 정보가 없으면
IF (0 = (SELECT COUNT(TagName) FROM dbo.BLOG_TAGS
WHERE UPPER(tagname) = UPPER(@tag)))
BEGIN
INSERT INTO dbo.BLOG_TAGS VALUES (@tag, 1)
END
ELSE
BEGIN
UPDATE dbo.BLOG_TAGS SET tagcount = tagcount + 1
WHERE UPPER(tagname) = UPPER(@tag)
END
END
ELSE IF @command = 'delete'
BEGIN
UPDATE dbo.BLOG_TAGS SET tagcount = tagcount - 1
WHERE UPPER(tagname) = UPPER(@tag)
-- 현재 태그의 개수가 0이면 삭제
IF (0 = (SELECT COUNT(TagName) FROM dbo.BLOG_TAGS
WHERE UPPER(tagname) = UPPER(@tag)))
BEGIN
DELETE FROM dbo.BLOG_TAGS
WHERE UPPER(tagname) = UPPER(@tag)
END
END
END
<리스트 5>에서 보는 것과 같이 "dbo.usp_SetTagInfo" 저장 프로시저에 대해 간략하게 설명하자면, @command 매개 변수에 "create"라는 값이 들어오게 되면, 우선 "BLOG_TAGS" 테이블에 @tag 매개 변수에 입력되는 태그 값에 관련된 정보가 있는지 없는지를 확인한다. 만약 해당 태그 정보가 있으면, "BLOG_TAGS" 테이블의 TagCount 필드의 값을 1 증가시켜주고, 태그 정보가 없는 경우에는 태그 정보를 테이블에 추가하게 된다. 마찬가지로, @command 매개 변수에 "delete"라는 값이 들어오게 되면, 해당 태그의 TagCount 필드의 값을 1 감소시킨 후, 만약 해당 태그의 TagCount 필드의 값이 0이 되면 해당 행을 삭제하게 된다. <리스트 5>에 사용된 코드를 이용하여, "dbo.usp_SetTagInfo" 저장 프로시저를 생성후에 “App_Code" 폴더 안에 이미 생성되어 있는 ”BlogDataClasses.dbml“ 파일의 디자이너 화면의 우측 영역에 이 저장 프로시저를 추가한다. 그 후에, "Admin.aspx.cs" 코드 비하인드 파일을 열어서 포스트의 작성/수정/삭제 시에 사용되는 각 이벤트에서 "dbo.usp_SetTagInfo" 저장 프로시저를 이용하여 "BLOG_TAGS" 테이블에 값을 추가/수정/삭제하는 SetTagList() 메소드를 호출하는 코드를 추가한다. <리스트 6>은 추가된 "Admin.aspx.cs" 코드 비하인드 파일의 소스 코드 및 SetTagList() 메소드의 코드를 보여준다.
// 포스트 쓰기 탭에서 작성 버튼 클릭 시
protected void btnPostWrite_Click(object sender, EventArgs e)
{
try
{
if (chkNotice.Checked)
{
... <코드 생략> ...
}
else
{
... <코드 생략> ...
SetTagList(string.Empty, txtPostTag.Text, "create");
}
}
catch (Exception ee)
{
... <코드 생략> ...
}
}
// 포스트 수정 탭에서 수정 버튼 클릭 시
protected void btnPostModify_Click(object sender, EventArgs e)
{
try
{
if (!string.IsNullOrEmpty(strPostID))
{
if (chkModifyNotice.Checked)
{
... <코드 생략> ...
}
else
{
... <코드 생략> ...
string strOldTag = blogPost.tag;
... <코드 생략> ...
SetTagList(strOldTag, txtModifyPostTag.Text, "modify");
}
}
}
catch (Exception ee)
{
... <코드 생략> ...
}
}
// 포스트 수정 탭에서 삭제 버튼 클릭 시
protected void btnPostDelete_Click(object sender, EventArgs e)
{
try
{
if (!string.IsNullOrEmpty(strPostID))
{
if (chkModifyNotice.Checked)
{
... <코드 생략> ...
}
else
{
... <코드 생략> ...
string strOldTag = blogPost.tag;
... <코드 생략> ...
SetTagList(strOldTag, string.Empty, "delete");
}
}
}
catch (Exception ee)
{
... <코드 생략> ...
}
}
private void SetTagList(string strOldTag, string strNewTag, string strCommand)
{
string[] strOldTagList = null;
string[] strNewTagList = null;
if (string.Compare(strCommand, "create", true) == 0)
{
strNewTagList = strNewTag.Split(',');
// 신규 태그 정보 입력
foreach (string strTag in strNewTagList)
{
int iTag = blogDataContext.usp_SetTagInfo(strCommand, strTag);
}
}
else if (string.Compare(strCommand, "modify", true) == 0)
{
strOldTagList = strOldTag.Split(',');
strNewTagList = strNewTag.Split(',');
// 기존 태그 정보 삭제
foreach (string strTag in strOldTagList)
{
int iOldTag = blogDataContext.usp_SetTagInfo("delete", strTag);
}
// 신규 태그 정보 입력
foreach (string strTag in strNewTagList)
{
int iNewTag = blogDataContext.usp_SetTagInfo("create", strTag);
}
}
else if (string.Compare(strCommand, "delete", true) == 0)
{
strOldTagList = strOldTag.Split(',');
// 기존 태그 정보 삭제
foreach (string strTag in strOldTagList)
{
int iTag = blogDataContext.usp_SetTagInfo(strCommand, strTag);
}
}
}
<리스트 6>에서 보는 것과 같이 SetTagList() 메소드를 이용하여 "BLOG_TAGS" 테이블에 태그 정보와 사용된 태그 개수 정보를 제어하는 부분을 추가하였다. 이제 태그 목록(Tag.aspx) 페이지에서 "BLOG_TAGS" 테이블에 저장된 정보를 가져와서 화면에 출력하는 부분 및 포스트 조회 화면이나 기타 다른 화면에서 작성된 포스트의 태그 정보를 클릭시에 선택한 태그가 포함되어 있는 포스트의 목록 정보를 출력하는 부분에 대한 설명을 하도록 하겠다.
태그 목록(Tag.aspx) 페이지는 두 개의 ListView 컨트롤로 구성되어 있으며, 첫번째 ListView 컨트롤은 "BLOG_TAGS" 테이블에 들어있는 정보를 화면에 출력하기 위해 사용되고, 두번째 ListView 컨트롤은 "BLOG_POSTS" 테이블에 저장된 정보 중 Tag 필드의 값이 선택한 태그(쿼리스트링 혹은 폼을 통해 전달되는 tag값)의 값과 일치하는 포스트 목록을 출력하기 위해 사용된다. <화면 8>은 등록되어 있는 전체 태그 목록이 출력된 화면을 보여준다.
<화면 8> 등록된 전체 태그 목록 출력 화면
두번째 ListView 컨트롤은 데이터 소스 컨트롤로써 SqlDataSource 데이터 소스 컨트롤을 사용하며, SqlDataSource 데이터 소스 컨트롤에서 사용할 저장 프로시져는 "dbo.usp_GetPostsInfoByTag"로, 이 저장 프로시저는 <리스트 7>에서 보여지는 코드와 같이 구성되어 있으며, 저장 프로시저를 생성한 후에 SqlDataSource 데이터 소스 컨트롤의 데이터 소스를 <화면 2>부터 <화면 6>에서 보여지는 것과 똑같이 구성하면 된다.
CREATE PROCEDURE [dbo].[usp_GetPostsInfoByTag]
(
@tag VARCHAR(20)
)
AS
BEGIN
SELECT PostID, PostName, posts.CreateDate, PostContent
, Tag, ViewCount, CommentCount, CategoryName
FROM dbo.BLOG_POSTS posts
INNER JOIN dbo.BLOG_CATEGORIES category
ON posts.categoryid = category.categoryid
WHERE posts.Tag LIKE '%' + @tag + '%'
ORDER BY posts.CreateDate DESC
END
"Tags.aspx.cs" 코드 비하인드 파일의 Page_Load 이벤트에서는, 쿼리스트링 혹은 폼을 통해 전달되는 값 중 "tag"값이 있는지를 검사하여, "tag"값이 있는 경우에는 "Tag.aspx" 페이지에 정의된 SqlDataSource 데이터 소스 컨트롤의 SelectParameter에 "tag"의 값을 전달하여 ListView 컨트롤을 데이터바인딩시키고, "tag"의 값이 없는 경우에는 두번째의 ListView 컨트롤이 포함된 영역을 보이지 않도록 Div 컨트롤의 스타일 속성 중, display 속성을 "none"으로 할당시킨다. <화면 9>는 "tag"값으로 "LINQ"라는 값이 전달되었을 때의 태그 목록 페이지의 화면을 보여준다.
<화면 9> "LINQ"라는 태그가 포함된 포스트 목록 출력 화면
포스트 작성시에 입력한 태그 정보를 쉼표(,)를 구분자로 하여 각각의 태그를 선택할 수 있게 하기 위해서, 코드 비하인드 파일에 DisplayTagList()라는 이름의 메소드를 정의한다. 이 메소드는 "Tag.aspx" 페이지의 "LvwTagList"라는 ListView 컨트롤의 ItemTemplate 안에 "lblPostTag"라는 Label 태그의 Text 속성에서 사용되며, 태그 정보를 쉼표(,)를 구분자로 하여 하이퍼링크 형태로 화면에 출력하게 한다. <리스트 8>은 DisplayTagList() 메소드의 코드를 보여준다.
public string DisplayTagList(string strTags)
{
string[] strArrayTag = strTags.Split(',');
StringBuilder sbTag = new StringBuilder();
foreach (string strTag in strArrayTag)
{
sbTag.AppendFormat
("<a href='/Tag/{0}.aspx' target='_self'>{0}</a>, ", strTag);
}
return sbTag.ToString().Substring(0, sbTag.ToString().Length - 2);
}
<리스트 8>에 정의된 DisplayTagList() 메소드의 코드를 바탕으로 포스트의 목록 정보가 출력되는 "Archive.aspx", "Category.aspx", "PostView.aspx", "Search.aspx" 페이지의 코드 비하인드 파일에 각각 DisplayTagList() 메소드를 정의하고 각 페이지에 사용된 ListView 컨트롤에서 태그 정보가 출력되는 곳에서 DisplayTagList() 메소드를 호출하도록 이달의 디스켓에 들어있는 소스를 참고하여 코드를 변경한다.
관리자 기능의 추가 - 카테고리 관리, 즐겨찾기 관리
블로그의 우측 메뉴에서 보이는 카테고리 목록과 즐겨찾기 목록을 관리하는 기능에 대해서 설명하도록 하겠다. “Admin.aspx" 페이지를 열어, 기존에 정의한 TabPanel 컨트롤을 2개 추가한 후, 첫 번째 TabPanel 컨트롤의 HeaderTemplate에는 카테고리 목록, 두 번째 TabPanel 컨트롤의 HeaderTemplate에는 즐겨찾기 목록이라고 입력한다. 또한, TabPanel의 ContentTemplate 안에 UpdatePanel 컨트롤을 각각 위치시킨 후, UpdatePanel 컨트롤의 ContentTemplate 템플릿 안에 ListView 컨트롤을 추가한다. 그 후에, 카테고리 목록을 추가/수정/삭제/조회하는데에 사용될 SqlDataSource 데이터 소스 컨트롤을 ”Admin.aspx" 웹 페이지로 추가한 후, 스마트 태그의 “데이터 소스 구성(Configurate Data Source...) 메뉴를 눌러 데이터 소스 구성 마법사를 실행한다. <화면 2>를 참고하여 데이터 연결 선택 화면을 진행하고, <화면 3>에서 ”테이블 또는 뷰의 열 지정(Specify column from a table or view)“을 선택한 후, <화면 10>과 같은 SELECT 구문이 나올 수 있도록 WHERE 버튼과 ORDER BY 버튼을 이용하여 구성하도록 한다.
<화면 10> Select 구문을 구성하는 화면
또한, <화면 10>에서 보이는 우측의 “고급(Advanced...)" 버튼을 클릭하여, <화면 11>과 같이 ”Insert, Update 및 Delete 문 생성(Generate INSERT, UPDATE, and DELETE statements)“을 체크한 후, ”확인(OK)" 버튼을 클릭하고, “다음(Next)" 버튼을 클릭하여, <화면 6>에서 보이는 쿼리 테스트 화면의 ”종료(Finish)" 버튼을 클릭하여 데이터 소스 구성 마법사를 종료하면, 자동적으로 SqlDataSource 데이터 소스 컨트롤에 4개의 Command 속성(SelectCommand, InsertCommand, UpdateCommand, DeleteCommand)이 추가된다.
<화면 11> 고급 SQL 등록 옵션 구성 화면
마찬가지로 즐겨찾기 목록의 조회와 즐겨찾기 정보를 추가/수정/삭제하기 위한 SqlDataSource 컨트롤을 웹 폼에 추가한 후, 동일한 방법으로 데이터 소스 구성 마법사를 실행한다. 이러한 방법으로 정의된 SqlDataSource 컨트롤을 ListView 컨트롤과 결합한 화면은 <화면 12>와 같다. (즐겨찾기 목록 정보도 카테고리 목록 정보와 동일하게 추가/수정/삭제/조회가 가능하며, 정의된 SqlDataSource 컨트롤과 ListView 컨트롤과의 결합 정보는 본 필자가 태오사이트에 강좌로 등록한, ListView 컨트롤 Part2(http://www.taeyo.pe.kr/Lecture/NET/AspNet35_listView02.asp)를 참고하도록 한다.)
<화면 12> 카테고리 목록 구성 화면
설명대로 구성되어진 카테고리 목록에 새로운 카테고리를 추가하면, 블로그 우측 메뉴에 추가한 카테고리 목록이 나타나게 되며, 새로운 포스트를 작성하고자 할 때에도 카테고리의 목록이 나타나게 된다. 이와 동일하게 즐겨찾기 목록에 새로운 즐겨찾는 사이트 또는 블로그에 대한 정보를 추가하도록 한다. 그리고, 블로그의 마스터 페이지인 “BlogMasterPage.master.cs" 파일에 즐겨찾기 목록의 정보를 표시하는 GetFavoriteListInfo() 메소드를 추가한다. GetFavoriteListInfo() 메소드의 코드는 <리스트 9>에 정의되어 있으며, 블로그에 표시되는 즐겨찾기 목록은 <화면 13>과 같이 보여지게 된다.
// 즐겨찾기 정보 가져오기
private void GetFavoriteListInfo()
{
BlogDataClassesDataContext blogDataContext
= new BlogDataClassesDataContext();
List<BLOG_LINKS> blogLinkList =
(from c in blogDataContext.BLOG_LINKS
orderby c.sortkey ascending
select c).ToList();
LvwFavoriteList.DataSource = blogLinkList;
LvwFavoriteList.DataBind();
blogDataContext = null;
}
<화면 13> 즐겨찾기 목록이 표시된 블로그 화면
마치며...
이로써, 4개월간의 Visual Studio 2008을 이용한 블로그 프로그래밍에 관련된 연재를 끝내고자 한다. 지면의 한계상 블로그 프로그래밍에서의 방명록에 관련된 기능과 트랙백에 관련된 기능 구현을 설명하지는 못했지만, 필자의 블로그(http://www.neostyx.net)에 “방명록 만들기”라는 포스트를 참조하여 방명록의 기능을 구현하였으면 한다. 또한, 트랙백에 관련된 포스트도 마소의 독자들을 위해서 올릴 예정이니 트랙백의 기능 구현도 필자의 블로그를 참고하면 좋겠다. 필자가 처음 글을 집필할 때의 의도처럼, 필자의 글을 바탕으로 Visual Studio를 이용해서 블로그를 만들려고 결심한 개발자 또는 독자가 많이 생겼으면 하며, 필자가 설명한 것보다 더 훌륭하고 멋진, 그리고 좋은 기능을 가진 블로그가 많이 나왔으면 하는 게 필자의 바램이다.
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-동일조건변경허락 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
반응형
'Program > ASP.NET' 카테고리의 다른 글
Wiki source (0) | 2009.07.19 |
---|---|
처리되지 않은 예외 처리방안 (0) | 2009.06.16 |
VS 2008을 이용한 블로그 프로그래밍 - Part11 (0) | 2009.06.16 |
VS 2008을 이용한 블로그 프로그래밍 - Part10 (0) | 2009.06.16 |
VS 2008을 이용한 블로그 프로그래밍 - Part9 (0) | 2009.06.16 |