첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
728x90
반응형
728x170

TestProject.zip
다운로드

▶ TestDB.sql

CREATE TABLE dbo.Notice
(
    ID            INT           IDENTITY(1, 1) NOT NULL PRIMARY KEY -- ID
   ,[Name]        NVARCHAR(25)  NOT NULL                            -- 작성자명
   ,MailAddress   NVARCHAR(100) NULL                                -- 메일 주소
   ,Title         NVARCHAR(150) NOT NULL                            -- 제목
   ,WriteDate     DATETIME      DEFAULT GETDATE() NOT NULL          -- 작성일
   ,WriteIP       NVARCHAR(15)  NULL                                -- 작성 IP
   ,Content       NTEXT         NOT NULL                            -- 내용
   ,[Password]    NVARCHAR(20)  NULL                                -- 패스워드
   ,ReadCount     INT           DEFAULT 0                           -- 조회 수
   ,[Encoding]    NVARCHAR(10)  NOT NULL                            -- 인코딩(HTML/TEXT)
   ,Homepage      NVARCHAR(100) NULL                                -- 홈페이지
   ,UpdateDate    DATETIME      NULL                                -- 수정일
   ,UpdateIP      NVARCHAR(15)  NULL                                -- 수정 IP
   ,[FileName]    NVARCHAR(255) NULL                                -- 파일명
   ,FileSize      INT           DEFAULT 0                           -- 파일 크기
   ,DownloadCount INT           DEFAULT 0                           -- 다운로드 수
   ,ReferenceID   INT           NOT NULL                            -- 참조 ID
   ,ReplyLevel    INT           DEFAULT 0                           -- 답변 레벨
   ,ReplyOrder    INT           DEFAULT 0                           -- 답변 순서
   ,ReplyCount    INT           DEFAULT 0                           -- 답변 수
   ,ParentID      INT           DEFAULT 0                           -- 부모 ID
   ,CommentCount  INT           DEFAULT 0                           -- 댓글 수
)
GO

CREATE TABLE dbo.NoticeComment
(
    ID         INT            IDENTITY(1, 1) NOT NULL PRIMARY KEY -- ID
   ,NoticeID   INT            NOT NULL                            -- 게시판 ID
   ,[Name]     NVARCHAR(25)   NOT NULL                            -- 작성자명
   ,Comment    NVARCHAR(4000) NOT NULL                            -- 내용
   ,WriteDate  SMALLDATETIME  DEFAULT(GETDATE())                  -- 작성일
   ,[Password] NVARCHAR(20)   NOT NULL                            -- 패스워드
)
GO

CREATE PROCEDURE dbo.WriteNotice
    @Name        NVARCHAR(25)
   ,@MailAddress NVARCHAR(100)
   ,@Title       NVARCHAR(150)
   ,@WriteIP     NVARCHAR(15)
   ,@Content     NTEXT
   ,@Password    NVARCHAR(20)
   ,@Encoding    NVARCHAR(10)
   ,@Homepage    NVARCHAR(100)
   ,@FileName    NVARCHAR(255)
   ,@FileSize    INT
AS
    DECLARE @MaximumReferenceID INT;

    SELECT @MaximumReferenceID = MAX(ReferenceID) FROM dbo.Notice;

    IF @MaximumReferenceID IS NULL
    BEGIN
        SET @MaximumReferenceID = 1;
    END
    ELSE
    BEGIN
        SET @MaximumReferenceID = @MaximumReferenceID + 1;
    END

    INSERT INTO dbo.Notice
    (
        [Name]
       ,MailAddress
       ,Title
       ,WriteIP
       ,Content
       ,[Password]
       ,[Encoding]
       ,Homepage
       ,[ReferenceID]
       ,[FileName]
       ,[FileSize]
    )
    Values
    (
        @Name
       ,@MailAddress
       ,@Title
       ,@WriteIP
       ,@Content
       ,@Password
       ,@Encoding
       ,@Homepage
       ,@MaximumReferenceID
       ,@FileName
       ,@FileSize
    );
GO

CREATE PROCEDURE dbo.ListNotice
    @Page INT
AS
    WITH OrderedNoticeBoard
    AS
    (
        SELECT
            ID
           ,[Name]
           ,MailAddress
           ,Title
           ,WriteDate
           ,ReadCount
           ,ReferenceID
           ,ReplyLevel
           ,ReplyOrder
           ,ReplyCount
           ,ParentID
           ,CommentCount
           ,[FileName]
           ,FileSize
           ,DownloadCount
           ,ROW_NUMBER() OVER (ORDER BY ReferenceID DESC, ReplyOrder ASC) AS 'RowNumber'
        FROM dbo.Notice
    )
    SELECT *
    FROM   OrderedNoticeBoard
    WHERE  RowNumber BETWEEN @Page * 10 + 1 AND (@Page + 1) * 10;
GO

CREATE PROCEDURE dbo.ViewNotice
    @ID Int
As
    UPDATE dbo.Notice
    SET    ReadCount = ReadCount + 1
    WHERE  ID = @ID;

    SELECT *
    FROM   dbo.Notice
    WHERE  ID = @ID;
GO

CREATE PROCEDURE dbo.ReplyNotice
    @Name        NVARCHAR(25)
   ,@MailAddress NVARCHAR(100)
   ,@Title       NVARCHAR(150)
   ,@WriteIP     NVARCHAR(15)
   ,@Content     NTEXT
   ,@Password    NVARCHAR(20)
   ,@Encoding    NVARCHAR(10)
   ,@Homepage    NVARCHAR(100)
   ,@ParentID    INT
   ,@FileName    NVARCHAR(255)
   ,@FileSize    INT
AS
    DECLARE @MaximumReplyOrder INT;
    DECLARE @MaximumReplyCount INT;
    DECLARE @ParentReferenceID   INT;
    DECLARE @ParentReplyLevel  INT;
    DECLARE @ParentReplyOrder  INT;

    UPDATE dbo.Notice
    Set    ReplyCount = ReplyCount + 1
    WHERE  ID = @ParentID;

    SELECT
        @MaximumReplyOrder = ReplyOrder
       ,@MaximumReplyCount = ReplyCount
    FROM  dbo.Notice
    WHERE ParentID   = @ParentID
    AND   ReplyOrder = (SELECT MAX(ReplyOrder) FROM dbo.Notice WHERE ParentID = @ParentID);

    IF @MaximumReplyOrder IS NULL
    BEGIN
        SELECT @MaximumReplyOrder = ReplyOrder
        FROM   dbo.Notice
        WHERE  ID = @ParentID;

        SET @MaximumReplyCount = 0;
    END

    SELECT
        @ParentReferenceID = ReferenceID
       ,@ParentReplyLevel  = ReplyLevel
    FROM  dbo.Notice
    WHERE ID = @ParentID;

    UPDATE dbo.Notice
    SET    ReplyOrder  = ReplyOrder + 1
    WHERE  ReferenceID = @ParentReferenceID And ReplyOrder > (@MaximumReplyOrder + @MaximumReplyCount);

    INSERT INTO dbo.Notice
    (
        [Name]
       ,MailAddress
       ,Title
       ,WriteIP
       ,Content
       ,[Password]
       ,[Encoding]
       ,Homepage
       ,ReferenceID
       ,ReplyLevel
       ,ReplyOrder
       ,ParentID
       ,[FileName]
       ,FileSize
    )
    VALUES
    (
        @Name
       ,@MailAddress
       ,@Title
       ,@WriteIP
       ,@Content
       ,@Password
       ,@Encoding
       ,@Homepage
       ,@ParentReferenceID
       ,@ParentReplyLevel + 1
       ,@MaximumReplyOrder + @MaximumReplyCount + 1
       ,@ParentID
       ,@FileName
       ,@FileSize
    );
GO

CREATE PROCEDURE dbo.GetNoticeCount
As
    Select Count(*) From dbo.Notice;
GO

CREATE PROCEDURE dbo.SearchNoticeCount
    @SearchField NVARCHAR(25)
   ,@SearchQuery NVARCHAR(25)
AS
    SET @SearchQuery = '%' + @SearchQuery + '%';

    SELECT COUNT(*)
    FROM   dbo.Notice
    WHERE
    (
        CASE @SearchField
            WHEN 'Name'    THEN [Name]
            WHEN 'Title'   THEN Title
            WHEN 'Content' THEN Content
            ELSE                @SearchQuery
        END
    )
    LIKE @SearchQuery;
GO

CREATE PROCEDURE dbo.DeleteNotice
    @ID       INT
   ,@Password NVARCHAR(30)
