'2018/04'에 해당되는 글 5건

Programming/.NET

ASP.NET MVC에서는 URL을 통해 HTTP요청을 할때 URL에 들어간 요청내용을 .NET개체로 변환해 처리할 수 있습니다. 이 과정을 바인딩(Binding)이라고 하는데 이것은 string이나 int형의 단일 형식 데이터부터 사용자 지정 클래스까지 다양한 개체를 바인딩으로 다룰 수 있다는 것을 의미합니다.

 

public ActionResult Index()
{
    string[] s = new string[5] { "aa""bb""cc""dd""ee" };
    return View(s);
}

 

액션메서드에서 문자열 배열을 뷰에 전달하고 있습니다.

 

@model string[]

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    @using (Html.BeginForm()) {
        <table border="1">
            <tbody>
                <tr>

                    @for (int i = 0; i <= 4; i++) {
                        <td>@Html.TextBox("s"Model[i])</td>
                    }
                </tr>
            </tbody>
        </table>
        <input type="submit" value="확인" />
    }
</body>
</html>

 

뷰에서는 model을 string[] 형식으로 취해 값을 받을 수 있고 이때 Model은 string 배열이 되므로 string 배열과 동일한 방식으로 접근할 수 있게 됩니다.

 

[HttpPost]
public ActionResult Index(string[] s)
{
    return View("Result"s);
}

 

또다른 Index 액션메서드는 뷰에서 사용자가 특정 값을 입력하고 '확인'을 눌렀을때 Post로 배열을 전달할 수 있도록 합니다. 이것은 배열을 바인딩 처리하는 하나의 예로서 볼 수 있습니다.

 

@model string[]

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Result</title>
</head>
<body>
    <table border="1">
        <tbody>
            <tr>
                @foreach (string s in Model)
                {

                    <td>@s</td>
                }
            </tr>
        </tbody>
    </table>
</body>
</html>

 

배열을 전달받은 뷰에서도 마찬가지로 string[] 형식을 취하여 Model을 통해 데이터를 다룰 수 있도록 합니다.

 

public ActionResult Index()
{
    List<string> s = new List<string>() { "aa""bb""cc""dd""ee" };
    return View(s);
}

 

이 예제는 기존의 단순한 배열에서 List형식의 컬렉션으로 변경한 결과를 보여주고 있습니다.

 

@model IList<string>

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    @using (Html.BeginForm()) {
        <table border="1">
            <tbody>
                <tr>

                    @foreach (string s in Model) {
                        <td>@Html.TextBox("s", s)</td>
                    }
                </tr>
            </tbody>
        </table>
        <input type="submit" value="확인" />
    }
</body>
</html>

 

모델의 형식을 IList<string>으로 잡는것 외에는 큰 차이가 존재하지 않습니다. 여기서 중요한 것은 바인딩을 통해 .NET의 개체를 손쉽게 처리할 수 있다는 것입니다.

 

public class Member
{
    public int Idx { getset}
    public string Name { getset}
    public string Email { getset}
    public DateTime BirthDay { getset}
    public int Point { getset}
}
▶ Model

 

public class HomeController : Controller
{
    Member[] mb = {
        new Member() { Idx = 1, Name = "홍길동"Email = "hong1@cliel.com"Point = 100, BirthDay = new DateTime(1981, 11, 14) },
        new Member() { Idx = 2, Name = "홍길남"Email = "hong2@cliel.com"Point = 110, BirthDay = new DateTime(1980, 4, 23) },
        new Member() { Idx = 3, Name = "홍길석"Email = "hong3@cliel.com"Point = 55, BirthDay = new DateTime(1973, 8, 19) },
        new Member() { Idx = 4, Name = "홍길순"Email = "hong4@cliel.com"Point = 80, BirthDay = new DateTime(1992, 6, 5) },
        new Member() { Idx = 5, Name = "홍길영"Email = "hong5@cliel.com"Point = 98, BirthDay = new DateTime(1986, 3, 8) }
    };

    // GET: Home
    public ActionResult Index(int id = 1)
    {
        int defaultId = 1;
        ViewBag.id = mb.ToList().Select(x => new SelectListItem { Value = x.Idx.ToString(), Text = x.Name, Selected = (x.Idx == defaultId) });

        IEnumerable<Member> member = mb.Where(x => x.Idx == id);
        return View(member);
    }
}

▶ Controller

 

