DotNetNoteController.cs 파일에 다음과 같이 코드를 작성한다. 각각의 페이지를 제작할 때마다 컨트롤러에 액션 메서드를 추가하는 방식으로 하나씩 코드를 늘려나가도 되는데, 여기서는 편의상 DotNetNote 컨트롤러의 모든 코드를 미리 제시하겠다.

    ▼  /Controllers/DotNetNoteController.cs

    using DotNetNote.Models;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc;
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Net.Http.Headers;
    using System.Threading.Tasks;
    
    namespace DotNetNote.Controllers
    {
      public class DotNetNoteController : Controller
      {
          // [DNN] 의존성 주입
          private IHostingEnvironment _environment; // 환경 변수
          private INoteRepository _repository; // 게시판 리파지터리
          private INoteCommentRepository _commentRepository; // 댓글 리파지터리
          
          public DotNetNoteController(
              IHostingEnvironment environment,
              INoteRepository repository,
              INoteCommentRepository commentRepository)
          {
              _environment = environment;
              _repository = repository;
              _commentRepository = commentRepository;
          }
          
          // 공통 속성: 검색 모드: 검색 모드이면 true, 그렇지 않으면 false
          public bool SearchMode { get; set; } = false;
          public string SearchField { get; set; } // 필드: Name, Title, Content
          public string SearchQuery { get; set; } // 검색 내용
          
          /// <summary>
          /// 현재 보여줄 페이지 번호
          /// </summary>
          public int PageIndex { get; set; } = 0;
          
          /// <summary>
          /// 총 레코드 갯수(글번호 순서 정렬용)
          /// </summary>
          public int TotalRecordCount { get; set; } = 0;
          
          /// <summary>
          /// 게시판 리스트 페이지
          /// </summary>
          public IActionResult Index()
          {
              // 검색 모드 결정: ?SearchField=Name&SearchQuery=닷넷코리아 
              SearchMode = (
                  !string.IsNullOrEmpty(Request.Query[“SearchField”]) &&
                  !string.IsNullOrEmpty(Request.Query[“SearchQuery”])
              );
              
              // 검색 환경이면 속성에 저장
              if (SearchMode)
              {
                  SearchField = Request.Query[“SearchField”].ToString();
                  SearchQuery = Request.Query[“SearchQuery”].ToString();
              }
              
              // [1] 쿼리스트링에 따른 페이지 보여주기
              if (!string.IsNullOrEmpty(Request.Query[“Page”].ToString()))
              {
                  // Page는 보여지는 쪽은 1, 2, 3, … 코드단에서는 0, 1, 2, …
                  PageIndex = Convert.ToInt32(Request.Query[“Page”]) - 1;
              }
              
              // [2] 쿠키를 사용한 리스트 페이지 번호 유지 적용(Optional): 
              //    100번째 페이지 보고 있다가 다시 리스트 왔을 때 100번째 페이지 표시
              if (!string.IsNullOrEmpty(Request.Cookies[“DotNetNotePageNum”]))
              {
                  if (!String.IsNullOrEmpty(
                      Request.Cookies[“DotNetNotePageNum”]))
                  {
                      PageIndex =
                          Convert.ToInt32(Request.Cookies[“DotNetNotePageNum”]);
                  }
                  else
                  {
                      PageIndex = 0;
                  }
              }
              
              // 게시판 리스트 정보 가져오기
              IEnumerable<Note> notes;
              if (!SearchMode)
              {
                  TotalRecordCount = _repository.GetCountAll();
                  notes = _repository.GetAll(PageIndex);
              }
              else
              {
                  TotalRecordCount = _repository.GetCountBySearch(
                      SearchField, SearchQuery);
                  notes = _repository.GetSeachAll(
                      PageIndex, SearchField, SearchQuery);
              }
              
              // 주요 정보를 뷰 페이지로 전송
              ViewBag.TotalRecord = TotalRecordCount;
              ViewBag.SearchMode  = SearchMode;
              ViewBag.SearchField = SearchField;
              ViewBag.SearchQuery = SearchQuery;
              
              return View(notes);
          }
          
          /// <summary>
          /// 게시판 글쓰기 폼
          /// </summary>
            [HttpGet]
          public IActionResult Create()
          {
              // 글쓰기 폼은 입력, 수정, 답변에서 _BoardEditorForm.cshtml 공유함
              ViewBag.FormType = BoardWriteFormType.Write;
              ViewBag.TitleDescription = “글 쓰기 - 다음 필드들을 채워주세요.”;
              ViewBag.SaveButtonText = “저장”;
              
              return View();
          }
          
          /// <summary>
          /// 게시판 글쓰기 처리 + 파일 업로드 처리
          /// </summary>
            [HttpPost]
          public async Task<IActionResult> Create(
              Note model, ICollection<IFormFile> files)
          {
              // 파일 업로드 처리 시작
              string fileName = String.Empty;
              int fileSize = 0;
              
              var uploadFolder = Path.Combine(_environment.WebRootPath, “files”);
              
              foreach (var file in files)
              {
                  if (file.Length > 0)
                  {
                      fileSize = Convert.ToInt32(file.Length);
                      // 파일명 중복 처리
                      fileName = Dul.FileUtility.GetFileNameWithNumbering(
                          uploadFolder, Path.GetFileName(
                              ContentDispositionHeaderValue.Parse(
                                  file.ContentDisposition).FileName.Trim(’“’)));
                      // 파일 업로드
                      using (var fileStream = new FileStream(
                          Path.Combine(uploadFolder, fileName), FileMode.Create))
                      {
                          await file.CopyToAsync(fileStream);
                      }
                  }
              }
              
              Note note = new Note();
              
              note.Name     = model.Name;
              note.Email    = Dul.HtmlUtility.Encode(model.Email);
              note.Homepage = model.Homepage;
              note.Title    = Dul.HtmlUtility.Encode(model.Title);
              note.Content  = model.Content;
              note.FileName = fileName;
              note.FileSize = fileSize;
              note.Password = model.Password;
              note.PostIp =
                  HttpContext.Connection.RemoteIpAddress.ToString(); // IP 주소
              note.Encoding = model.Encoding;
              
              _repository.Add(note); // 데이터 저장
              
              // 데이터 저장 후 리스트 페이지 이동시 toastr로 메시지 출력
              TempData[“Message”] = “데이터가 저장되었습니다.”;
              
              return RedirectToAction(“Index”); // 저장 후 리스트 페이지로 이동
          }
          
          
          /// <summary>
          /// 게시판 파일 강제 다운로드 기능(/BoardDown/:Id)
          /// </summary>
          public FileResult BoardDown(int id)
          {
              string fileName = ””;
              
              // 넘어온 번호에 해당하는 파일명 가져오기(보안때문에… 파일명 숨김)
              fileName = _repository.GetFileNameById(id);
              
              if (fileName == null)
              {
                  return null;
              }
              else
              {
                  // 다운로드 카운트 증가 메서드 호출
                  _repository.UpdateDownCountById(id);
                  
                  byte[] fileBytes = System.IO.File.ReadAllBytes(Path.Combine(
                      _environment.WebRootPath, “files”) + “\“ + fileName);
                  
                  return File(fileBytes, “application/octet-stream”, fileName);
              }
          }
          
          /// <summary>
          /// 게시판의 상세보기 페이지(Details, BoardView)
          /// </summary>
          public IActionResult Details(int id)
          {
              // 넘어온 Id 값에 해당하는 레코드 하나 읽어서 Note 클래스에 바인딩
              var note = _repository.GetNoteById(id);
              
              // [!] 인코딩 방식에 따른 데이터 출력
              ContentEncodingType encoding = (ContentEncodingType)Enum.Parse(
                  typeof(ContentEncodingType), note.Encoding);
              string encodedContent = ””;
              switch (encoding)
              {
                  // Text: 소스 그대로 표현
                  case ContentEncodingType.Text:
                      encodedContent =
                          Dul.HtmlUtility.EncodeWithTabAndSpace(note.Content);
                      break;
                  // Html: HTML 형식으로 출력
                  case ContentEncodingType.Html:
                      encodedContent = note.Content; // 변환 없음
                      break;
                  // Mixed: 엔터 처리만
                  case ContentEncodingType.Mixed:
                      encodedContent = note.Content.Replace(“\r\n”, “<br />“);
                      break;
                  // Html: 기본
                  default:
                      encodedContent = note.Content; // 변환 없음
                      break;
              }
              ViewBag.Content = encodedContent; //[!]
              
              // 첨부된 파일 확인
              if (note.FileName.Length > 1)
              {
                  // [a] 파일 다운로드 링크: String.Format()으로 표현해 봄 
                  ViewBag.FileName = String.Format(
                      “<a href=‘/DotNetNote/BoardDown?Id={0}’>“
                      + ”{1}{2} / 전송수: {3}</a>“, note.Id
                      , “<img src=\“/images/ext/ext_zip.gif\” border=\“0\”>“
                      , note.FileName, note.DownCount);
                  // [b] 이미지 미리보기: C# 6.0 String 보간법으로 표현해 봄
                  if (Dul.BoardLibrary.IsPhoto(note.FileName))
                  {
                      ViewBag.ImageDown =
                          $“<img src=\‘/DotNetNote/ImageDown/{note.Id}\’><br />“;
                  }
              }
              else
              {
                  ViewBag.FileName = ”(업로드된 파일이 없습니다.)”;
              }
              
              // 현재 글에 해당하는 댓글 리스트와 현재 글 번호를 담아서 전달
              NoteCommentViewModel vm = new NoteCommentViewModel();
              vm.NoteCommentList = _commentRepository.GetNoteComments(note.Id);
              vm.BoardId = note.Id;
              ViewBag.CommentListAndId = vm;
              
              return View(note);
          }
          
          /// <summary>
          /// 게시판 삭제 폼
          /// </summary>
            [HttpGet]
          public IActionResult Delete(int id)
          {
              ViewBag.Id = id;
              return View();
          }
          
          /// <summary>
          /// 게시판 삭제 처리
          /// </summary>
            [HttpPost]
          public IActionResult Delete(int id, string Password)
          {
              if (_repository.DeleteNote(id, Password) > 0)
              {
                  TempData[“Message”] = “데이터가 삭제되었습니다.”;
                  
                  // 학습 목적으로 삭제 후의 이동 페이지를 2군데 중 하나로 분기
                  if (DateTime.Now.Second % 2 == 0)
                  {
                      // [a] 삭제 후 특정 뷰 페이지로 이동
                      return RedirectToAction(“DeleteCompleted”);
                  }
                  else
                  {
                      // [b] 삭제 후 Index 페이지로 이동
                      return RedirectToAction(“Index”);
                  }
              }
              else
              {
                  ViewBag.Message = “삭제되지 않았습니다. 비밀번호를 확인하세요.”;
              }
              
              ViewBag.Id = id;
              return View();
          }
          
          /// <summary>
          /// 게시판 삭제 완료 후 추가적인 처리할 때 페이지
          /// </summary>
          public IActionResult DeleteCompleted()
          {
              return View();
          }
          
          /// <summary>
          /// 게시판 수정 폼
          /// </summary>
            [HttpGet]
          public IActionResult Edit(int id)
          {
              ViewBag.FormType = BoardWriteFormType.Modify;
              ViewBag.TitleDescription = “글 수정 - 아래 항목을 수정하세요.”;
              ViewBag.SaveButtonText = “수정”;
              
              // 기존 데이터를 바인딩
              var note = _repository.GetNoteById(id);
              
              // 첨부된 파일명 및 파일 크기 기록
              if (note.FileName.Length > 1)
              {
                  ViewBag.FileName = note.FileName;
                  ViewBag.FileSize = note.FileSize;
                  ViewBag.FileNamePrevious =
                      $“기존에 업로드된 파일명: {note.FileName}”;
              }
              else
              {
                  ViewBag.FileName = ””;
                  ViewBag.FileSize = 0;
              }
              
              return View(note);
          }
          
          /// <summary>
          /// 게시판 수정 처리 + 파일 업로드
          /// </summary>
            [HttpPost]
          public async Task<IActionResult> Edit(
              Note model, ICollection<IFormFile> files,
              int id, string previousFileName = ””, int previousFileSize = 0)
          {
              ViewBag.FormType = BoardWriteFormType.Modify;
              ViewBag.TitleDescription = “글 수정 - 아래 항목을 수정하세요.”;
              ViewBag.SaveButtonText = “수정”;
              
              string fileName = ””;
              int fileSize = 0;
              
              if (previousFileName != null)
              {
                  fileName = previousFileName;
                  fileSize = previousFileSize;
              }
              
              // 파일 업로드 처리 시작
              var uploadFolder = Path.Combine(_environment.WebRootPath, “files”);
              
              foreach (var file in files)
              {
                  if (file.Length > 0)
                  {
                      fileSize = Convert.ToInt32(file.Length);
                      // 파일명 중복 처리
                      fileName = Dul.FileUtility.GetFileNameWithNumbering(
                          uploadFolder, Path.GetFileName(
                              ContentDispositionHeaderValue.Parse(
                                  file.ContentDisposition).FileName.Trim(’“’)));
                      // 파일 업로드
                      using (var fileStream = new FileStream(
                          Path.Combine(uploadFolder, fileName), FileMode.Create))
                      {
                          await file.CopyToAsync(fileStream);
                      }
                  }
              }
              
              Note note = new Note();
              
              note.Id = id;
              note.Name     = model.Name;
              note.Email    = Dul.HtmlUtility.Encode(model.Email);
              note.Homepage = model.Homepage;
              note.Title    = Dul.HtmlUtility.Encode(model.Title);
              note.Content  = model.Content;
              note.FileName = fileName;
              note.FileSize = fileSize;
              note.Password = model.Password;
              note.ModifyIp =
                  HttpContext.Connection.RemoteIpAddress.ToString(); // IP 주소
              note.Encoding = model.Encoding;
              
              int r = _repository.UpdateNote(note); // 데이터베이스에 수정 적용
              if (r > 0)
              {
                  TempData[“Message”] = “수정되었습니다.”;
                  return RedirectToAction(“Details”, new { Id = id });
              }
              else
              {
                  ViewBag.ErrorMessage =
                      “업데이트가 되지 않았습니다. 암호를 확인하세요.”;
                  return View(note);
              }
          }
          
          /// <summary>
          /// 답변 글쓰기 폼
          /// </summary>
          /// <param name=“id”>부모글 Id</param>
            [HttpGet]
          public IActionResult Reply(int id)
          {
              ViewBag.FormType = BoardWriteFormType.Reply;
              ViewBag.TitleDescription = “글 답변 - 다음 필드들을 채워주세요.”;
              ViewBag.SaveButtonText = “답변”;
              
              // 기존 데이터를 바인딩
              var note = _repository.GetNoteById(id); // 기존 부모글 Id
              
              // 새로운 Note 개체 생성
              var newNote = new Note();
              
              // 기존 글의 제목과 내용을 새 Note 개체에 저장 후 전달
              newNote.Title = $“Re : {note.Title}”;
              newNote.Content =
                  $“\n\nOn {note.PostDate}, ‘{note.Name}’ wrote:\n———-\n>“
                  + $”{note.Content.Replace(”<span class=“n”>n”, “<span class=“n”>n

    신간 소식 구독하기
    뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.