AS
    DECLARE @Count INT;

    SELECT @Count = COUNT(*)
    FROM   dbo.Notice
    WHERE  ID         = @ID
    AND    [Password] = @Password;

    IF @Count = 0
    BEGIN
        Return 0;
    END

    DECLARE @ReplyCount  INT;
    DECLARE @ReplyOrder  INT;
    DECLARE @ReferenceID INT;
    DECLARE @ParentID    INT;

    SELECT
        @ReplyCount  = ReplyCount
       ,@ReplyOrder  = ReplyOrder
       ,@ReferenceID = ReferenceID
       ,@ParentID    = ParentID
    FROM  dbo.Notice
    WHERE ID = @ID;

    IF @ReplyCount = 0
    BEGIN
        IF @ReplyOrder > 0
        BEGIN
            UPDATE dbo.Notice
            SET    ReplyOrder  = ReplyOrder - 1
            WHERE  ReferenceID = @ReferenceID
            AND    ReplyOrder  > @ReplyOrder;

            UPDATE Notice
            SET    ReplyCount = ReplyCount - 1
            WHERE  ID = @ParentID;
        END

        DELETE FROM dbo.Notice
        WHERE ID = @ID;

        DELETE FROM dbo.Notice
        WHERE  ID         = @ParentID
        AND    UpdateIP   = N'((DELETED))'
        AND    ReplyCount = 0;
    END
    ELSE
    BEGIN
        UPDATE dbo.Notice
        SET
            [Name]       = N'(Unknown)',
            MailAddress  = '',
            [Password]   = '',
            Title        = N'(삭제된 글입니다.)',
            Content      = N'(삭제된 글입니다. 현재 답변이 포함되어 있기 때문에 내용만 삭제되었습니다.)',
            UpdateIP     = N'((DELETED))',
            [FileName]   = '',
            FileSize     = 0,
            CommentCount = 0
        WHERE ID = @ID;
    END
GO

CREATE PROCEDURE dbo.UpdateNotice
    @Name        NVARCHAR(25) 
   ,@MailAddress NVARCHAR(100)
   ,@Title       NVARCHAR(150)
   ,@UpdateIP    NVARCHAR(15) 
   ,@Content     NTEXT        
   ,@Password    NVARCHAR(30) 
   ,@Encoding    NVARCHAR(10) 
   ,@Homepage    NVARCHAR(100)
   ,@FileName    NVARCHAR(255)
   ,@FileSize    INT          
   ,@ID          INT
AS
    DECLARE @Count INT

    SELECT @Count = Count(*)
    FROM   dbo.Notice
    WHERE  ID         = @ID
    AND    [Password] = @Password;

    IF @Count > 0
    BEGIN
        UPDATE dbo.Notice
        SET
            [Name]      = @Name
           ,MailAddress = @MailAddress
           ,Title       = @Title
           ,UpdateIP    = @UpdateIP
           ,UpdateDate  = GETDATE()
           ,Content     = @Content
           ,[Encoding]  = @Encoding
           ,Homepage    = @Homepage
           ,[FileName]  = @FileName
           ,FileSize    = @FileSize
        Where ID = @ID;

        SELECT '1';
    END
    ELSE
        SELECT '0';
GO

CREATE PROCEDURE dbo.SearchNotice
    @Page        INT
   ,@SearchField NVARCHAR(25)
   ,@SearchQuery NVARCHAR(25)
AS
    WITH OrderedNoticeBoard
    AS
    (
        SELECT
            ID
           ,[Name]
           ,MailAddress
           ,Title
           ,WriteDate
           ,ReadCount
           ,ReferenceID
           ,ReplyLevel
           ,ReplyOrder
           ,ReplyCount
           ,ParentID
           ,CommentCount
           ,[FileName]
           ,FileSize
           ,DownloadCount
           ,ROW_NUMBER() OVER (ORDER BY ReferenceID DESC, ReplyOrder ASC) AS 'RowNumber'
        FROM dbo.Notice
        WHERE
        (
            CASE @SearchField
                WHEN 'Name'    THEN [Name]
                WHEN 'Title'   THEN Title
                WHEN 'Content' THEN Content
                ELSE                @SearchQuery
            END
        )
        LIKE '%' + @SearchQuery + '%'
    )
    SELECT
        ID
       ,[Name]
       ,MailAddress
       ,Title
       ,WriteDate
       ,ReadCount
       ,ReferenceID
       ,ReplyLevel
       ,ReplyOrder
       ,ReplyCount
       ,ParentID
       ,CommentCount
       ,[FileName]
       ,FileSize
       ,DownloadCount
       ,RowNumber
    FROM  OrderedNoticeBoard
    WHERE RowNumber BETWEEN @Page * 10 + 1 AND (@Page + 1) * 10
    ORDER BY ID DESC;
GO

 

728x90

 

▶ CommentControl.ascx

<%@ Control
    Language="C#"
    AutoEventWireup="true" 
    CodeBehind="CommentControl.ascx.cs" 
    Inherits="TestProject.NoticeBoard.Controls.CommentControl" %>
<asp:Repeater ID="repeater" runat="server">
    <HeaderTemplate>
        <table style="margin-left:20px;margin-right:20px;width:95%;padding:10px;">
    </HeaderTemplate>
    <ItemTemplate>
        <tr style="border-bottom:1px dotted silver;">
            <td style="width:80px;"><%# Eval("Name") %></td>
            <td style="width:350px;"><%# TestProject.HTMLHelper.Encode(Eval("Comment").ToString()) %></td>
            <td style="width:180px;"><%# Eval("WriteDate") %></td>
            <td style="width:10px;text-align:center;">
                <a title="댓글 삭제" href='CommentDeletePage.aspx?NoticeID=<%= Request["ID"] %>&ID=<%# Eval("ID") %>'>
                    <img border="0" src="/Image/NoticeBoard/delete.gif" />
                </a>
            </td>
        </tr>
    </ItemTemplate>
    <FooterTemplate>
        </table>
    </FooterTemplate>
</asp:Repeater>
<table style="margin-left:auto;width:500px;">
    <tr>
        <td style="width:64px;text-align:right;">성명&nbsp;</td>
        <td style="width:128px;">
            <asp:TextBox ID="nameTextBox" runat="server"
                CssClass="form-control"
                Style="display:inline-block;"
                Width="128px" />
        </td>
        <td style="width:64px;text-align:right;">패스워드&nbsp;</td>
        <td style="width:128px;">
            <asp:TextBox ID="passwordTextBox" runat="server" 
                CssClass="form-control"
                Style="display:inline-block;"
                Width="128px"
                TextMode="Password" />
        </td>
        <td style="width:128px;text-align:right;">
            <asp:Button ID="writeButton" runat="server" 
                CssClass="form-control btn btn-primary" 
                Style="display: inline-block;"
                Width="96px"
                Text="의견 남기기"
                OnClick="writeButton_Click" />
        </td>
    </tr>
    <tr>
        <td style="width:64px;text-align:right;">댓글&nbsp;</td>
        <td style="width:448px;" colspan="4">
            <asp:TextBox ID="commentTextBox" runat="server" 
                CssClass="form-control" 
                Style="display:inline-block;"
                Width="448px"
                Rows="3"
                Columns="70"
                TextMode="MultiLine" />
        </td>
    </tr>
</table>
<hr />

 

300x250

 

▶ CommentControl.ascx.cs

using System;
using System.Web.UI;

using NoticeBoard.Models;

namespace TestProject.NoticeBoard.Controls
{
    /// <summary>
    /// 댓글 컨트롤
    /// </summary>
    public partial class CommentControl : UserControl
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 댓글 저장소
        /// </summary>
        private CommentRepository repository;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - CommentControl()

        /// <summary>
        /// 생성자
        /// </summary>
        public CommentControl()
        {
            this.repository = new CommentRepository();
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Protected

        #region 페이지 로드시 처리하기 - Page_Load(sender, e)

        /// <summary>
        /// 페이지 로드시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        protected void Page_Load(object sender, EventArgs e)
        {
            if(!Page.IsPostBack)
            {
                this.repeater.DataSource = this.repository.GetCommentList(Convert.ToInt32(Request["ID"]));

                this.repeater.DataBind();
            }
        }

        #endregion
        #region 의견 남기기 버튼 클릭시 처리하기 - writeButton_Click(sender, e)

        /// <summary>
        /// 의견 남기기 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        protected void writeButton_Click(object sender, EventArgs e)
        {
            CommentModel comment = new CommentModel();

            comment.NoticeID  = Convert.ToInt32(Request["ID"]);
            comment.Name     = this.nameTextBox.Text;
            comment.Password = this.passwordTextBox.Text;
            comment.Comment  = this.commentTextBox.Text;

            this.repository.AddComment(comment);

            Response.Redirect($"{Request.ServerVariables["SCRIPT_NAME"]}?ID={Request["ID"]}");
        }

        #endregion
    }
}

 

▶ EditorControl.ascx

<%@ Control
    Language="C#"
    AutoEventWireup="true" 
    CodeBehind="EditorControl.ascx.cs" 
    Inherits="TestProject.NoticeBoard.Controls.EditorControl" %>
<style>
.BoardWriteFormTableLeftStyle
{
    width      : 100px;
    text-align : right;
}
</style>
<h2 style="text-align:center;">게시판</h2>
<asp:Label ID="titleDescriptionLabel" runat="server"
    ForeColor="#ff0000" />