@using WebApplication1.Classes
@model IEnumerable<WebApplication1.Classes.Member>

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <div>
        <table border="1">
            <thead><tr><th>이름</th><th>포인트</th><th>생년월일</th></tr></thead>
            <tbody>
                @foreach (Member m in Model) {
                    <tr>
                        <td>@m.Name</td>
                        <td>@m.Point</td>
                        <td>@m.BirthDay.ToString("yyyy년MM월dd일")</td>
                    </tr>
                }
            </tbody>
        </table>
    </div>
    <br />
    @using (Html.BeginForm()) {
        @Html.DropDownList("id")
        <input type="submit" value="확인" />
    }
</body>
</html>

▶ View

 

 

이 예제에서는 Routing 구성에 따라 URL에서 id라는 세그먼트를 옵션으로 받을 수 있으며 Controller에서 id값을 받아 Member중에 Idx와 동일한 명단을 출력할 것입니다. 여기서 중요한 것은 id로 전달된 3이라는 숫자값입니다. URL을 통해 숫자 3을 전달했는데 Controller에서 이 값을 int형의 개체로 받아 내부에서 적절한 처리를 수행하고 있는 아주 간단한 바인딩처리의 예입니다.

 

URL을 통해 HTTP요청을 하는 경우 id와 같은 세그먼트 바인딩은 매개변수의 이름과 요청하는 식별자의 이름이 같고 데이터형식이 일치할 수 있는 경우에만 동작할 수 있습니다. 예제에서는 매개변수의 이름(id)과 라우팅정보에 해당하는 id이름이 같고, 3이라는 숫자는 int형에 대응될 수 있기 때문에 정상적으로 처리될 수 있었습니다. 또한 액션 메서드에서는 int형 id에 기본으로 1이라는 값을 주었는데 이는 id값이 URL에서 생략되었을때 대체적으로 사용할 수 있는 값을 제공하기 위함입니다.

 

바인딩은 단순 데이터에만 국한되지 않고 특정 개체자체를 전달할 수도 있습니다. 특히 이러한 사례는 HTTP POST에서 잘 살펴볼 수 있습니다.

 

public ActionResult AddMember()
{
    return View(new Member());
}

▶ Action

 

@model WebApplication1.Classes.Member

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>AddMember</title>
</head>
<body>
    @using (Html.BeginForm()) {
        @Html.EditorFor(x => x.Idx)<br/>
        @Html.EditorFor(x => x.Name)<br />
        @Html.EditorFor(x => x.Email)<br />
        @Html.EditorFor(x => x.Point)<br />
        @Html.EditorFor(x => x.BirthDay)<br />
        <input type="submit" value="확인" />
    }
</body>
</html>
▶ View

 

AddMember는 Member를 추가할 경우의 입력폼을 가진 View를 출력합니다. 이 View에서 Member에 관한 각 항목을 입력하고 '확인'버튼을 누르면

 

[HttpPost]
public ActionResult AddMember(Member m)
{
    return View("ResultMember"m);
}

 

Member개체는 POST를 통해 같은 메서드로 바인딩처리되고

 

@model WebApplication1.Classes.Member

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>AddMember</title>
</head>
<body>
    @using (Html.BeginForm()) {
        @Html.EditorFor(x => x.Idx)<br/>
        @Html.EditorFor(x => x.Name)<br />
        @Html.EditorFor(x => x.Email)<br />
        @Html.EditorFor(x => x.Point)<br />
        @Html.EditorFor(x => x.BirthDay)<br />
        <input type="submit" value="확인" />
    }
</body>
</html>

 

ResultMember View를 통해 입력결과를 확인할 수 있습니다. 이 예제는 실제 Member에 대한 추가작업을 수행하지는 않지만 HTTP POST를 통해 특정 개체를 전달하고 전달된 개체를 바인딩하여 그대로 활용하는 방식을 볼 수 있습니다.

 

또한 ASP.NET MVC에서는 이러한 바인딩동작을 좀더 유연하게 처리할 수 있도록 Bind라는 속성을 제공하고 있습니다.

 

public ActionResult AddMember([Bind(Exclude"Point")]Member m)
{
    return View("ResultMember"m);
}

 

Bind 의 Exclude 속성은 지정한 이름에 해당하는 클래스의 멤버에 대해서는 아예 바인딩을 처리하지 않도록 지시할 수 있습니다. 물론 아래와 같이 클래스개체에 직접적으로 지정하는 것도 가능합니다.

 

[Bind(Exclude = "Point")]
public class Member

 

반대의 개념으로 Include도 있는데 이 속성에 멤버를 지정하면 해당하는 멤버만 바인딩에 포함시키고 그 외에 모든 멤버를 바인딩에서 제외하게 됩니다.

 

