티스토리 뷰

반응형

Portable Library (.Net Framework 4.5 : WPF, Metro style app)에서 Single Page Application에서 만들어 놓은 WebAPI를 사용해서 CRUD를 하는 방법에 대해 알아보도록 하자.

 

참고 강의 :

2012년 4월 14일 송파 KOSTA 이복영 강사님 주말반 수업 내용

 

1. 기본 준비

1) Using MVVM Pattern in Portable Library

http://kaki104.tistory.com/entry/Using-MVVM-Pattern-in-Portable-Library

 

2) MVC4 - Single Page Application (SPA)

http://kaki104.tistory.com/category/HTML5/MVC4

 

위의 2개의 포스트를 먼저 읽고, 첨부 파일을 받아서 실행할 준비가 되어 있어야 한다.

 

2. SPASample

솔루션을 열고, 실행한 후 http://localhost:61466/person 으로 이동한다.(IIS가 계속 실행이 되고 있어야 한다)

처음에는 1개의 레코드만 있는데 몇개의 레코드를 추가해 준다.

 

3. SamplePortableClassLibrary 

솔루션을 열고 프로젝트의 Propertys로 이동해서 Change Target Frameworks 창을 열어서 Silverlight에 체크를 풀고 OK

 

 

Solution Explorer에서 Silverlight 프로젝트와 Silverlight Web 프로젝트를 솔루션에서 제거한다.

 

 

4. PersonViewModel.cs 수정

//상단에 추가

HttpClient client;

 

...

 

//수정

public PersonViewModel()
{
    //httpClient 초기화
    client = new HttpClient();

 

    //데이터를 임으로 등록한 부분을 막아 놓는다. - SPA에서 데이터를 불러와서 사용한다.

    //People = new ObservableCollection<Person>
    //{
    //    new Person{ Id=0 , Age=11 , Name="kaki104" , Sex=true},
    //    new Person{ Id=1 , Age=22 , Name="kakao" , Sex=false},
    //    new Person{ Id=2 , Age=33 , Name="kass" , Sex=true},
    //    new Person{ Id=3 , Age=44 , Name="kameo" , Sex=false},
    //    new Person{ Id=4 , Age=55 , Name="keroro" , Sex=true}
    //};
    //CurrentPerson = People.FirstOrDefault();

 

    //전체 데이터 가져오기

    getAllData();
}

...

 

private async void getAllData()
{
    //전체 데이터 조회
    var response = await client.GetAsync("http://localhost:61466/api/personContainer/GetPeople");
    string content = await response.Content.ReadAsStringAsync();
    var people = StaticFunctions.ReadToObject(typeof(ObservableCollection<Person>), content) as ObservableCollection<Person>;
    People = new ObservableCollection<Person>(people);
}

 

...

 

/// <summary>
/// Single Page Application에 있는 WebAPI를 호출해서 CRUD 작업
/// </summary>
/// <param name="url"></param>
/// <param name="person"></param>
private async void SPA_crud_Operation(string url, Person person)
{
    var response = await client.PostAsync(url,
                            new StringContent(StaticFunctions.WriteFromObject(typeof(Person), person),
                            Encoding.UTF8,
                            "application/json"));

    string content = await response.Content.ReadAsStringAsync();
    var resultPerson = StaticFunctions.ReadToObject(typeof(Person), content) as Person;
    if (resultPerson != null)
    {
        person.Id = resultPerson.Id;
        person.Age = resultPerson.Age;
        person.Name = resultPerson.Name;
        person.Sex = resultPerson.Sex;
    }
}

 

...

 

ICommand addCommand;
public ICommand AddCommand
{
    get
    {
        if (addCommand == null)
        {
            addCommand = new DelegateCommand(obj =>
            {
                CurrentPerson = new Person();
                //서버에서 Id를 자동으로 생성하기 때문에 여기는 막음
                //CurrentPerson.Id = People.Max(p => p.Id) + 1;
                People.Add(CurrentPerson);
                string url = "http://localhost:61466/api/personContainer/InsertPerson";
                SPA_crud_Operation(url, CurrentPerson);
            });
        }
        return addCommand;
    }
}

 

