ASP.NET/MVC 3

.NET MVC 3를 이용한 기본 Controller 생성, View 템플릿 추가하기, 모델 이용하기, 페이지들 간의 링크 추가하기

littlemk 2018. 7. 19. 09:05

비쥬얼 스튜디오 버전 :: Visual Studio 2010 Web Developer Express



# .NET MVC 3를 이용한 기본 Controller 생성

    1. Test02 라는 프로젝트 생성 (기본값으로 생성)

    



  1. HomeController 생성
    => Solution Explorer 안의 Controllers 우클릭 -> Add -> Controller 클릭 


    



  1. HomeController 소스 변경

public string Index()
{
    return "Hello from Home";
}


    


    




  1. StoreController 생성 (기본값)




  1. StoreController 소스 변경
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MvcMusicStore.Controllers{
    public class StoreController : Controller
    {
        //
        // GET: /Store/
        public string Index()
        {
            return "Hello from Store.Index()";
        }
        //
        // GET: /Store/Browse
        public string Browse()
        {
            return "Hello from Store.Browse()";
        }
        //
        // GET: /Store/Details
        public string Details()
        {
            return "Hello from Store.Details()";
        }
    }
}


# 다음 url에 접속하여 컨트롤러가 잘 돌아가는지 확인

url :: localhost:xxxx/Store

url :: localhost:xxxx/Store/Browse

url :: localhost:xxxx/Store/Details



  1. StoreController의 Browse 소스 변경
 public string Browse(string genre)
 {
   string message = HttpUtility.HtmlEncode("Store.Browse, Genre = " + genre);
   return message;
   //return "Hello from Store.Browse()";
 }


! 노트 :: 위의 코드에서처럼 사용자가 입력한 모든 값은 HttpUtility.HtmlEncode 유틸리티 메서드를 이용해서 안전하게 처리해야만 합니다. 
그래야만 /Store/Browse?Genre=<script>window.location='http://hackersite.com'</script>와 같은 뷰에 대한 악의적인 사용자의 자바스크립트 주입 공격을 방지할 수 있습니다.



  1. /Store/Browse?Genre=Disco로 이동
  



  1. StoreController의 Details 소스 변경
 public string Details(int id)
 {
   string message = "Store.Details, ID = " + id;
   return message;
   //return "Hello from Store.Details()";
 }



  1. /Store/Details/2로 이동
  







# .NET MVC 3를 이용한 View 템플릿 추가하기



  1. 기존 HomeContoller 소스 변경
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace Test02.Controllers
{
    public class HomeController : Controller
    {
        //
        // GET: /Home/
        public ActionResult Index()
        {
            return View();
        }
        /*
        public string Index()
        {
            return "Hello from Home";
        }
        */
    }
}


  1. View 템플릿 추가
    





  1. index.cshtml 소스 변경
@{
    ViewBag.Title = "Index";
}
<h2>한글지원이 될까요?</h2>



  1. /Views/Shared 폴더 내의 _Layout.cshtml 파일 확인




  1. _Layout.cshtml 소스 변경
<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>
</head>
<body>
    <div id="header">
        <h1>ASP.NET MVC Music Store</h1>
        <ul id="navlist">
            <li class=""first> <a href="/" id="current">Home</a></li>
            <li><a href="/Store/">Store</a></li>
        </ul>
    </div>
    @RenderBody()
</body>
</html>


  1. http://mvcmusicstore.codeplex.com/ CSS 및 사진 파일 다운로드 후 해당 폴더의 Content 폴더 Solution Explorer 내의 Content 폴더에 삽입
    






# 모델 이용하기


  1. Models 우클릭 -> Add -> Class 클릭


  1. Genre.cs 모델 파일 생성 
    


    
  1. Genre.cs 모델 소스 변경
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Test02.Models
{
    public class Genre
    {
        public string Name { get; set; }
    }
}