또 하나 유용하게 활용할 수 있는 속성으로는 Prefix라는 것이 있는데 이 기능을 제대로 살펴보기 위해서는 우선 다음과 같이 클래스의 구조를 살짝 변경해야 합니다.

 

public class Member
{
    public int Idx { getset}
    public UserName Name { getset}
    public string Email { getset}
    public DateTime BirthDay { getset}
    public int Point { getset}
}

public class UserName
{
    public string Name { getset}
    public string Nick { getset}
}

 

Member클래스의 Name을 하위 클래스로 구현해 실제이름과 별명을 같이 지정할 수 있게 확장한 형태라고 가정해 보겠습니다.

 

List<Membermb = new List<Classes.Member{
    new Member() { Idx = 1, Name = new UserName() { Name = "홍길동"Nick = "홍1" }Email = "hong1@cliel.com"Point = 100, BirthDay = new DateTime(1981, 11, 14) },
    new Member() { Idx = 2, Name = new UserName() { Name = "홍길남"Nick = "홍2" }Email = "hong2@cliel.com"Point = 110, BirthDay = new DateTime(1980, 4, 23) },
    new Member() { Idx = 3, Name = new UserName() { Name = "홍길석"Nick = "홍3" }Email = "hong3@cliel.com"Point = 55, BirthDay = new DateTime(1973, 8, 19) },
    new Member() { Idx = 4, Name = new UserName() { Name = "홍길순"Nick = "홍4" }Email = "hong4@cliel.com"Point = 80, BirthDay = new DateTime(1992, 6, 5) },
    new Member() { Idx = 5, Name = new UserName() { Name = "홍길동"Nick = "홍5" }Email = "hong5@cliel.com"Point = 98, BirthDay = new DateTime(1986, 3, 8) }
};

▶ Controller

 

public ActionResult Index(intid = 1)
{
    int defaultId = 1;
    ViewBag.id = mb.ToList().Select(x => new SelectListItem { Value = x.Idx.ToString(), Text = x.Name.Name, Selected = (x.Idx == defaultId) });

    IEnumerable<Member> member = mb.Where(x => x.Idx == id);
    return View(member);
}

▶ Action

 

물론 그에 맞게 새롭게 List와 기본액션메서드를 변경해야 합니다.

 

<body>

    @using (Html.BeginForm()) {
        @Html.EditorFor(x => x.Idx)<br/>
        @Html.EditorFor(x => x.Name.Name)<br />
        @Html.EditorFor(x => x.Name.Nick)<br />
        @Html.EditorFor(x => x.Email)<br />
        @Html.EditorFor(x => x.Point)<br />
        @Html.EditorFor(x => x.BirthDay)<br />
        <input type="submit" value="확인" />
    }
</body>

 

하위 클래스의 경우 속성값 설정에는 보시는 바와 같이 [개체명].[속성] 형태로 지정되어야 합니다. 그런데 이런 형태의 하위 클래스사용은 생각보다 빈번하게 다루어질 수 있어서 간혹 다른 클래스사이의 바인딩을 수행해야 하는 경우도 있습니다. 예를 들어

 

public class MemberName
{
    public string Name { getset}
    public string Nick { getset}
}

 

AddMember 에서 지정한 사용자 이름과 별명을 이 새로운 클래스로 바인딩을 해야 한다고 했을때

 

public ActionResult AddMember2(MemberName mn)
{
    return View("ResultMemberName"mn);
}

 

그에 따른 액션메서드와

 

@model WebApplication1.Classes.MemberName

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title></title>
</head>
<body>
    <table border="1">
        <thead><tr><th>이름</th><th>별명</th></tr></thead>
        <tbody>
            <tr>
                <td>@Model.Name</td>
                <td>@Model.Nick</td>
            </tr>
        </tbody>
    </table>
</body>
</html>

 

뷰를 추가한뒤

 

<body>

     @using (Html.BeginForm("AddMember2""Home")) {
        @Html.EditorFor(x => x.Idx)<br/>
        @Html.EditorFor(x => x.Name.Name)<br />
        @Html.EditorFor(x => x.Name.Nick)<br />
        @Html.EditorFor(x => x.Email)<br />
        @Html.EditorFor(x => x.Point)<br />
        @Html.EditorFor(x => x.BirthDay)<br />
        <input type="submit" value="확인" />
    }
</body>

 