<hr />
<table
    style="margin-left:auto;margin-right:auto;width:600px;border-collapse:collapse;padding:5px;">
    <% if(!string.IsNullOrEmpty(Request.QueryString["ID"]) && FormType == NoticeBoard.Models.BoardWriteFormType.Modify) { %>    
    <tr>
        <td class="BoardWriteFormTableLeftStyle">
            <span style="color: #ff0000;">*</span>ID
        </td>
        <td style="width:500px;">
            <%= Request.QueryString["ID"] %>
        </td>
    </tr>
    <% } %>
    <tr>
        <td class="BoardWriteFormTableLeftStyle"><span style="color: #ff0000;">*</span>성명</td>
        <td style="width:500px;">
            <asp:TextBox ID="nameTextBox" runat="server"
                CssClass="form-control"
                MaxLength="10" 
                Width="150px" />
            <asp:RequiredFieldValidator ID="nameRequiredFieldValidator" runat="server"
                ControlToValidate="nameTextBox"
                Display="None" 
                SetFocusOnError="True"
                ErrorMessage="* 성명을 입력해 주시기 바랍니다." />
        </td>
    </tr>
    <tr>
        <td style="text-align:right;">메일 주소</td>
        <td>
            <asp:TextBox ID="mailAddressTextBox" runat="server"
                CssClass="form-control" 
                style="display:inline-block;"
                MaxLength="80"
                Width="200px" />
            <span style="color:#aaaaaa;font-style:italic">(선택 사항)</span>
            <asp:RegularExpressionValidator ID="mailAddressRegularExpressionValidator" runat="server"
                ControlToValidate="mailAddressTextBox"
                ValidationExpression="\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*"
                Display="None" 
                SetFocusOnError="True"
                ErrorMessage="* 메일 주소를 입력해 주시기 바랍니다." />
        </td>
    </tr>
    <tr>
        <td style="text-align:right;">홈페이지</td>
        <td>
            <asp:TextBox ID="homepageTextBox" runat="server" 
                CssClass="form-control"
                style="display:inline-block;" 
                MaxLength="80"
                Width="300px" />
            <span style="color:#aaaaaa;font-style:italic;">(선택 사항)</span>
            <asp:RegularExpressionValidator ID="homepageRegularExpressionValidator" runat="server" 
                ControlToValidate="homepageTextBox"
                ValidationExpression="http://([\w-]+\.)+[\w-]+(/[\w- ./?%&amp;=]*)?"
                Display="None"
                SetFocusOnError="True"
                ErrorMessage="* 홈페이지를 입력해 주시기 바랍니다." />
        </td>
    </tr>
    <tr>
        <td style="text-align:right;"><span style="color: #ff0000;">*</span>제목</td>
        <td>
            <asp:TextBox ID="titleTextBox" runat="server" CssClass="form-control" 
                Width="480px"></asp:TextBox>
            <asp:RequiredFieldValidator ID="titleRequiredFieldValidator" runat="server" 
                ControlToValidate="titleTextBox"
                Display="None" 
                SetFocusOnError="True"
                ErrorMessage="* 제목을 입력해 주시기 바랍니다." />
        </td>
    </tr>
    <tr>
        <td style="text-align:right;"><span style="color: #ff0000;">*</span>내용</td>
        <td>
            <asp:TextBox ID="contentTextBox" runat="server" 
                CssClass="form-control" 
                style="display:inline-block;"
                Width="480px"
                Height="150px"
                TextMode="MultiLine" />
            <asp:RequiredFieldValidator ID="contentRequiredFieldValidator" runat="server" 
                ControlToValidate="contentTextBox"
                Display="None" 
                SetFocusOnError="True"
                ErrorMessage="* 내용을 입력해 주시기 바랍니다." />
        </td>
    </tr>
    <tr>
        <td style="text-align:right;">파일 첨부</td>
        <td>
            <asp:CheckBox ID="uploadCheckBox" runat="server"
                CssClass="check-inline" 
                AutoPostBack="True"
                Text="체크 박스를 체크하면 업로드 화면이 표시됩니다." 
                OnCheckedChanged="uploadCheckBox_CheckedChanged" />
            <span style="color:#aaaaaa;font-style:italic">(선택 사항)</span>
            <br />
            <asp:Panel ID="filePanel" runat="server"
                Width="480px" 
                Height="25px"
                Visible="false">
                <input id="fileNameButton" runat="server"
                    style="width:290px;height:22px"
                    name="fileNameTextBox"
                    type="file" />
                <asp:label ID="previousFileNameLabel" runat="server"
                    text=""
                    Visible="false" />
            </asp:Panel>
        </td>
    </tr>
    <tr>
        <td style="text-align:right;"><span style="color: #ff0000;">*</span>인코딩</td>
        <td>
            <asp:RadioButtonList ID="encodingRadioButtonList" runat="server" 
                RepeatDirection="Horizontal"
                RepeatLayout="Flow">
                <asp:ListItem Value="Text" Selected="True">텍스트</asp:ListItem>
                <asp:ListItem Value="HTML">HTML</asp:ListItem>
                <asp:ListItem Value="Mixed">혼합</asp:ListItem>
            </asp:RadioButtonList>
        </td>
    </tr>
    <tr>
        <td style="text-align:right;"><span style="color: #ff0000;">*</span>패스워드</td>
        <td>
            <asp:TextBox ID="passwordTextBox" runat="server"
                CssClass="form-control" 
                style="display:inline-block;"
                MaxLength="20"
                Width="150px" 
                TextMode="Password"
                EnableViewState="False" />
            <span style=" color: #aaaaaa;">(수정/삭제시 필요)</span>
            <asp:RequiredFieldValidator ID="passwordRequiredFieldValidator" runat="server"
                ControlToValidate="passwordTextBox"
                Display="None" 
                SetFocusOnError="True"
                ErrorMessage="* 패스워드를 입력해 주시기 바랍니다." />
        </td>
    </tr>
    <%  if(!Page.User.Identity.IsAuthenticated) { %>
    <tr>
        <td style="text-align:right;"><span style="color: #ff0000;">*</span>보안코드</td>
        <td>
            <asp:TextBox ID="imageTextTextBox" runat="server" 
                CssClass="form-control" 
                style="display:inline-block;" 
                MaxLength="20" 
                Width="150px"
                EnableViewState="False" />
            <span style=" color: #aaaaaa;">(아래에 제시되는 보안코드를 입력하십시오.)</span>
            <br />
            <asp:Image ID="imageTextImage" runat="server" 
                ImageUrl="~/NoticeBoard/ImageTextPage.aspx" />
            <asp:Label ID="errorLabel" runat="server"
                ForeColor="Red" />
        </td>
    </tr>
    <% } %>
    <tr>
        <td colspan="2" style="text-align:center;">
            <asp:Button ID="saveButton" runat="server"
                CssClass="btn btn-primary"
                Text="저장" 
                OnClick="saveButton_Click" />
            <a class="btn btn-default" href="NoticeListPage.aspx">목록</a>
            <br />
            <asp:ValidationSummary ID="validationSummary" runat="server" 
                ShowSummary="False"
                ShowMessageBox="True"
                DisplayMode="List" />
            <br />
        </td>
    </tr>
</table>

 

▶ EditorControl.ascx.cs

using System;
using System.IO;
using System.Web.UI;

using NoticeBoard.Models;

namespace TestProject.NoticeBoard.Controls
{
    /// <summary>
    /// 에디터 컨트롤
    /// </summary>
    public partial class EditorControl : UserControl
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// ID
        /// </summary>
        private string id;

        /// <summary>
        /// 업로드 디렉토리 경로
        /// </summary>
        private string uploadDirectoryPath = string.Empty;

        /// <summary>
        /// 파일명
        /// </summary>
        private string fileName = string.Empty;

        /// <summary>
        /// 파일 크기
        /// </summary>
        private int fileSize = 0;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 폼 타입 - FormType

        /// <summary>
        ///  폼 타입
        /// </summary>
        public BoardWriteFormType FormType { get; set; }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Protected

        #region 페이지 로드시 처리하기 - Page_Load(sender, e)

        /// <summary>
        /// 페이지 로드시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        protected void Page_Load(object sender, EventArgs e)
        {
            this.id = Request.QueryString["ID"];

            if(!Page.IsPostBack)
            {
                switch(FormType)
                {
                    case BoardWriteFormType.Write :

                        this.titleDescriptionLabel.Text = "글 쓰기 - 아래 항목을 입력해 주시기 바랍니다.";

                        break;

                    case BoardWriteFormType.Modify :

                        this.titleDescriptionLabel.Text = "글 수정 - 아래 항목을 입력해 주시기 바랍니다.";

                        DisplayDataForUpdate();

                        break;

                    case BoardWriteFormType.Reply :

                        this.titleDescriptionLabel.Text = "글 답변 - 아래 항목을 입력해 주시기 바랍니다.";

                        DisplayDataForReply();

                        break;
                }
            }
        }

        #endregion
        #region 업로드 체크 박스 체크 변경시 처리하기 - uploadCheckBox_CheckedChanged(sender, e)