노트: 이 예제 코드에 사용되는 { get; set; } 표기법은 C#의 자동-구현 속성 기능을 활용하고 있는 것입니다. 이 기능을 이용하면, 내부 필드를 생성하지 않고서도 속성의 여러 가지 이점들을 얻을 수 있습니다.

  1. Album.cs 파일 생성 및 소스 변경


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Test02.Models
{
    public class Album
    {
        public string Title { get; set; }
        public Genre Genre { get; set; }
    }
}


  1. StoreController.cs 소스 변경
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Test02.Models;
namespace Test02.Controllers
{
    public class StoreController : Controller
    {
        //
        // GET: /Store/
        public string Index()
        {
            return "Hello from Store.Index()";
        }
        //
        // GET: /Store/Browse
        public string Browse(string genre)
        {
            string message = HttpUtility.HtmlEncode("Store.Browse, Genre = " + genre);
            return message;
            //return "Hello from Store.Browse()";
        }
        //
        // GET: /Store/Details
        public ActionResult Details(int id)
        {
            var album = new Album { Title = "Album " + id };
            return View(album);
        }
    }
}


노트: 만약, C#에 익숙하지 않다면, var 키워드가 사용된 album 변수가 후기 바인딩(Late-Bound) 기법을 사용하고 있는 것으로 오해할 수도 있습니다. 그러나, 그렇지 않습니다. C# 컴파일러는 변수에 할당되는 값에 기반한 형식 추론(Type-Inference)에 따라 album 변수의 형식이 Album인 것을 인지하고, 지역 album 변수를 Album 형식으로 컴파일합니다. 따라서, 일반적인 코드처럼 컴파일 시점 검사와 Visual Studio 코드 편집기의 지원을 받을 수 있습니다.


  1. Build Test02  

    => ctrl+shift+b 로 Test02 프로젝트 빌드하기

    빌드를 하게되면, 아래와 같이 StoreController의 Details 액션 메서드에서 View 템플릿 생성이 가능해진다.



  1. View 템플릿 생성 (model)
    


  1. Details.cshtml 뷰 템플릿 생성 및 소스 변경

@model Test02.Models.Album
@{
    ViewBag.Title = "Details";
}
<h2>Album : @Model.Title</h2>



  1. Url 실행 화면 (localhost:xxxx/Store/Details/5)


  1. StoreController 클래스의 Browse 액션 메서드 소스 수정
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Test02.Models;
namespace Test02.Controllers
{
    public class StoreController : Controller
    {
        //
        // GET: /Store/
        public string Index()
        {
            return "Hello from Store.Index()";
        }
        //
        // GET: /Store/Browse
        public ActionResult Browse(string genre)
        {
            var genreModel = new Genre { Name = genre };
            return View(genreModel);
        }
        //
        // GET: /Store/Details
        public ActionResult Details(int id)
        {
            var album = new Album { Title = "Album " + id };
            return View(album);
        }
    }
}


  1. StoreController Build (ctrl+shift+b) 및 Browse의 뷰 템플릿 생성
    


    

  1. 생성된 Browse.cshtml 파일 소스 변경
<!-- 기존 소스코드 -->

@model Test02.Models.Genre
@{
    ViewBag.Title = "Browse";
}
<h2>Browse</h2>


<!-- 변경된 소스코드 -->

@model Test02.Models.Genre
@{
    ViewBag.Title = "Browse";
}
<h2>Browsing Genre : @Model.Name</h2>





  1. StoreController의 Index 액션 메서드 소스 변경 및 build (ctrl+shift+b)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Test02.Models;
namespace Test02.Controllers
{
    public class StoreController : Controller
    {
        //
        // GET: /Store/
        public ActionResult Index()
        {
            var genres = new List<Genre>
            {
                new Genre { Name = "Disco" },
                new Genre { Name = "Rock" },
                new Genre { Name = "Jazz" }
            };
            return View(genres);
            //return "Hello from Store.Index()";
        }
        //
        // GET: /Store/Browse
        public ActionResult Browse(string genre)
        {
            var genreModel = new Genre { Name = genre };
            return View(genreModel);
        }
        //
        // GET: /Store/Details
        public ActionResult Details(int id)
        {
            var album = new Album { Title = "Album " + id };
            return View(album);
        }
    }
}


  1. Index 액션 매서드의 Index view 생성
    



  1. Index.cshtml 소스 변경