AddMember.cshtml을 위와 같이 수정하고 '확인'을 누르게 되면 새롭게 추가된 뷰에는 아무것도 나오지 않게 됩니다. 왜냐하면 AddMember 에서는 여전히 Name값을 전달하기 위해 Name.Name과 Name.Nick 에서 Name이라는 공통된 접두사를 사용하고 있기 때문입니다. 이 접두사는 새로 생성한 MemberName 클래스에는 존재하지 않는 접두사이기에 입력한 값을 가져올 수 없습니다.

 

public ActionResult AddMember2([Bind(Prefix="Name")]MemberName mn)
{
    return View("ResultMemberName"mn);
}

 

이 문제를 해결하려면 매개변수를 통해 개체를 전달할때 Bind 의 Prefix 속성을 통하여 값을 가져올 접두사를 지정하는 것입니다. 이렇게 하면 자연스럽게 AddMember에서 Name.Name과 Name.Nick를 통해 값을 가져올 수 있게 됩니다.

 

지금까지는 단일 클래스모델의 바인딩을 알아봤는데 가장 처음에 말씀드렸던 배열의 바인딩을 이용하면 다중 클래스모델의 바인딩도 손쉽게 다룰 수 있습니다.

 

public ActionResult AddMember()
{
    return View(new Member());
}

[HttpPost]
public ActionResult AddMember(List<Memberm)
{
    return View("ResultMember"m);
}

 

AddMember의 액션메서드를 위와 같이 수정합니다. 특히 두번째 AddMember의 액션메서드는 매개변수로 받는 Member를 List 컬렉션으로 바인딩하고 있습니다.

 

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>AddMember</title>
</head>
<body>
    @using (Html.BeginForm()) {
        for (int i = 0; i <= 2; i++) {
            @Html.Editor("[" + i + "].Name.Name")<br />
            @Html.Editor("[" + i + "].Point")<br />
            <br /><br />
        }

        <input type="submit" value="확인" />
    }
</body>
</html>

 

처음 시작되는 기본뷰에서는 필요한 속성들을 [0]과 같은 접두사를 통해 지정하고 있습니다. 여기서 []안에 숫자는 Member에 대한 각 개체의 배열순번과 일치하여 해당 순번의 배열에 되는 Member개체에 값을 전달하게 됩니다.

 

@using WebApplication1.Classes
@model List<WebApplication1.Classes.Member>

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>ResultMember</title>
</head>
<body>
    <table border="1">
        @foreach (Member m in Model) {
            <tr>
                <td>
                    @m.Name.Name
                </td>
                <td>
                    @m.Point
                </td>
            </tr>
        }
    </table>
</body>
</html>

POST이후 보여질 뷰에서는 모델형식을 List<WebApplication1.Classes.Member> 형식으로 잡고 순차적으로 순회를 하게 되면 List에 담긴 각 Member개체의 값을 출력하게 됩니다.

0 0
Programming/.NET

C# 3.0이전에 클래스의 속성은 아래와 같이 작성해야 했습니다.

 

class Member
{
    string name;
    public string Name {
        get { return name}
        set { name = value}
    }
}

 

즉, 변수를 하나 만들고 그 변수와 연계되는 속성을 따로 만들어야 합니다. 물론

 

class Member
{
    public string name;
}

 

이렇게 처리하는 경우도 있으나 캡슐화에 위배되는 문제가 생기게 됩니다. 그래서 속성처리는 하되 코드의 간결함을 유지할 수 있도록 하는 자동구현속성이 생기게 됩니다.

 

public string Name { getset}

 

따라서 위와 같이 하면 컴파일러는 처음예제와 같은 코드로 변환하여 컴파일을 진행하게 됩니다.

 

이러한 속성은 객체를 초기화하는데도 사용될 수 있습니다. 예를 들어 내부 변수를 초기화 하기 위해 생성자를 아래와 같이 만들었을때

 

class Member
{
    int _i;

    public Member(int i)
    {

        _i = i;
    }
}

 

만약 변수가 하나더 추가된다면 생성자를 다음과 같이 수정할 수 있습니다.

 

class Member
{
    int _i;
    int _j;

    public Member(int iint j)
    {

        _i = i;

        _j = j;
    }
}

 

이때 변수 _i와 _j가 따로 초기화 될 수 있다면 그 만큼 생성자를 분리해야 할 것입니다.

 

class Member
{
    int _i;
    int _j;

    public Member() : this(0, 0)
    {
    }

    public Member(int i) : this(0, i)
    {
    }