        /// <summary>
        /// 업로드 체크 박스 체크 변경시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        protected void uploadCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            this.filePanel.Visible = !this.filePanel.Visible;
        }

        #endregion
        #region 저장 버튼 클릭시 처리하기 - saveButton_Click(object sender, EventArgs e)

        /// <summary>
        /// 저장 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        protected void saveButton_Click(object sender, EventArgs e)
        {
            if(ValidateSecurtyImageText())
            {
                UploadFile();

                NoticeModel notice = new NoticeModel();

                notice.ID          = Convert.ToInt32(this.id);
                notice.Name        = this.nameTextBox.Text;
                notice.MailAddress = HTMLHelper.Encode(this.mailAddressTextBox.Text);
                notice.Homepage    = this.homepageTextBox.Text;
                notice.Title       = HTMLHelper.Encode(this.titleTextBox.Text);
                notice.Content     = this.contentTextBox.Text;
                notice.FileName    = this.fileName;
                notice.FileSize    = this.fileSize;
                notice.Password    = this.passwordTextBox.Text;
                notice.WriteIP     = Request.UserHostAddress;
                notice.Encoding    = this.encodingRadioButtonList.SelectedValue;

                NoticeRepository repository = new NoticeRepository();

                switch(FormType)
                {
                    case BoardWriteFormType.Write :

                        repository.Add(notice);

                        Response.Redirect("NoticeListPage.aspx");

                        break;

                    case BoardWriteFormType.Modify :

                        notice.UpdateIP = Request.UserHostAddress;
                        notice.FileName = ViewState["FileName"].ToString();
                        notice.FileSize = Convert.ToInt32(ViewState["FileSize"]);

                        int recordCount = repository.Update(notice);

                        if(recordCount > 0)
                        {
                            Response.Redirect($"NoticeViewPage.aspx?ID={this.id}");
                        }
                        else
                        {
                            this.errorLabel.Text = "수정을 실패했습니다. 암호를 확인해 주시기 바랍니다.";
                        }

                        break;

                    case BoardWriteFormType.Reply :

                        notice.ParentID = Convert.ToInt32(this.id);

                        repository.Reply(notice);

                        Response.Redirect("NoticeListPage.aspx");

                        break;

                    default :

                        repository.Add(notice);

                        Response.Redirect("NoticeListPage.aspx");

                        break;
                }
            }
            else
            {
                this.errorLabel.Text = "보안코드가 일치하지 않습니다.. 다시 입력해 주시기 바랍니다.";
            }
        }

        #endregion

        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region 수정용 데이터 표시하기 - DisplayDataForUpdate()

        /// <summary>
        /// 수정용 데이터 표시하기
        /// </summary>
        private void DisplayDataForUpdate()
        {
            NoticeModel notice = (new NoticeRepository()).Get(Convert.ToInt32(this.id));

            this.nameTextBox.Text        = notice.Name;
            this.mailAddressTextBox.Text = notice.MailAddress;
            this.homepageTextBox.Text    = notice.Homepage;
            this.titleTextBox.Text       = notice.Title;
            this.contentTextBox.Text     = notice.Content;

            string ecoding = notice.Encoding;

            if(ecoding == "Text")
            {
                this.encodingRadioButtonList.SelectedIndex = 0;
            }
            else if(ecoding == "Mixed")
            {
                this.encodingRadioButtonList.SelectedIndex = 2;
            }
            else
            {
                this.encodingRadioButtonList.SelectedIndex = 1;
            }

            if(notice.FileName.Length > 1)
            {
                ViewState["FileName"] = notice.FileName;
                ViewState["FileSize"] = notice.FileSize;

                this.filePanel.Height = 50;

                this.previousFileNameLabel.Visible = true;
                this.previousFileNameLabel.Text    = $"기존 업로드 파일명 : {notice.FileName}";
            }
            else
            {
                ViewState["FileName"] = "";
                ViewState["FileSize"] = 0;
            }
        }

        #endregion
        #region 답변용 데이터 표시하기 - DisplayDataForReply()

        /// <summary>
        /// 답변용 데이터 표시하기
        /// </summary>
        private void DisplayDataForReply()
        {
            NoticeModel notice = (new NoticeRepository()).Get(Convert.ToInt32(this.id));

            this.titleTextBox.Text = $"Re : {notice.Title}";

            this.contentTextBox.Text = $"\n\nOn {notice.WriteDate}, '{notice.Name}' wrote:\n----------\n>{notice.Content.Replace("\n", "\n>")}\n---------";
        }

        #endregion
        #region 보안 이미지 텍스트 검증하기 - ValidateSecurtyImageText()

        /// <summary>
        /// 보안 이미지 텍스트 검증하기
        /// </summary>
        private bool ValidateSecurtyImageText()
        {
            if(Page.User.Identity.IsAuthenticated)
            {
                return true;
            }
            else
            {
                if(Session["ImageText"] != null)
                {
                    return (this.imageTextTextBox.Text == Session["ImageText"].ToString());
                }
            }

            return false;
        }

        #endregion
        #region 파일 업로드하기 - UploadFile()

        /// <summary>
        /// 파일 업로드하기
        /// </summary>
        private void UploadFile()
        {
            this.uploadDirectoryPath = Server.MapPath("~/FileUpload");
            this.fileName            = string.Empty;
            this.fileSize            = 0;

            if(this.fileNameButton.PostedFile != null)
            {
                if(this.fileNameButton.PostedFile.FileName.Trim().Length > 0 && this.fileNameButton.PostedFile.ContentLength > 0)
                {
                    if(FormType == BoardWriteFormType.Modify)
                    {
                        ViewState["FileName"] = FileHelper.GetUniqueFileName
                        (
                            this.uploadDirectoryPath,
                            Path.GetFileName(this.fileNameButton.PostedFile.FileName)
                        );

                        ViewState["FileSize"] = this.fileNameButton.PostedFile.ContentLength;

                        this.fileNameButton.PostedFile.SaveAs
                        (
                            Path.Combine
                            (
                                this.uploadDirectoryPath,
                                ViewState["FileName"].ToString()
                            )
                        );
                    }
                    else
                    {
                        this.fileName = FileHelper.GetUniqueFileName
                        (
                            this.uploadDirectoryPath,
                            Path.GetFileName(this.fileNameButton.PostedFile.FileName)
                        );

                        this.fileSize = this.fileNameButton.PostedFile.ContentLength;

                        this.fileNameButton.PostedFile.SaveAs(Path.Combine(this.uploadDirectoryPath, this.fileName));
                    }
                }
            }
        }

        #endregion
    }
}

 

▶ PagingControl.ascx

<%@ Control
    Language="C#"
    AutoEventWireup="true" 
    CodeBehind="PagingControl.ascx.cs" 
    Inherits="TestProject.NoticeBoard.Controls.PagingControl" %>
<asp:Literal ID="pagingLiteral" runat="server" />

 

▶ PagingControl.ascx.cs

using System;
using System.ComponentModel;
using System.Web.UI;

namespace TestProject.NoticeBoard.Controls
{
    /// <summary>
    /// 페이징 컨트롤
    /// </summary>
    public partial class PagingControl : UserControl
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 레코드 수
        /// </summary>
        private int recordCount;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 검색 모드 - SearchMode

        /// <summary>
        /// 검색 모드
        /// </summary>
        public bool SearchMode { get; set; } = false;

        #endregion
        #region 검색 필드 - SearchField

        /// <summary>
        /// 검색 필드
        /// </summary>
        public string SearchField { get; set; }

        #endregion
        #region 검색 쿼리 - SearchQuery

        /// <summary>
        /// 검색 쿼리
        /// </summary>
        public string SearchQuery { get; set; }

        #endregion
        #region 페이지 인덱스 - PageIndex

        /// <summary>
        /// 페이지 인덱스
        /// </summary>
        [Category("PagingControl")]
        public int PageIndex { get; set; }

        #endregion
        #region 페이지 수 - PageCount

        /// <summary>
        /// 페이지 수
        /// </summary>
        [Category("PagingControl")]
        public int PageCount { get; set; }

        #endregion
        #region 페이지 크기 - PageSize

        /// <summary>
        /// 페이지 크기
        /// </summary>
        [Category("PagingControl")]
        public int PageSize { get; set; } = 10;

        #endregion
        #region 레코드 수 - RecordCount