@model IEnumerable<Test02.Models.Genre>
<!--
    해당 코드는 이 뷰가 여러개의 Genre 개체들을 담고 있는 모델 개체를 사용한다는 것을 Razor 뷰 엔진에 전달.
   
    :: List<Genre> 개체 대신 IEnumerable<genre> 개체를 사용하는 이유 ::
    IEnumerable<Genre> 개체가 보다 범용적이므로, IEnumerable 인터페이스를 지원하는 모든 개체 형식들을 모델 형식으로 사용 가능하기 때문.
 -->
@{
    ViewBag.Title = "Store";
}
<h3>Browse Genres</h3>
<p>
    Select from @Model.Count() genres:
    <!--
    그리고, 이 코드를 작성할 때도, 완벽하게 인텔리센스가 지원되어 "@Model."이라고 코드를 입력하면
    Genre 개체들이 담겨 있는 IEnumerable 인터페이스가 지원해주는 메서드들과 속성들을 보면서 작업할 수 있음.
     -->
</p>
<ul>
    @foreach (var genre in Model)
    {
        <li>@genre.Name</li>
    }
</ul>






# 페이지들 간의 링크 추가하기


 */Store/Browse Url로 이동하도록 변경 시 문자열로 의존한 경우

<ul>
    @foreach (var genre in Model)
    {
        <li><a href="/Store/Browse?genre=@genre.Name">@genre.Name</a></li>
    }
</ul>

위의 소스코드로도 동작은 하지만, 변경이 필요한 부분들은 일일이 수정해줘야하는 불편한 경우가 생긴다.



 */Store/Browse Url로 이동하도록 변경 시 HTML 도우미 메서드를 사용한 경우

@Html.ActionLink("Go to the Store Index", "Index")

-> <a> 태그의 작성을 손 쉽게 만들어 줄 뿐만아니라, 하이퍼링크를 클릭했을 때 이동할 액션 메서드만 지정해주면 된다.
ps) StoreController 영역의 Details 메서드에 링크 텍스트가 "Go to the Store Index"를 클릭했을 때,
/Store/ Index()메서드로 이동하는 링크가 생성된다. 



  1. Index.cshtml에 Browse 페이지에 대한 링크를 추가하기
@model IEnumerable<Test02.Models.Genre>
<!--
    해당 코드는 이 뷰가 여러개의 Genre 개체들을 담고 있는 모델 개체를 사용한다는 것을 Razor 뷰 엔진에 전달.
   
    :: List<Genre> 개체 대신 IEnumerable<genre> 개체를 사용하는 이유 ::
    IEnumerable<Genre> 개체가 보다 범용적이므로, IEnumerable 인터페이스를 지원하는 모든 개체 형식들을 모델 형식으로 사용 가능하기 때문.
 -->
@{
    ViewBag.Title = "Store";
}
<h3>Browse Genres</h3>
<p>
    Select from @Model.Count() genres:
    <!--
    그리고, 이 코드를 작성할 때도, 완벽하게 인텔리센스가 지원되어 "@Model."이라고 코드를 입력하면
    Genre 개체들이 담겨 있는 IEnumerable 인터페이스가 지원해주는 메서드들과 속성들을 보면서 작업할 수 있음.
     -->
</p>
<ul>
    @foreach (var genre in Model)
    {
        <li>@genre.Name</li>
    }
</ul><br />
<p>다음은 Html.ActionLink를 사용하여 Browse로 이동가능하게 만든 링크입니다.</p><br />
<ul>
    @foreach (var genre in Model)
    {
        <li>@Html.ActionLink(genre.Name, "Browse", new { genre = genre.Name })</li>
    }
</ul>









참고 사이트 :: http://www.egocube.pe.kr/translation/content/asp-net-mvc-3-tutorial-1/201207230001