Post List

레이블이 C#인 게시물을 표시합니다. 모든 게시물 표시
레이블이 C#인 게시물을 표시합니다. 모든 게시물 표시

2016년 6월 22일 수요일

윈도우 앱 개발 그룹(Facebook) 6월 오프라인 모임 후기

윈도우 앱 개발 그룹(Facebook) 6월 오프라인 모임 후기

  • 일시 : 2016년 6월 22일 수요일 19:00 ~ 22:00
  • 장소 : 토즈 강남점
이 모임을 처음 간 것은 4월달이었습니다. 회사를 강남 근처로 옮기니 여러가지 스터디와 모임을 참가할 수 있어서 너무 좋네요.
박문찬 MVP님 (https://www.facebook.com/kaki104)이 매달 1번씩 윈도우 앱에 대해서 소개해주시는 오프라인 모임을 준비해 주십니다. 이번에는 Bot Framework에 대해서 소개를 해 주셨으며, 간단한 예제를 같이 만들어보았습니다.
참가자들

박문찬님의 Bot Framework에 대한 설명 및 따라하기 예제

Bot Framework 란 ???

Bot Framework라는것 자체가 인공지능이라던지 그런건 아니었습니다. 단지 Web API로 개발한 서비스를 채팅 API와 연결해 주는 역할 정도랄까요 ? 단순히 웹브라우저나 자체적으로 앱을 만들어서 해당 서비스를 제공할 경우에는 큰 의미가 없겠지만, 우리가 개발한 서비스를 Facebook Messanger 나 카카오톡라인Slack텔레그램 등... 을 통해서 서비스 가능하게 해주는 역할을 하는 것입니다.
모임시간에는 간단한 에코봇과 샌드위치 주문을 받아주는 봇을 만들어 보았습니다.
Telegram에서 @LunaSampleBot에게 말을 걸면 예제를 직접 실행해 보실 수 있습니다.


2016년 6월 12일 일요일

Entity Framework Code First (Table 생성 및 수정)

Entity Framework Code First (Table 생성 및 수정)

Code First란 ?

전통적인 방식의 경우 SQL을 이용하여 Database에 Table을 생성한 다음 Application에서 개발을 시작합니다. Code First방식이란 Domain Class의 명세를 이용하여 Application 실행 시 해당 Table이 없는 경우 자동으로 생성을 해주는 방식을 말합니다.
Entity Framework 4.1 이후부터 지원해주는 방식이며, Domain Driven Design의 경우 유용합니다.
. Modify Models after Scaffolding

Code First 실습

1. Project 생성 및 Entity Framework 설치

  • Visual Studio에서 C# Console Application Project를 하나 생성합니다.
  • Nuget Package Manager를 실행합니다. (아래 방법 중 하나로 실행이 가능합니다.)
    • Solution Explorer에서 Project에서 우클릭하여 Manage Nuget Packages...
    • 상단 Menu에서 Tools -> Nuget Package Manager -> Manage Nuget Packages for Solution...
  • EntityFramework를 검색하여 설치합니다. (4.1 이후 버전으로 설치합니다. 이 Post를 작성할 당시 6.1.3 버전이 최신입니다.)

2. Domain Model 정의

아래와 같이 School 과 Standard라는 2개의 Domain Model을 정의합니다.
class Student
{
    public int       StudentID   { get; set; }
    public string    StudentName { get; set; }
    public DateTime? DateOfBirth { get; set; }
    public byte[]    Photo       { get; set; }
    public decimal   Height      { get; set; }
    public float     Weight      { get; set; }

    public Standard  Standard    { get; set; }
}

class Standard
{
    public int    StandardID   { get; set; }
    public string StandardName { get; set; }

    public ICollection<Student> Students { get; set; }
}
School은 Standard의 참조를 가지고 있으며, Standard는 School의 집합을 가지고 있습니다.

3. Entity Framework Context 정의

using System.Data.Entity;
DbContext를 사용하기 위해서는 System.Data.Entity를 using해주면 편합니다.
class SchoolContext : DbContext
{
    public DbSet<Student> Students { get; set; }
    public DbSet<Standard> Standards { get; set; }
}
2개의 Domain Model을 DbSet Property로 정의합니다.
특정 Database로의 접근을 원할 경우 DbContext의 생성자로 Connection String를 전달하도록 생성자를 정의해주면 됩니다. Console Application Project에서 default일 경우 Visual Studio와 함께 설치된 LocalDB로 연결 됩니다.

4. Context 실행

class Program
{
    static void Main(string[] args)
    {
        using (var context = new SchoolContext())
        {
            Student s = new Student() { StudentName = "New Student" };

            context.Students.Add(s);
            context.SaveChanges();
        }
    }
}
Database에 따로 Table을 생성하지 않고 위 Code를 실행하면 자동으로 Table이 생성됩니다.
그림 Table Created
그림에서 확인되는 것을 보면 Standard에는 Student에 대한 항목이 없으며, Student에는 Standard_StandardID라는 Foreign Key가 추가 된 것이 확인됩니다.
개발 또는 운영 중 새로운 Table이 추가 될 경우에는 Domain Model을 선언하고 Context의 DbSet Property를 선언해주면 됩니다.

Change Models after Scaffolding

1. Domain Model 수정

먼저 Teacher Model을 추가한 뒤,
class Teacher
{
    public int TeacherID { get; set; }
    public string TeacherName { get; set; }
}
Student에 Teacher의 참조를 추가합니다.
class Student
{
    public int StudentID { get; set; }
    public string StudentName { get; set; }
    public DateTime? DateOfBirth { get; set; }
    public byte[] Photo { get; set; }
    public decimal Height { get; set; }
    public float Weight { get; set; }

    public Standard Standard { get; set; }
    public Teacher Teacher { get; set; }
}

2. Context 실행

F5를 눌러서 실행을 하면 오류가 발생합니다.
Domain Model의 새로운 Property가 추가될 경우에는 오류가 발생합니다. (Table 입장에서는 Column이 추가되어야 할 경우)
이 경우에는 Migration 이라는 작업을 따로 해 줘야 합니다.
여러 가지 방법이 존재합니다.
  1. Package Manager Console에서 Enable-Migrations 명령어를 이용
  2. Connection String에서 Database name을 변경
  3. Entity Framework에서 Database Initializer를 사용
위 방법 중 3번 방법이 가장 편하므로, 해당 방법만 설명 드리겠습니다.

3. Database Initializer 선언

class SchoolInitializer : DropCreateDatabaseIfModelChanges<SchoolContext>
{
    protected override void Seed(SchoolContext context)
    {
        base.Seed(context);
    }
}
별도의 작업이 필요한 경우 Seed() 안에서 정의를 해주면 됩니다. 현재는 별 다른 작업이 필요 없으므로 Seed()Override하지 않고 삭제해도 됩니다.

4. Database Initializer 실행

Application 실행시 Database Initializer를 먼저 실행시켜 주면 오류 없이 Table이 수정됩니다. 심지어 DbSet Property에 Teacher를 추가하지 않았는데도 불구하고 Teacher Table이 추가되었습니다.
class Program
{
    static void Main(string[] args)
    {
        Database.SetInitializer<SchoolContext>(new SchoolInitializer());

        using (var context = new SchoolContext())
        {
            Student s = new Student() { StudentName = "New Student" };

            context.Students.Add(s);
            context.SaveChanges();
        }
    }
}
일단 오류없이 실행은 되었습니다. Database를 확인해 보면 Table 정보가 수정된 것을 볼 수 있습니다.
그림 Table Modified

2016년 5월 24일 화요일

ASP.NET MVC : View

View

View 란?

MVC Framework에서 사용자에게 결과를 보여주는 역할을 합니다.
ASP.NET에서는 Razor Engine을 이용하여 View를 조금 더 편하게 작성 할 수 있습니다. (.cshtmlRazor Engine이 무엇인지 간단하게 얘기하자면 View (HTML page) 작성시 C# 문법과 .NET Framework를 사용할 수 있습니다. LayoutPartial View를 이용하여 특정 영역만 따로 rendering 하는 것도 가능하며, 각종 Helper method를 제공하여서 반복적인 HTML TAG 작성 작업을 줄여주며, 직접 Helper method를 작성하여서도 활용 할 수 있습니다.
View의 기본적인 사용법은 Controller and Action 절에서 예제 작성시 간단히 언급했으므로 생략하도록 하겠습니다.
View를 편리하게 사용하기 위한 방법(주로 재활용 방안) 위주로 진행하겠습니다.

1. Layout section

Layout (주로 _Layout.cshtml 식의 명칭) 내부에는 section을 제공해 줍니다.
  • @RenderBody() : 해당 Layout을 사용하는 View의 내용이 이 위치에 삽입됩니다.
  • @RenderSection("Name") : View 에서 @section Name { ... } 의 내용이 해당 section에 삽입됩니다.
Layout에서 선언한 @RenderSection("...")이 View에서 사용하지 않으면 오류가 발생합니다. 해당 section에 선택적으로 사용을 하려면 (View에서 사용하지 않아도 오류가 발생하지 않게 하려면) @RenderSection("...", false)로 선언을 하면 됩니다.
*_Layout.cshtml
// _Layout.cshtml

...

<body>
    @RanderSection("Header")

    ...

    @RanderBody()

    ...

    @RanderSection("Footer", required = false)
</body>
  • Index.cshtml
@{
    Layout = "_Layout";
}

@section Header {
<div>This is Header</div>
}

<div>
    RenderBody contains every contents in this document, except @section ...
</div>

2. Partial View

Razor Tag, HTML Markup 으로 이루어진 동일한 코드를 반복적으로 사용할 경우 유용합니다.
  • Partial.cshtml
<div>
    This is Partial View.
    @Html.ActionLink("The Link of Index on this Controller", "Index")
</div>
  • List.cshtml
@{
    ViewBag.Title = "List";
    Layout = null;
}

<h3>List</h3>

@Html.Partial("Partial")
위의 경우 List.cshtml에서 Partial.cshtml의 Partial view를 사용하였는데, Partial view 내부를 보면 ActionLink를 Controller 이름을 명시하지 않았습니다. Partial View를 Rednering하는 곳이 List.cshtml 내부이기 때문에 해당 Controller를 기준으로 동작합니다.
Partial View도 ViewModel을 가질 수 있습니다. (Strongly Typed Partial View)
그럴 경우 @Html.Partial(...) 의 두번째 인자로 ViewModel을 전달해 줘야 합니다.
  • Partial2.cshtml
@model IEnumerable<string>
...
  • List.cshtml
...
@Html.Partial("Partial2", new [] { "Luna" , "Star" } )

3. Child Action

View 에서 호출되는 Action Method를 의미합니다. @Html.Action(...) helper method를 사용하면 모든 Action method를 View에서 호출이 가능하지만, [ChileActionOnly] 이란 attribute를 붙이면 Routing System에서 사용되지 않고 순수히 View에서 호출할 경우에만 동작하는 것을 의미합니다.
  • HomeController.cs
...
[ChildActionOnly]
public ActionResult Time()
{
    return PartialView(DateTime.Now);
}
  • Time.cshtml
@model DateTime
<div>
    @Model.ToShortTimeString()
</div>
  • List.cshtml
...
@Html.Action("Time")
Child Action에 매개변수가 필요한 경우에는 무명형식을 이용해서 전달이 가능합니다. 단 파라메터의 이름이 같아야 합니다.
  • HomeController.cs
...
[ChildActionOnly]
public ActionResult Time(DateTime time)
{
    return PartialView(DateTime.Now);
}
  • List.cshtml
...
@Html.Action("Time", new { time = DateTime.Now })

2016년 5월 21일 토요일

Newtonsoft.Json 사용하기 : C# (.Net) 에서 JSON 생성 및 Parsing 하기

Newtonsoft.Json 사용법

C# 에서 JSON document를 다루기 위해 가장 많이 사용되는 것은 Newtonsoft.Json입니다. nuget manager에서 JSON으로 검색시 가장 먼저 나옵니다. 그만큼 많이 사용되며, 사용법 또한 간단합니다.

1. 설치 및 namespace

솔루션 탐색기 (Solution Explorer)에서 마우스 우클릭 하신뒤 Manage nuget packages...을 누르셔서 Browse 탭에서Newtonsoft.Json을 검색하셔서 Install을 누르면 됩니다.
그림 MVC
다른 방법으로는 도구(Tools) -> Nuget package manager -> Package Manager Console 로 가셔서 아래와 같이 입력하시면 됩니다.
PM> Install-Package Newtonsoft.Json
사용시 소스코드에서 아래의 namespace를 추가해 주시면 됩니다.
using Newtonsoft.Json.Linq;

2. 간단한 특징 설명

2개의 Object를 이용해서 사용하시면 됩니다.
  • JObject : JSON Object 입니다.
    • JObject 자체가 name값을 가질 수는 없습니다.
    • (key, value) pair 들을 가질 수 있습니다.
    • key : string 값입니다.
    • value : JToken 타입이며 대부분의 premitive type들과 DateTime, TiemSpan, Uri 값을 직접대입 가능하며, 기타 Object도 입력이 가능합니다.
      • value에 다른 JObject나, JArray를 넣을 수 있습니다.
  • JArray : JSON Array 입니다.
    • JObject와 특징이 거의 비슷하나 key 없이 value 들을 가지고 있습니다.
즉, JObject나 Jarray 자체는 name을 가질 수 없으나, 다른 JObject에 value로 소속될 경우에는 key값을 가져야 하며, 다른 JArray에 소속될 경우에는 key값 없이 입력됩니다

3. JObject 사용법

너무나 간단하기 때문에 별도 설명은 필요 없을듯 합니다.
  • 생성 : new JObject()
  • Element 추가 : .add(key, value)
바로 예제를 보도록 하겠습니다.

3.1 Element 추가

3.1.1 기본적인 사용법

var json = new JObject();
json.Add("id", "Luna");
json.Add("name", "Silver");
json.Add("age", 19);

Console.WriteLine(json.ToString());
{
  "id": "Luna",
  "name": "Silver",
  "age": 19
}

3.1.2 JSON 형식의 문자열로 생성

var json2 = JObject.Parse("{ id : \"Luna\" , name : \"Silver\" , age : 19 }");
json2.Add("blog", "devluna.blogspot.kr");

Console.WriteLine(json2.ToString());
{
  "id": "Luna",
  "name": "Silver",
  "age": 19,
  "blog": "devluna.blogspot.kr"
}

3.1.3 다른 class Object로부터 생성

User u = new User { id = "SJ", name = "Philip", age = 25 };
var json3 = JObject.FromObject(u);

Console.WriteLine(json3.ToString());
{
  "id": "SJ",
  "name": "Philip",
  "age": 25
}

3.1.4 무명형식으로 생성

var json4 = JObject.FromObject(new { id = "J01", name = "June", age = 23 });

Console.WriteLine(json4.ToString());
{
  "id": "J01",
  "name": "June",
  "age": 23
}

3.1.5 다른 JObject를 Element로 추가

var json5 = JObject.Parse("{ id : \"sjy\" , name : \"seok-joon\" , age : 27 }");
json5.Add("friend1", json);
json5.Add("friend2", json2);
json5.Add("friend3", json3);
json5.Add("friend4", json4);

Console.WriteLine(json5.ToString());
{
  "id": "sjy",
  "name": "seok-joon",
  "age": 27,
  "friend1": {
    "id": "Luna",
    "name": "Silver",
    "age": 19
  },
  "friend2": {
    "id": "Luna",
    "name": "Silver",
    "age": 19,
    "blog": "devluna.blogspot.kr"
  },
  "friend3": {
    "id": "SJ",
    "name": "Philip",
    "age": 25
  },
  "friend4": {
    "id": "J01",
    "name": "June",
    "age": 23
  }
}

3.2 Element값 사용하기

3.2.1 Element값 읽기

[ ] 연산자에 key값을 넣어주면 해당 value를 얻을 수 있습니다.
var json4_name = json4["name"];

Console.WriteLine(json4_name);
June

3.2.2 Element값 삭제하기

.Remove(key)를 이용해서 삭제가 가능합니다.
json4.Remove("name");

Console.WriteLine(json4.ToString());
{
  "id": "J01",
  "age": 23
}
.RemoveAll()로 모든 Element를 다 삭제 할 수도 있습니다.
json5.RemoveAll();

Console.WriteLine(json5.ToString());
{}

4. JArray 사용법

Element 입력시 key를 가지지 않는 다는 것을 빼고는 JObject와 거의 같습니다.

4.1 Element 추가하기

4.1.1 기본적인 사용법

var jarray = new JArray();
jarray.Add(1);
jarray.Add("Luna");
jarray.Add(DateTime.Now);

Console.WriteLine(jarray.ToString());
[
  1,
  "Luna",
  "2016-05-21T09:45:27.1049839+09:00"
]

!#4.1.2 JObject를 Element로 추가

var jFriends = new JArray();
jFriends.Add(json);
jFriends.Add(json2);
jFriends.Add(json3);
jFriends.Add(json4);

Console.WriteLine(jFriends.ToString());
[
  {
    "id": "Luna",
    "name": "Silver",
    "age": 19
  },
  {
    "id": "Luna",
    "name": "Silver",
    "age": 19,
    "blog": "devluna.blogspot.kr"
  },
  {
    "id": "SJ",
    "name": "Philip",
    "age": 25
  },
  {
    "id": "J01",
    "age": 23
  }
]

4.1.3 JArray를 Element로 추가

var jarray2 = new JArray();
jarray2.Add(jarray);
jarray2.Add(jFriends);

Console.WriteLine(jarray2.ToString());
[
  [
    1,
    "Luna",
    "2016-05-21T09:51:03.2882071+09:00"
  ],
  [
    {
      "id": "Luna",
      "name": "Silver",
      "age": 19
    },
    {
      "id": "Luna",
      "name": "Silver",
      "age": 19,
      "blog": "devluna.blogspot.kr"
    },
    {
      "id": "SJ",
      "name": "Philip",
      "age": 25
    },
    {
      "id": "J01",
      "age": 23
    }
  ]
]

4.2 Element값 사용하기

4.2.1 Element값 읽기

[ ] 연산자로 읽을 수 있습니다.
var jf0 = jFriends[0];

Console.WriteLine(jf0.ToString());
{
  "id": "Luna",
  "name": "Silver",
  "age": 19
}
for , foreach로 iteration이 가능합니다.
foreach(JObject fElement in jFriends)
{
    var fName = fElement["name"] ?? "<NULL>";
    Console.WriteLine(fName);
}
Silver
Silver
Philip
<NULL>

4.2.2 Element값 삭제하기

jFriends.Remove(jFriends[1]);
jFriends.Remove(jFriends[2]);

Console.WriteLine(jFriends.ToString());
[
  {
    "id": "Luna",
    "name": "Silver",
    "age": 19
  },
  {
    "id": "SJ",
    "name": "Philip",
    "age": 25
  }
]

5. JObject에 JArray 추가하기

json2.Add("Friends", jFriends);

Console.WriteLine(json2.ToString());
{
  "id": "Luna",
  "name": "Silver",
  "age": 19,
  "blog": "devluna.blogspot.kr",
  "Friends": [
    {
      "id": "Luna",
      "name": "Silver",
      "age": 19
    },
    {
      "id": "SJ",
      "name": "Philip",
      "age": 25
    }
  ]
}