        /// <summary>
        /// 레코드 수
        /// </summary>
        [Category("PagingControl")]
        public int RecordCount
        {
            get
            {
                return this.recordCount;
            }
            set
            {
                this.recordCount = value;

                PageCount = ((this.recordCount - 1) / PageSize) + 1;
            }
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Protected

        #region 페이지 로드시 처리하기 - Page_Load(sender, e)

        /// <summary>
        /// 페이지 로드시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        protected void Page_Load(object sender, EventArgs e)
        {
            SearchMode = (!string.IsNullOrEmpty(Request.QueryString["SearchField"]) && !string.IsNullOrEmpty(Request.QueryString["SearchQuery"]));

            if(SearchMode)
            {
                SearchField = Request.QueryString["SearchField"];
                SearchQuery = Request.QueryString["SearchQuery"];
            }

            PageIndex++;

            int i;

            string html = "<ul class='pagination pagination-sm'>";

            if(PageIndex > 10)
            {
                if(SearchMode)
                {
                    html += "<li><a href=\""                                   +
                            Request.ServerVariables["SCRIPT_NAME"]             +
                            "?Page="                                           +
                            Convert.ToString(((PageIndex - 1) / (int)10) * 10) +
                            "&SearchField="                                    +
                            SearchField                                        +
                            "&SearchQuery="                                    +
                            SearchQuery                                        +
                            "\">◀</a></li>";
                }
                else
                {
                    html += "<li><a href=\""                                   +
                            Request.ServerVariables["SCRIPT_NAME"]             +
                            "?Page="                                           +
                            Convert.ToString(((PageIndex - 1) / (int)10) * 10) +
                            "\">◀</a></li>";
                }
            }
            else
            {
                html += "<li class=\"disabled\"><a>◁</a></li>";
            }

            for(i = (((PageIndex - 1) / (int)10) * 10 + 1); i <= ((((PageIndex - 1) / (int)10) + 1) * 10); i++)
            {
                if(i > PageCount)
                {
                    break;
                }

                if(i == PageIndex)
                {
                    html += " <li class='active'><a href='#'>" + i.ToString() + "</a></li>";
                }
                else
                {
                    if(SearchMode)
                    {
                        html += "<li><a href=\""                       +
                                Request.ServerVariables["SCRIPT_NAME"] +
                                "?Page="                               +
                                i.ToString()                           +
                                "&SearchField="                        +
                                SearchField                            +
                                "&SearchQuery="                        +
                                SearchQuery                            +
                                "\">"                                  +
                                i.ToString()                           +
                                "</a></li>";
                    }
                    else
                    {
                        html += "<li><a href=\""                       +
                                Request.ServerVariables["SCRIPT_NAME"] +
                                "?Page="                               +
                                i.ToString()                           +
                                "\">"                                  +
                                i.ToString()                           +
                                "</a></li>";
                    }
                }
            }

            if(i < PageCount)
            {
                if(SearchMode)
                {
                    html += "<li><a href=\""                                        +
                            Request.ServerVariables["SCRIPT_NAME"]                  +
                            "?Page="                                                +
                            Convert.ToString(((PageIndex - 1) / (int)10) * 10 + 11) +
                            "&SearchField="                                         +
                            SearchField                                             +
                            "&SearchQuery="                                         +
                            SearchQuery                                             +
                            "\">▶</a></li>";
                }
                else
                {
                    html += "<li><a href=\""                                        +
                            Request.ServerVariables["SCRIPT_NAME"]                  +
                            "?Page="                                                +
                            Convert.ToString(((PageIndex - 1) / (int)10) * 10 + 11) +
                            "\">▶</a></li>";
                }
            }
            else
            {
                html += "<li class=\"disabled\"><a>▷</a></li>";
            }

            html += "</ul>";

            this.pagingLiteral.Text = html;
        }

        #endregion
    }
}

 

▶ SearchControl.ascx

<%@ Control
    Language="C#"
    AutoEventWireup="true" 
    CodeBehind="SearchControl.ascx.cs" 
    Inherits="TestProject.NoticeBoard.Controls.SearchControl" %>
<div style="text-align:center;">
    <asp:DropDownList ID="searchFieldDropDownList" runat="server"
        CssClass="form-control"
        Style="display:inline-block;"
        Width="80px">
        <asp:ListItem Value="Name">성명</asp:ListItem>
        <asp:ListItem Value="Title">제목</asp:ListItem>
        <asp:ListItem Value="Content">내용</asp:ListItem>
    </asp:DropDownList>&nbsp;
    <asp:TextBox ID="searchQueryTextBox" runat="server"
        CssClass="form-control"
        Style="display: inline-block;"
        Width="200px" />&nbsp;
    <asp:RequiredFieldValidator ID="searchQueryRequiredFieldValidator" runat="server" 
        ControlToValidate="searchQueryTextBox"
        Display="None" 
        ErrorMessage="검색할 단어를 입력하세요." />
    <asp:ValidationSummary ID="validationSummary" runat="server" 
        ShowSummary="False"
        ShowMessageBox="True" />
    <asp:Button ID="searchButton" runat="server"
        CssClass="form-control"
        Style="display:inline-block;"
        Width="100px" 
        Text="검색" 
        OnClick="searchButton_Click" />
</div>
<br />
<% if(!string.IsNullOrEmpty(Request.QueryString["SearchField"]) && !String.IsNullOrEmpty(Request.QueryString["SearchQuery"])) { %>
<div style="text-align:center;">
    <a class="btn btn-success" href="/NoticeBoard/NoticeListPage.aspx">검색 완료</a>
</div>
<% } %>

 

▶ SearchControl.ascx.cs

using System;
using System.Web.UI;

namespace TestProject.NoticeBoard.Controls
{
    /// <summary>
    /// 검색 컨트롤
    /// </summary>
    public partial class SearchControl : UserControl
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Protected

        #region 페이지 로드시 처리하기 - Page_Load(sender, e)

        /// <summary>
        /// 페이지 로드시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        protected void Page_Load(object sender, EventArgs e)
        {
        }

        #endregion
        #region 검색 버튼 클릭시 처리하기 - searchButton_Click(sender, e)

        /// <summary>
        /// 검색 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        protected void searchButton_Click(object sender, EventArgs e)
        {
            string url = string.Format
            (
                "/NoticeBoard/NoticeListPage.aspx?SearchField={0}&SearchQuery={1}", 
                this.searchFieldDropDownList.SelectedItem.Value,
                this.searchQueryTextBox.Text
            );

            Response.Redirect(url);
        }

        #endregion
    }
}

 

▶ CommentDeletePage.aspx

<%@ Page
    Language="C#"
    MasterPageFile="~/Site.Master"
    AutoEventWireup="true"
    CodeBehind="CommentDeletePage.aspx.cs"
    Inherits="TestProject.NoticeBoard.CommentDeletePage"
    Title="댓글 삭제 페이지" %>
<asp:Content ID="content" ContentPlaceHolderID="MainContent" runat="server">
    <h2 style="text-align: center;">게시판</h2>
    <span style="color: #ff0000">댓글 삭제 - 패스워드를 입력하면 댓글을 삭제할 수 있습니다.</span>
    <hr />
    <table style="width:500px;margin-left:auto;margin-right:auto;">
        <tr>
            <td colspan="2">
                <i class="glyphicon glyphicon-lock"></i>
                <span style="font-size:12pt;">댓글 삭제</span>
            </td>
        </tr>
        <tr>
            <td>&nbsp;</td>
            <td>
                <span>해당 댓글을 삭제하시려면 패스워드를 입력해 주시기 바랍니다.</span>
                <br />
                패스워드(<u>P</u>):
                <asp:TextBox ID="passwordTextBox" runat="server"
                    CssClass="form-control"
                    Style="display:inline-block;"
                    MaxLength="40"
                    Width="250px"
                    TextMode="Password"
                    AccessKey="P"
                    TabIndex="2" />
            </td>
        </tr>
        <tr>
            <td colspan="2" style="text-align:center;">
                <asp:Button ID="deleteButton" runat="server"
                    CssClass="btn btn-danger"
                    Text="삭제"
                    OnClick="deleteButton_Click" />
                <asp:RequiredFieldValidator ID="passwordRequiredFieldValidator" runat="server"
                    ControlToValidate="passwordTextBox"
                    Display="None"
                    ErrorMessage="패스워드를 입력해 주시기 바랍니다." />
                <asp:ValidationSummary ID="validationSummary" runat="server"
                    ShowMessageBox="true"
                    ShowSummary="false" />
                <input type="button"
                    class="btn btn-default"
                    value="이전으로" 
                    onclick="history.go(-1);" />
                <br />
                <asp:Label ID="errorLabel" runat="server"
                    ForeColor="Red" />
            </td>
        </tr>
    </table>
</asp:Content>

 

▶ CommentDeletePage.aspx.cs

using System;
using System.Web.UI;

using NoticeBoard.Models;

namespace TestProject.NoticeBoard
{
    /// <summary>
    /// 댓글 삭제 페이지
    /// </summary>
    public partial class CommentDeletePage : Page
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Property
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 게시글 ID - NoticeID

        /// <summary>
        /// 게시글 ID
        /// </summary>
        public int NoticeID { get; set; }

        #endregion
        #region 댓글 ID - ID

        /// <summary>
        /// 댓글 ID
        /// </summary>
        public int ID { get; set; }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Protected

        #region 페이지 로드시 처리하기 - Page_Load(sender, e)

        /// <summary>
        /// 페이지 로드시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        protected void Page_Load(object sender, EventArgs e)
        {
            if(Request["NoticeID"] != null && Request.QueryString["ID"] != null)
            {
                NoticeID = Convert.ToInt32(Request["NoticeID"]);
                ID       = Convert.ToInt32(Request["ID"      ]);
            }
            else
            {
                Response.End();
            }
        }

        #endregion
        #region 삭제 버튼 클릭시 처리하기 - deleteButton_Click(sender, e)

        /// <summary>
        /// 삭제 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        protected void deleteButton_Click(object sender, EventArgs e)
        {
            CommentRepository repository = new CommentRepository();

            if(repository.GetCommentCount(NoticeID, ID, this.passwordTextBox.Text) > 0)
            {
                repository.DeleteComment(NoticeID, ID, this.passwordTextBox.Text);

                Response.Redirect($"NoticeViewPage.aspx?ID={NoticeID}");
            }
            else
            {
                this.errorLabel.Text = "패스워드가 일치하지 않습니다. 다시 입력해 주시기 바랍니다.";
            }
        }

        #endregion
    }
}

 

▶ ImageDownloadPage.aspx