...

 

ICommand selectChangedCommand;
public ICommand SelectChangedCommand
{
    get
    {
        if (selectChangedCommand == null)
        {
            selectChangedCommand = new DelegateCommand(obj =>
            {
                var person = obj as Person;
                if (person != null && People.Count(p => p.Id == person.Id) > 0)
                {

                    //현재 Person 업데이트
                    if (CurrentPerson != null)
                    {
                        string url = "http://localhost:61466/api/personContainer/UpdatePerson";
                        SPA_crud_Operation(url, CurrentPerson);
                    }

                    CurrentPerson = person;
                }
            });
        }
        return selectChangedCommand;
    }
}

...

 

ICommand removeCommand;
public ICommand RemoveCommand
{
    get
    {
        if (removeCommand == null)
        {
            removeCommand = new DelegateCommand(obj =>
            {
                var person = obj as Person;
                if (person != null && People.Count(p => p.Id == person.Id) > 0)
                {
                    People.Remove(person);
                    string url = "http://localhost:61466/api/personContainer/DeletePerson";
                    SPA_crud_Operation(url, person);
                }
            });
        }
        return removeCommand;
    }
}

5. StaticFunctions.cs

Json -> Object, Object -> Json으로 변경하는 함수를 만든다.

 

public static class StaticFunctions
{
    // Create a User object and serialize it to a JSON stream.
    public static string WriteFromObject(Type type, object data)
    {
        //Create a stream to serialize the object to.
        MemoryStream ms = new MemoryStream();

        // Serializer the User object to the stream.
        DataContractJsonSerializer ser = new DataContractJsonSerializer(type);
        ser.WriteObject(ms, data);
        byte[] json = ms.ToArray();

        return Encoding.UTF8.GetString(json, 0, json.Length);
    }

    // Deserialize a JSON stream to a User object.
    public static object ReadToObject(Type type, string json)
    {
        MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json));
        DataContractJsonSerializer ser = new DataContractJsonSerializer(type);
        object returnValue = ser.ReadObject(ms);
        return returnValue;
    }
}

여기까지 코딩이 완료가 되면 빌드를 하고 일단 WpfApplication1을 시작 프로젝트로 만들고 실행해 보자

 

6. WPF project

실행화면으로 http://localhost:61466/person 웹에서 보이는 내용과 동일한 내용이 출력된 것을 알 수 있다. 이곳에서 Id 9번 레코드를 선택하고 Set Current 버튼을 눌러서 편집을 하고, 완료 후에 다른 레코드를 선택해서 Set Current 버튼을 눌러서 Update를 하도록 한다.

 변경된 9번 레코드의 내용이다.

 웹으로 이동해서 변경한 내용이 적용되었는지 확인해 본다.

 

WPF Application에서 Add People 버튼을 눌러서 레코드를 추가하고, 웹에서 확인한다.

 Id = 10번 레코드가 추가가 되어 있는 것을 확인 할 수 있다.

 

방금 추가한 10번 레코드를 선택하고 Set Current 버튼을 눌러서 현재 레코드로 만든 후 Remove People 버튼을 눌러서 삭제를 하자.

10번 레코드가 삭제가 되어 있는 것을 볼 수 있다.

 

 

7. Metro style app

프젝트를 중지하고, Application1을 시작 프로젝트로 지정하고 실행한다.

예상은 하고 있었겠지만, WPF Application과 동일한 결과가 출력되고, Insert, Update, Delete모두 잘 동작된다.

 

 

 

8. Single Page Application을 이용해서

Web, WPF, Metro style app까지 SQL CE 4.0 Database에 CRUD를 하는 방법에 대해서 알아 보았다. 아쉬운 점은 Silverlight까지는 지원이 않된다는 것인데..앞으로 지원이 가능해 진다면, Portable Library의 활용범위가 무척 넓어 질 것이라고 생각한다. 그리고, 이 포스트에서 다루지는 않았지만, MEF, Rx 2.0 beta 기능을 추가하면 훨씬 더 강력한 Portable Library를 만들 수 있다.

 

9. 소스

 

SamplePortableClassLibrary_webapi.zip

반응형
댓글