    public Member(int iint j)
    {

        _i = i;         _j = j;
    }
}

 

이러한 불편함은 속성을 통해 해결할 수 있습니다.

 

class Member
{
    public int I
    {
        get;

        set;
    }

    public int J
    {
        get;
        set;
    }
}

 

클래스에서 속성을 위와같이 적용해 두면 클래스의 개체를 초기화 할때 다음처럼 초기화 하는 것이 가능합니다.

 

Member m1 = new Member();
Member m2 = new Member { I = 10 };
Member m3 = new Member { J = 20 };
Member m4 = new Member { I = 10, J = 20 };

 

이러한 초기화 방식은 기본 생성자와 함께 혼용할 수도 있습니다.

 

class Member
{
    string _s;
    public int I
    {
        get;

        set;
    }

    public int J
    {
        get;
        set;
    }

    public Member()
    {
    }

    public Member(string s)
    {
        _s = s;
    }
}

 

->

 

Member m1 = new Member();
Member m2 = new Member() { I = 10 };
Member m3 = new Member("hello") { J = 20 };
Member m4 = new Member() { I = 10, J = 20 };

 

만약 이러한 속성에 기본값을 지정해야 한다면 다음과 같이 처리할 수 있습니다.

 

public int J
{
    get;
    set;
} = 100;

 

또한 람다식을 사용하면 get 정의에 한해 단일문으로 속성을 정의할 수 있습니다.

 

public int I => 100;

'Programming > .NET' 카테고리의 다른 글

[C#] 람다식 (Lambda expression)  (0) 2018.05.02
[ASP.NET MVC] 바인딩(Binding)  (0) 2018.04.25
[C#] 자동구현속성  (0) 2018.04.17
[C#] 익명메서드(anonymous method)  (0) 2018.04.10
[ASP.NET MVC] Web API  (0) 2018.03.28
[ASP.NET MVC] 필터(Filter)  (0) 2018.03.20
0 0
etc
https://blog.naver.com/q_w963/221232470189

'etc' 카테고리의 다른 글

뮤지컬<파워레인저>  (0) 2018.05.15
4월 초대장 드림[마감]  (46) 2018.05.02
뮤지컬 <명성황후>  (0) 2018.04.12
뮤지컬 <캐리와 장난감 친구들>  (0) 2018.04.12
한성인민 A36X에 16GB 메모리 달기  (3) 2016.07.05
PowerMockUp 소개  (0) 2016.04.12
0 0
etc

https://blog.naver.com/q_w963/221232477964

'etc' 카테고리의 다른 글

4월 초대장 드림[마감]  (46) 2018.05.02
뮤지컬 <명성황후>  (0) 2018.04.12
뮤지컬 <캐리와 장난감 친구들>  (0) 2018.04.12
한성인민 A36X에 16GB 메모리 달기  (3) 2016.07.05
PowerMockUp 소개  (0) 2016.04.12
특정 단어로 여러 페이지 소스 찾기  (0) 2012.07.31
0 0
Programming/.NET

익명메서드란 이름이 없는 메서드로서 프로그램 처리과정중 일시적으로 사용될 메서드를 델리게이트로 전달하고자 할때 사용될 수 있습니다.

 

static void Main(string[] args)
{
    anonMethod(null);
    Console.Read();
}

static void anonMethod(object o)
{
    Console.WriteLine("method");
}

 

위 예제는 anonMethod라는 전형적인 메서드 구현 방법을 보여주고 있습니다. 이를 익명메서드로 수정하면 다음과 같이 할 수 있습니다.

 

static void Main(string[] args)
{
    Thread td = new Thread(delegate (object o) { Console.WriteLine("method")});
    td.Start();

    Console.Read();
}

 

혹은 아예 델리게이트를 변수에 담아두고 사용하는 것도 가능합니다.

 

delegate void callMethod(object o);

static void Main(string[] args)
{
    callMethod cm = delegate (object o) { Console.WriteLine("method")};
    cm(null);

    Console.Read();
}

 

'Programming > .NET' 카테고리의 다른 글

[ASP.NET MVC] 바인딩(Binding)  (0) 2018.04.25
[C#] 자동구현속성  (0) 2018.04.17
[C#] 익명메서드(anonymous method)  (0) 2018.04.10
[ASP.NET MVC] Web API  (0) 2018.03.28
[ASP.NET MVC] 필터(Filter)  (0) 2018.03.20
[ASP.NET MVC] 컨트롤러(Controller)  (0) 2018.03.14
0 0
1
블로그 이미지

클리엘