<%@ Page
    Language="C#"
    AutoEventWireup="true"
    CodeBehind="ImageDownloadPage.aspx.cs"
    Inherits="TestProject.NoticeBoard.ImageDownloadPage" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title></title>
    </head>
    <body>
        <form id="form" runat="server">
            <div>
            </div>
        </form>
    </body>
</html>

 

▶ ImageDownloadPage.aspx.cs

using System;
using System.IO;
using System.Web.UI;

namespace TestProject.NoticeBoard
{
    /// <summary>
    /// 이미지 다운로드 페이지
    /// </summary>
    public partial class ImageDownloadPage : Page
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Protected

        #region 페이지 로드시 처리하기 - Page_Load(sender, e)

        /// <summary>
        /// 페이지 로드시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        protected void Page_Load(object sender, EventArgs e)
        {
            if(string.IsNullOrEmpty(Request.QueryString["FileName"]))
            {
                Response.End();
            }

            string fileName      = Request.Params["FileName"].ToString();
            string fileExtension = Path.GetExtension(fileName);
            string contentType   = string.Empty;

            if(fileExtension == ".gif" || fileExtension == ".jpg" || fileExtension == ".jpeg" || fileExtension == ".png")
            {
                switch(fileExtension)
                {
                    case ".gif"  : contentType = "image/gif";  break;
                    case ".jpg"  : contentType = "image/jpeg"; break;
                    case ".jpeg" : contentType = "image/jpeg"; break;
                    case ".png"  : contentType = "image/png";  break;
                }
            }
            else
            {
                Response.Write("<script language='javascript'>alert('이미지 파일이 아닙니다.');</script>");

                Response.End();
            }

            string filePath = Server.MapPath("~/FileUpload/") + fileName;

            Response.Clear();

            Response.ContentType = contentType;

            Response.WriteFile(filePath);

            Response.End();
        }

        #endregion
    }
}

 

▶ ImageTextPage.aspx

<%@ Page
    Language="C#"
    AutoEventWireup="true"
    CodeBehind="ImageTextPage.aspx.cs"
    Inherits="TestProject.NoticeBoard.ImageTextPage" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
            <div>
            </div>
        </form>
    </body>
</html>

 

▶ ImageTextPage.aspx.cs

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.Web.UI;

namespace TestProject.NoticeBoard
{
    /// <summary>
    /// 이미지 텍스트 페이지
    /// </summary>
    public partial class ImageTextPage : Page
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Protected

        #region 페이지 로드시 처리하기 - Page_Load(sender, e)

        /// <summary>
        /// 페이지 로드시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        protected void Page_Load(object sender, EventArgs e)
        {
            Bitmap bitmap = new Bitmap(80, 20);

            Graphics graphics = Graphics.FromImage(bitmap);

            graphics.Clear(Color.White);

            graphics.SmoothingMode     = SmoothingMode.HighSpeed;
            graphics.TextRenderingHint = TextRenderingHint.AntiAlias;

            Random random = new Random();

            char character1 = (char)random.Next(65, 90 );
            char character2 = (char)random.Next(48, 57 );
            char character3 = (char)random.Next(97, 122);
            char character4 = (char)random.Next(48, 57 );

            Session["ImageText"] = $"{character1}{character2}{character3}{character4}";

            graphics.DrawString(character1.ToString(), new Font("Verdana", 12, FontStyle.Bold     ), Brushes.DarkBlue, new PointF(5 , 1));
            graphics.DrawString(character2.ToString(), new Font("Arial"  , 11, FontStyle.Italic   ), Brushes.DarkBlue, new PointF(25, 1));
            graphics.DrawString(character3.ToString(), new Font("Verdana", 11, FontStyle.Regular  ), Brushes.DarkBlue, new PointF(45, 1));
            graphics.DrawString(character4.ToString(), new Font("Arial"  , 12, FontStyle.Underline), Brushes.DarkBlue, new PointF(65, 1));

            Response.ContentType = "image/gif";

            bitmap.Save(Response.OutputStream, ImageFormat.Gif);

            bitmap.Dispose();

            graphics.Dispose();
        }

        #endregion
    }
}

 

▶ NoticeDeletePage.aspx

<%@ Page
    Language="C#"
    MasterPageFile="~/Site.Master" 
    AutoEventWireup="true"
    CodeBehind="NoticeDeletePage.aspx.cs" 
    Inherits="TestProject.NoticeBoard.NoticeDeletePage"
    Title="게시글 삭제" %>
<asp:Content ID="content" ContentPlaceHolderID="MainContent" runat="server">
    <script>
        function ConfirmDelete()
        {
            var canDelete = false;

            if(window.confirm("현재 글을 삭제하시겠습니까?"))
            {
                canDelete = true;
            }
            else
            {
                canDelete = false;
            }

            return canDelete;
        }
    </script>
    <h2 style="text-align: center;">게시판</h2>
    <span style="color: #ff0000">글 삭제 - 글을 삭제하려면 글 작성시에 함께 저장한 패스워드가 필요합니다.</span>
    <hr />
    <div style="text-align:center;">
        <asp:Label ID="idLabel" runat="server"
            ForeColor="Red" />
        번 글을 지우시겠습니까?
        <br />
        패스워드 :
        <asp:TextBox ID="passwordTextBox" runat="server"
            CssClass="form-control"
            Style="display: inline-block;" 
            Width="120px" 
            TextMode="Password" />
        <asp:Button ID="deleteButton" runat="server"
            CssClass="btn btn-danger"
            Style="display:inline-block;"
            Width="100px" 
            Text="삭제"
            OnClick="deleteButton_Click" />
        <asp:HyperLink ID="cancelHyperLink" runat="server"
            CssClass="btn btn-default">
            취소
        </asp:HyperLink>
        <br />
        <asp:Label ID="messageLabel" runat="server"
            ForeColor="Red" />
        <br />
    </div>
</asp:Content>

 

▶ NoticeDeletePage.aspx.cs

using System;
using System.Web.UI;

using NoticeBoard.Models;

namespace TestProject.NoticeBoard
{
    /// <summary>
    /// 게시글 삭제 페이지
    /// </summary>
    public partial class NoticeDeletePage : Page
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// ID
        /// </summary>
        private string id;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Protected

        #region 페이지 로드시 처리하기 - Page_Load(sender, e)

        /// <summary>
        /// 페이지 로드시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        protected void Page_Load(object sender, EventArgs e)
        {
            this.id = Request.QueryString["ID"];

            this.cancelHyperLink.NavigateUrl = "NoticeViewPage.aspx?ID=" + this.id;

            this.idLabel.Text = this.id;

            this.deleteButton.Attributes["onclick"] = "return ConfirmDelete();";

            if(string.IsNullOrEmpty(this.id))
            {
                Response.Redirect("NoticeListPage.aspx");
            }
        }

        #endregion
        #region 삭제 버튼 클릭시 처리하기 - deleteButton_Click(sender, e)

        /// <summary>
        /// 삭제 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        protected void deleteButton_Click(object sender, EventArgs e)
        {
            if((new NoticeRepository()).Delete(Convert.ToInt32(this.id), this.passwordTextBox.Text) > 0)
            {
                Response.Redirect("NoticeListPage.aspx");
            }
            else
            {
                this.messageLabel.Text = "삭제시 실패했습니다. 패스워드를 확인해 주시기 바랍니다.";
            }
        }

        #endregion
    }
}

 

▶ NoticeDownloadPage.aspx

<%@ Page
    Language="C#"
    AutoEventWireup="true"
    CodeBehind="NoticeDownloadPage.aspx.cs"
    Inherits="TestProject.NoticeBoard.NoticeDownloadPage" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title></title>
    </head>
    <body>
        <form id="form" runat="server">
            <div>
            </div>
        </form>
    </body>
</html>

 

▶ NoticeDownloadPage.aspx.cs

using System;
using System.Web.UI;

using NoticeBoard.Models;

namespace TestProject.NoticeBoard
{
    /// <summary>
    /// 게시글 다운로드 페이지
    /// </summary>
    public partial class NoticeDownloadPage : Page
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 업로드 디렉토리 경로
        /// </summary>
        private string uploadDirectoryPath = string.Empty;

        /// <summary>
        /// 파일명
        /// </summary>
        private string fileName = string.Empty;

        /// <summary>
        /// 게시글 저장소
        /// </summary>
        private NoticeRepository repository;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - NoticeDownloadPage()

        /// <summary>
        /// 생성자
        /// </summary>
        public NoticeDownloadPage()
        {
            this.repository = new NoticeRepository();
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Protected

        #region 페이지 로드시 처리하기 - Page_Load(sender, e)

        /// <summary>
        /// 페이지 로드시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        protected void Page_Load(object sender, EventArgs e)
        {
            this.uploadDirectoryPath = Server.MapPath("~/FileUpload/");
            this.fileName            = this.repository.GetFileName(Convert.ToInt32(Request["ID"]));

            if(this.fileName == null)
            {
                Response.Clear();

                Response.End();
            }
            else
            {
                this.repository.UpdateDownloadCount(this.fileName);

                Response.Clear();

                Response.ContentType = "application/octet-stream";

                string attachmentFileName = Server.UrlPathEncode((this.fileName.Length > 50) ? this.fileName.Substring(this.fileName.Length - 50, 50) : this.fileName);

                Response.AddHeader
                (
                    "Content-Disposition",
                    "attachment;filename=" + attachmentFileName
                );

                Response.WriteFile(this.uploadDirectoryPath + this.fileName);

                Response.End();
            }
        }

        #endregion
    }
}

 

▶ NoticeListPage.aspx

<%@ Page
    Language="C#"
    MasterPageFile="~/Site.Master" 
    AutoEventWireup="true"
    CodeBehind="NoticeListPage.aspx.cs" 
    Inherits="TestProject.NoticeBoard.NoticeListPage"
    Title="게시글 목록 페이지" %>
<%@ Register 
    Src="~/NoticeBoard/Controls/SearchControl.ascx" 
    TagPrefix="local"
    TagName="SearchControl" %>
<%@ Register
    Src="~/NoticeBoard/Controls/PagingControl.ascx" 
    TagPrefix="local"
    TagName="PagingControl" %>
<asp:Content ID="content" ContentPlaceHolderID="MainContent" runat="server">
    <h2 style="text-align:center;">게시판</h2>
    <span style="color:#ff0000">글 목록</span>
    <hr />
    <table style="margin-left:auto;margin-right:auto;width:700px;">
        <tr>
            <td>
                <style>
                    table th
                    {
                        text-align : center;
                    }
                </style>
                <div style="font-style:italic;text-align:right;font-size:8pt;">
                    전체 레코드 : <asp:Literal ID="totalRecordLabel" runat="server" />
                </div>
                <asp:GridView ID="gridView" runat="server"
                    CssClass="table table-bordered table-hover table-condensed table-striped table-responsive"
                    AutoGenerateColumns="False"
                    DataKeyNames="ID">
                    <Columns>
                        <asp:TemplateField HeaderText="ID"
                            HeaderStyle-Width="50px"
                            ItemStyle-HorizontalAlign="Center">
                            <ItemTemplate>
                                <%# RecordCount - ((Container.DataItemIndex)) - (PageIndex * 10) %>
                            </ItemTemplate>
                        </asp:TemplateField>
                        <asp:TemplateField HeaderText="제목"
                            ItemStyle-HorizontalAlign="Left"
                            HeaderStyle-Width="350px">
                            <ItemTemplate>
                                <%# TestProject.NoticeBoardHelper.GetReplyImageHTML(Eval("ReplyLevel")) %>
                                <asp:HyperLink ID="lnkTitle" runat="server"
                                    NavigateUrl='<%# "NoticeViewPage.aspx?ID=" + Eval("ID") %>'>
                                    <%# TestProject.StringHelper.CutUnicodeString(Eval("Title").ToString(), 30) %>
                                </asp:HyperLink>
                                <%# TestProject.NoticeBoardHelper.GetReplyCountHTML(Eval("CommentCount")) %>
                                <%# TestProject.NoticeBoardHelper.GetNewImageHTML(Eval("WriteDate"))%>
                            </ItemTemplate>
                        </asp:TemplateField>
                        <asp:TemplateField HeaderText="파일"
                            HeaderStyle-Width="70px"
                            ItemStyle-HorizontalAlign="Center">
                            <ItemTemplate>
                                <%# TestProject.NoticeBoardHelper.GetFileDownloadLinkHTML(Convert.ToInt32(Eval("ID")), Eval("FileName").ToString(), Eval("FileSize").ToString()) %>
                            </ItemTemplate>
                        </asp:TemplateField>
                        <asp:BoundField DataField="Name" HeaderText="작성자"
                            HeaderStyle-Width="60px"
                            ItemStyle-HorizontalAlign="Center" />
                        <asp:TemplateField HeaderText="작성일"
                            ItemStyle-Width="90px"
                            ItemStyle-HorizontalAlign="Center">
                            <ItemTemplate>
                                <%# TestProject.NoticeBoardHelper.GetDateTimeHTML(Eval("WriteDate")) %>
                            </ItemTemplate>
                        </asp:TemplateField>
                        <asp:BoundField DataField="ReadCount" HeaderText="조회수"
                            ItemStyle-HorizontalAlign="Right"
                            HeaderStyle-Width="60px" />
                    </Columns>
                </asp:GridView>
            </td>
        </tr>
        <tr>
            <td style="text-align:center;">
                <local:PagingControl ID="pagingControl" runat="server" />
            </td>
        </tr>
        <tr>
            <td style="text-align:right;">
                <a class="btn btn-primary" href="NoticeWritePage.aspx">글쓰기</a>
            </td>
        </tr>
    </table>
    <local:SearchControl ID="searchControl" runat="server" />
</asp:Content>

 

▶ NoticeListPage.aspx.cs

using System;
using System.Web.UI;

using NoticeBoard.Models;

namespace TestProject.NoticeBoard
{
    /// <summary>
    /// 게시판 목록 페이지
    /// </summary>
    public partial class NoticeListPage : Page
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region Field

        /// <summary>
        /// 페이지 인덱스
        /// </summary>
        public int PageIndex = 0;

        /// <summary>
        /// 레코드 카운트
        /// </summary>
        public int RecordCount = 0;

        #endregion

        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 게시글 저장소
        /// </summary>
        private NoticeRepository repository;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 검색 모드 여부 - SearchMode

        /// <summary>
        /// 검색 모드 여부
        /// </summary>
        public bool SearchMode { get; set; } = false;

        #endregion
        #region 검색 필드 - SearchField

        /// <summary>
        /// 검색 필드
        /// </summary>
        public string SearchField { get; set; }

        #endregion
        #region 검색 쿼리 - SearchQuery

        /// <summary>
        /// 검색 쿼리
        /// </summary>
        public string SearchQuery { get; set; }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - NoticeListPage()

        /// <summary>
        /// 생성자
        /// </summary>
        public NoticeListPage()
        {
            this.repository = new NoticeRepository();
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Protected

        #region 페이지 로드시 처리하기 - Page_Load(sender, e)

        /// <summary>
        /// 페이지 로드시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        protected void Page_Load(object sender, EventArgs e)
        {
            SearchMode = (!string.IsNullOrEmpty(Request.QueryString["SearchField"]) && !string.IsNullOrEmpty(Request.QueryString["SearchQuery"]));

            if(SearchMode)
            {
                SearchField = Request.QueryString["SearchField"];
                SearchQuery = Request.QueryString["SearchQuery"];
            }

            if(Request["Page"] != null)
            {
                PageIndex = Convert.ToInt32(Request["Page"]) - 1;
            }
            else
            {
                PageIndex = 0;
            }

            if(SearchMode == false)
            {
                RecordCount = this.repository.GetCount();
            }
            else
            {
                RecordCount = this.repository.GetCount(SearchField, SearchQuery);
            }

            this.totalRecordLabel.Text = RecordCount.ToString();

            this.pagingControl.PageIndex   = PageIndex;
            this.pagingControl.RecordCount = RecordCount;

            if(!Page.IsPostBack)
            {
                DisplayData();
            }
        }

        #endregion

        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region 데이터 표시하기 - DisplayData()

        /// <summary>
        /// 데이터 표시하기
        /// </summary>
        private void DisplayData()
        {
            if(SearchMode == false)
            {
                this.gridView.DataSource = this.repository.GetList(PageIndex);
            }
            else
            {
                this.gridView.DataSource = this.repository.Search(PageIndex, SearchField, SearchQuery);
            }

            this.gridView.DataBind();
        }

        #endregion
    }
}

 

▶ NoticeReplyPage.aspx

<%@ Page
    Language="C#"
    MasterPageFile="~/Site.Master" 
    AutoEventWireup="true"
    ValidateRequest="false"
    CodeBehind="NoticeReplyPage.aspx.cs" 
    Inherits="TestProject.NoticeBoard.NoticeReplyPage"
    Title="게시글 답변 페이지" %>
<%@ Register
    Src="~/NoticeBoard/Controls/EditorControl.ascx" 
    TagPrefix="local"
    TagName="EditorControl" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
    <local:EditorControl ID="editorControl" runat="server" />
</asp:Content>

 

▶ NoticeReplyPage.aspx.cs

using System;
using System.Web.UI;

using NoticeBoard.Models;

namespace TestProject.NoticeBoard
{
    /// <summary>
    /// 게시글 답변 페이지
    /// </summary>
    public partial class NoticeReplyPage : Page
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Protected

        #region 페이지 로드시 처리하기 - Page_Load(sender, e)

        /// <summary>
        /// 페이지 로드시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        protected void Page_Load(object sender, EventArgs e)
        {
            this.editorControl.FormType = BoardWriteFormType.Reply;
        }

        #endregion
    }
}

 

▶ NoticeUpdatePage.aspx

<%@ Page
    Language="C#"
    MasterPageFile="~/Site.Master" 
    AutoEventWireup="true"
    ValidateRequest="false"
    CodeBehind="NoticeUpdatePage.aspx.cs" 
    Inherits="TestProject.NoticeBoard.NoticeUpdatePage"
    Title="게시글 수정 페이지" %>
<%@ Register
    Src="~/NoticeBoard/Controls/EditorControl.ascx" 
    TagPrefix="local"
    TagName="EditorControl" %>
<asp:Content ID="content" ContentPlaceHolderID="MainContent" runat="server">
    <local:EditorControl ID="editorControl" runat="server" />
</asp:Content>

 

▶ NoticeUpdatePage.aspx.cs

using System;
using System.Web.UI;

using NoticeBoard.Models;

namespace TestProject.NoticeBoard
{
    /// <summary>
    /// 게시글 수정 페이지
    /// </summary>
    public partial class NoticeUpdatePage : Page
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Protected

        #region 페이지 로드시 처리하기 - Page_Load(sender, e)

        /// <summary>
        /// 페이지 로드시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        protected void Page_Load(object sender, EventArgs e)
        {
            this.editorControl.FormType = BoardWriteFormType.Modify;
        }

        #endregion
    }
}

 

▶ NoticeViewPage.aspx

<%@ Page
    Language="C#"
    MasterPageFile="~/Site.Master"
    AutoEventWireup="true"
    CodeBehind="NoticeViewPage.aspx.cs"
    Inherits="TestProject.NoticeBoard.NoticeViewPage"
    Title="게시글 보기 페이지" %>
<%@ Register
    Src="~/NoticeBoard/Controls/CommentControl.ascx"
    TagPrefix="local"
    TagName="CommentControl" %>
<asp:Content ID="content" ContentPlaceHolderID="MainContent" runat="server">
    <h2 style="text-align:center;">게시판</h2>
    <span style="color:#ff0000">글 보기 - 현재 글에 대해서 수정 및 삭제를 할 수 있습니다. </span>
    <hr />
    <table style="margin-left:auto;margin-right:auto;width:700px;">
        <tbody>
            <tr style="background-color:#46698c;color:white;">
                <td style="width:80px;text-align:right;height:35px;"><b style="font-size:18px">제목</b> :</td>
                <td colspan="3">
                    <asp:Label ID="titleLabel" runat="server"
                        Width="100%"
                        Font-Bold="True"
                        Font-Size="18px" />
                </td>
            </tr>
            <tr style="background-color:#efefef;">
                <td class="text-right">ID :</td>
                <td>
                    <asp:Label ID="idLabel" runat="server"
                        Width="84" />
                </td>
                <td class="text-right">메일 주소 :</td>
                <td>
                    <asp:Label ID="mailAddressLabel" runat="server"
                        Width="100%" />
                </td>
            </tr>
            <tr style="background-color:#efefef;">
                <td class="text-right">성명 :</td>
                <td>
                    <asp:Label ID="nameLabel" runat="server"
                        Width="100%" />
                </td>
                <td class="text-right">홈페이지 : </td>
                <td>
                    <asp:Label ID="homepageLabel" runat="server"
                        Width="100%" />
                </td>
            </tr>
            <tr style="background-color:#efefef;">
                <td class="text-right">작성일 :</td>
                <td>
                    <asp:Label ID="writeDateLabel" runat="server"
                        Width="100%" />
                </td>
                <td class="text-right">IP 주소 :</td>
                <td>
                    <asp:Label ID="writeIPLabel" runat="server"
                        Width="100%" />
                </td>
            </tr>
            <tr style="background-color:#efefef;">
                <td class="text-right">조회수 :</td>
                <td>
                    <asp:Label ID="readCountLabel" runat="server"
                        Width="100%" />
                </td>
                <td class="text-right">파일 :</td>
                <td>
                    <asp:Label ID="fileLabel" runat="server"
                        Width="100%" />
                </td>
            </tr>
            <tr>
                <td colspan="4" style="padding:10px;">
                    <asp:Literal ID="imageLiteral" runat="server" />
                    <asp:Label ID="contentLabel" runat="server" 
                        Width="100%"
                        Height="115px" />
                </td>
            </tr>
            <tr>
                <td colspan="4">
                    <hr />
                </td>
            </tr>
            <tr>
                <td colspan="4">
                    <local:CommentControl ID="commentControl" runat="server" />
                </td>
            </tr>
        </tbody>
    </table>
    <div style="text-align:center;">
        <asp:HyperLink ID="deleteHyperLink" runat="server" 
            CssClass="btn btn-default">
            삭제
        </asp:HyperLink>
        <asp:HyperLink ID="updateHyperLink" runat="server" 
            CssClass="btn btn-default">
            수정
        </asp:HyperLink>
        <asp:HyperLink ID="replyHyperLink" runat="server" 
            CssClass="btn btn-default">
            답변
        </asp:HyperLink>
        <asp:HyperLink ID="listHyperLink" runat="server" 
            CssClass="btn btn-default"
            NavigateUrl="NoticeListPage.aspx">
            목록
        </asp:HyperLink>
    </div>
    <asp:Label ID="errorLabel" runat="server" 
        ForeColor="Red"
        EnableViewState="False" />
    <br />
</asp:Content>

 

▶ NoticeViewPage.aspx.cs

using System;
using System.Web.UI;

using NoticeBoard.Models;

namespace TestProject.NoticeBoard
{
    /// <summary>
    /// 게시글 보기 페이지
    /// </summary>
    public partial class NoticeViewPage : Page
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// ID
        /// </summary>
        private string id;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Protected

        #region 페이지 로드시 처리하기 - Page_Load(sender, e)

        /// <summary>
        /// 페이지 로드시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        protected void Page_Load(object sender, EventArgs e)
        {
            this.deleteHyperLink.NavigateUrl = "NoticeDeletePage.aspx?ID=" + Request["ID"];
            this.updateHyperLink.NavigateUrl = "NoticeUpdatePage.aspx?ID=" + Request["ID"];
            this.replyHyperLink.NavigateUrl  = "NoticeReplyPage.aspx?ID="  + Request["ID"];

            this.id = Request.QueryString["ID"];

            if(this.id == null)
            {
                Response.Redirect("./NoticeListPage.aspx");
            }

            if(!Page.IsPostBack)
            {
                DisplayData();
            }
        }

        #endregion

        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region 데이터 표시하기 - DisplayData()

        /// <summary>
        /// 데이터 표시하기
        /// </summary>
        private void DisplayData()
        {
            NoticeModel notice = (new NoticeRepository()).Get(Convert.ToInt32(this.id));

            this.idLabel.Text          = this.id;
            this.nameLabel.Text        = notice.Name;
            this.mailAddressLabel.Text = string.Format("<a href=\"mailto:{0}\">{0}</a>", notice.MailAddress);
            this.titleLabel.Text       = notice.Title;

            string content = notice.Content;

            string encoding = notice.Encoding;

            if(encoding == "Text")
            {
                this.contentLabel.Text = HTMLHelper.EncodeIncludingTabAndSpace(content);
            }
            else if(encoding == "Mixed")
            {
                this.contentLabel.Text = content.Replace("\r\n", "<br />");
            }
            else
            {
                this.contentLabel.Text = content;
            }

            this.readCountLabel.Text = notice.ReadCount.ToString();
            this.homepageLabel.Text  = string.Format("<a href=\"{0}\" target=\"_blank\">{0}</a>", notice.Homepage);
            this.writeDateLabel.Text = notice.WriteDate.ToString();
            this.writeIPLabel.Text   = notice.WriteIP;

            if(notice.FileName.Length > 1)
            {
                this.fileLabel.Text = string.Format
                (
                    "<a href='./NoticeDownloadPage.aspx?ID={0}'>{1} {2} / 전송 수 : {3}</a>",
                    notice.ID,
                    "<img src=\"/images/ext/ext_zip.gif\" border=\"0\">",
                    notice.FileName,
                    notice.DownloadCount
                );

                if(NoticeBoardHelper.IsImageFile(notice.FileName))
                {
                    this.imageLiteral.Text = $"<img src=\'ImageDownloadPage.aspx?FileName={Server.UrlEncode(notice.FileName)}\'>";
                }
            }
            else
            {
                this.fileLabel.Text = "(업로드된 파일이 없습니다.)";
            }
        }

        #endregion
    }
}

 

▶ NoticeWritePage.aspx

<%@ Page
    Language="C#"
    MasterPageFile="~/Site.Master" 
    AutoEventWireup="true"
    ValidateRequest="false"
    CodeBehind="NoticeWritePage.aspx.cs" 
    Inherits="TestProject.NoticeBoard.NoticeWritePage"
    Title="게시글 쓰기 페이지" %>
<%@ Register
    Src="~/NoticeBoard/Controls/EditorControl.ascx" 
    TagPrefix="local"
    TagName="EditorControl" %>
<asp:Content ID="content" ContentPlaceHolderID="MainContent" runat="server">
    <local:EditorControl id="editorControl" runat="server" />
</asp:Content>

 

▶ NoticeWritePage.aspx.cs

using System;
using System.Web.UI;

using NoticeBoard.Models;

namespace TestProject.NoticeBoard
{
    /// <summary>
    /// 게시글 쓰기 페이지
    /// </summary>
    public partial class NoticeWritePage : Page
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Protected

        #region 페이지 로드시 처리하기 - Page_Load(sender, e)

        /// <summary>
        /// 페이지 로드시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        protected void Page_Load(object sender, EventArgs e)
        {
            this.editorControl.FormType = BoardWriteFormType.Write;
        }

        #endregion
    }
}
728x90
반응형
그리드형(광고전용)
Posted by icodebroker

댓글을 달아 주세요