MixedCode

안녕하세요. 비지니스와 융합기술의 만남을 추구하는? 믹스드코드입니다. ^^

뷰,뷰모델에 이어 이번에는 뷰나 뷰모델에서 사용되는 데이터의 구조를 정의하고 데이터를 담아 전달하는 역할을 하는 데이터 모델에 대해 알아보고 데이터 모델의 정의방법을 알아봅니다. 

뷰모델에서의 데이터 제공처로 사용될 서버측 OPEN API 기반의 RESTful 방식의 데이터 저장소로부터 데이터를  호출하고 데이터 저장,조회,수정,삭제하는 방법들을 차근차근 알아봅니다.

3.Model 구성과 서버와 통신하기 - 기초편
일반적으로 모델의 용도는 데이터 구조를 객체지향적으로 개발언어(C#)로 표현하고 실제 데이터를 담거나 담아서 이동시키는(DTO) 기능을  기본적으로  제공합니다.

Application의 종류마다 데이터를 제공하는 방식이 조금씩 다르지만 요즘은 다양한 UI에서 필요한 데이터를  단일화되고  통합된 방식으로 제공하기 위해 웹기반의 RESTful이라는 JSON 데이터 포맷 형태로 데이터를 주고받는 데이터 처리 인터페이스 방식을 많이 사용하고 있습니다.   

Native App UI도  동일한 방식으로 특정 서버를 통해 JSON 데이터 포맷 기반의 RESTful 방식(OPEN API)으로 특정 서버에서 제공된 데이터를 사용하거나 해당 서버로 JSON포맷으로 데이터를 전송하여 각종 데이터를 처리합니다.

따라서 Natvie App Client Side App(Xamarin.Forms APP)은  서버측과 RESTful방식으로 통신하고 데이터구조를 JSON 포맷에서 데이터모델객체로 또는 데이터 모델객체를 JSON포맷으로 상호 변환할수 기능이 제공되어야합니다


1) OPEN API 통신을 위한  PCL 프로젝트 환경 구성하기
-서버측 OPEN API 와 RESTful 기반 통신을 하기 위해서는 Xamarin.Foms 클라이언트에서 RESTful 통신이 가능한 수단이 필요합니다.
해당 기능은 아래 경로의 System.Net.Http.dll 어셈블리에서 관련 Restful 통신기능을 제공합니다.
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\
ReferenceAssemblies\Microsoft\Framework\Xamarin.
iOS\v1.0\System.Net.Http.dll

1.1
System.Net.Http.dll 프로젝트 참조하기(RESTful 통신객체인 HttpClient 지원)
-PCL프로젝트의 참조 추가를 클릭합니다.
-상기 DLL의 경로를 찾아보기  노드의 찾아보기 버튼을 클릭하여 해당경로의 DLL파일을 선택하여 참조를 추가합니다.




1.2 NewtonSoft.Json NugetPackage 추가하기
- 서버로부터 전달되는 JSON포맷의 문자열 형태의 데이터 구조를 APP에서 정의한 데이터모델 객체 구조로 변경해주거나 데이터모델 객체 구조를 서버로 전달할때 JSON 포맷으로 변환해주기 위해 오픈소스로 제공되는   
NewtonSoft.Json.DLL을 Nuget Package저장소에서 조회하여 로컬 솔루션 팩키지로 다운받은 후 PCL프로젝트에 참조 추가합니다.
-PCL프로젝트를 선택하고 참조를 오른쪽 마우스 클릭하고 NugetPackage관리를 클릭합니다.
-찾아보기 탭에서  
NewtonSoft.Json 키워드를 입력하고 조회후 선택하고 설치를 클릭하여 PCL프로젝트에 해당 라이브러리를 추가합니다.




2) 데이터 모델 생성하기
먼저 DB로부터 전달되는 사용자 데이터의 구조를 표현하거나 뷰로부터 전달되는 사용자 데이터를 서버쪽에 전달하기 위한 구조를 표현하기 위해 UserModel.cs 클래스 파일을 Model폴더에 생성하고 데이터 구조를 기술해보도록 하겠습니다.
PCL 프로젝트에 Model폴더를 만들고 폴더 아래에 UserModel.cs 클래스 파일을 생성합니다.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace XamarinMVVMDemo.Model
{
    public class UserModel 
    {
        public string UserID { get; set; }
        public string UserName { get; set; }
        public string Email { get; set; }
        public string Telephone { get; set; }
        public DateTime? RegistDate { get; set; }
    }
}

4) 뷰모델 데이터 속성을 데이터 모델에 담아 OPEN API 서버로 전송하여 등록하기  
뷰모델의 사용자 등록 함수에서 뷰모델에 바인딩 된 데이터를 UserModel의 인스턴스에 값을 채우고 서버측 OPEN API에 데이터를 전송하는 기능을 구현해보도록 하겠습니다.
 
-in ViewModel

     //사용자 정보 신규등록
     private async void Regist()
        {
            UserModel user = new UserModel();
            user.UserID = this.UserID;
            user.UserName = this.UserName;
            user.Email = this.Email;
            user.Telephone = this.Telephone;
            user.RegistDate = DateTime.Now;

            string baseApiAddress = "http://mixedcode.com/api/user/";
            HttpClient client = new HttpClient();

            var uri = new Uri(baseApiAddress);
            var json = JsonConvert.SerializeObject(user);
            var content = new StringContent(json, Encoding.UTF8, "application/json");

            var response = await client.PostAsync(uri, content);
            var result = response.IsSuccessStatusCode;

            GetUserListBind();
        }


      //사용자 목록조회
      public void GetUserListBind()
        {
            string baseApi = "http://mixedcode.com/";

            HttpClient client = new HttpClient();
            client.BaseAddress = new Uri(baseApi);
            client.MaxResponseContentBufferSize = 256000;

            var response = client.GetAsync("api/user/").Result;

            List<UserModel> users = null;

            if (response.IsSuccessStatusCode)
            {
                var jsonResult = response.Content.ReadAsStringAsync().Result;
                users = JsonConvert.DeserializeObject<List<UserModel>>(jsonResult);

                UserDataList = new ObservableCollection<UserModel>(users);
            }
        }

  //사용자데이터 목록 바인딩 속성정의
        private ObservableCollection<UserModel> _UserDataList;
        public ObservableCollection<UserModel> UserDataList
        {
            get
            {
                return _UserDataList;
            }

            set
            {
                _UserDataList = value;
                OnPropertyChanged("UserDataList");
            }
        }


-ViewModel 전체코드

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


using System.ComponentModel;
using System.Windows.Input;
using Xamarin.Forms;
using XamarinMVVMDemo.Model;
using System.Net.Http;
using Newtonsoft.Json;
using System.Net.Http.Headers;
using System.Collections.ObjectModel;


namespace XamarinMVVMDemo.ViewModel
{
    public class MainPageViewModel : INotifyPropertyChanged
    {

        public MainPageViewModel()
        {

            RegistCommand = new Command(Regist);
            ModifyCommand = new Command<string>(Modify);
            DeleteCommand = new Command(Delete);

            this.UserID = "Eddy.Kang";
            this.UserName = "강창훈";
            this.Email = "admin@signalsoft.co.kr";
            this.Telephone = "010-2760-5246";
            this.RegistDate = DateTime.Now;

            GetUserListBind();
        }


        public ICommand RegistCommand{ get; private set; }

        public ICommand ModifyCommand { get; private set; }

        public ICommand DeleteCommand { get; private set; }


        private async void Regist()
        {
            UserModel user = new UserModel();
            user.UserID = this.UserID;
            user.UserName = this.UserName;
            user.Email = this.Email;
            user.Telephone = this.Telephone;
            user.RegistDate = DateTime.Now;

            string baseApiAddress = "http://mixedcode.com/api/user/";
            HttpClient client = new HttpClient();


            var uri = new Uri(baseApiAddress);
            var json = JsonConvert.SerializeObject(user);
            var content = new StringContent(json, Encoding.UTF8, "application/json");


            var response = await client.PostAsync(uri, content);
            var result = response.IsSuccessStatusCode;


            GetUserListBind();
        }


        private void Modify(string commandPrameter)
        {
            var test = commandPrameter;
        }


        private void Delete()
        {


        }


        public void GetUserListBind()
        {
            string baseApi = "http://mixedcode.com/";


            HttpClient client = new HttpClient();
            client.BaseAddress = new Uri(baseApi);
            client.MaxResponseContentBufferSize = 256000;


            var response = client.GetAsync("api/user/").Result;


            List<UserModel> users = null;


            if (response.IsSuccessStatusCode)
            {
                var jsonResult = response.Content.ReadAsStringAsync().Result;
                users = JsonConvert.DeserializeObject<List<UserModel>>(jsonResult);


                UserDataList = new ObservableCollection<UserModel>(users);
            }
        }


        private ObservableCollection<UserModel> _UserDataList;
        public ObservableCollection<UserModel> UserDataList
        {
            get
            {
                return _UserDataList;
            }


            set
            {
                _UserDataList = value;
                OnPropertyChanged("UserDataList");
            }
        }

        private string _UserID;
        public string UserID
        {
            get
            {
                return _UserID;
            }


            set
            {
                if (_UserID == value) return;
                _UserID = value;
                OnPropertyChanged("UserID");
            }
        }


        private string _UserName;
        public string UserName
        {
            get
            {
                return _UserName;
            }


            set
            {
                if (_UserName == value) return;
                _UserName = value;
                OnPropertyChanged("UserName");
            }
        }

        private string _Email;
        public string Email
        {
            get
            {
                return _Email;
            }


            set
            {
                if (_Email == value) return;
                _Email = value;
                OnPropertyChanged("Email");
            }
        }

        private string _Telephone;
        public string Telephone
        {
            get
            {
                return _Telephone;
            }


            set
            {
                if (_Telephone == value) return;
                _Telephone = value;
                OnPropertyChanged("Telephone");
            }
        }


        private DateTime? _RegistDate;
        public DateTime? RegistDate
        {
            get
            {
                return _RegistDate;
            }


            set
            {
                if (_RegistDate == value) return;
                _RegistDate = value;
                OnPropertyChanged("RegistDate");
            }
        }


        public event PropertyChangedEventHandler PropertyChanged;


        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this,new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}




-참고로 아래 코드는 실제 MIXEDCODE.COM에 샘플로 구현된 ASP.NET WEBAPI로 구현한 OPENAPI 클래스의 구조를 보여줍니다.

  [EnableCors(origins: "http://mixedcode.com", headers: "*", methods: "*")]
    public class UserController : ApiController
    {
        /// <summary>
        /// 사용자목록
        /// </summary>
        /// <returns></returns>
        public IEnumerable<UserModel> Get()
        {
            using (UserBiz userBiz = new UserBiz())
            {
                return userBiz.SelectUserAll().AsEnumerable<UserModel>();
            }
        }

        public IHttpActionResult GetUser(string id)
        {
            UserModel user = null;

            using (UserBiz biz = new UserBiz())
            {
                user = biz.SelectUserInfo(id);
            }
            if (user == null)
            {
                return NotFound();
            }
            return Ok(user);
        }

        public IHttpActionResult Post(UserModel user)
        {
            using (UserBiz biz = new UserBiz())
            {
                biz.CreateUser(user);
            }
            return Ok(user);
        }

        public IHttpActionResult Put(UserModel user)
        {
            using (UserBiz biz = new UserBiz())
            {
                biz.ModifyUser(user);
            }
            return Ok(user);
        }

        public IHttpActionResult Delete(string id)
        {
            using (UserBiz biz = new UserBiz())
            {
                biz.DeleteUser(id);
            }
            return Ok("");
        }
    }


5) 서버의 Open API로부터 제공된 사용자 목록 데이터를 뷰의 리스트뷰 컨트롤에 관련 뷰모델의 속성으로  바인딩 처리합니다.
-in Xaml

        <ListView Grid.Row="7" Grid.ColumnSpan="2" HorizontalOptions="Fill" ItemsSource="{Binding UserDataList}" 
                  RowHeight="30" VerticalOptions="FillAndExpand"  BackgroundColor="{StaticResource BackgroundColorType1}" >
            <ListView.ItemTemplate>
                <DataTemplate>

                    <ViewCell>
                        <Grid  VerticalOptions="Fill" Margin="5,5,5,5">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="20"></RowDefinition>
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="1.*"></ColumnDefinition>
                                <ColumnDefinition Width="1.*"></ColumnDefinition>
                                <ColumnDefinition Width="1.*"></ColumnDefinition>
                                <ColumnDefinition Width="1.*"></ColumnDefinition>
                                <ColumnDefinition Width="1.*"></ColumnDefinition>
                            </Grid.ColumnDefinitions>
                            <Label Grid.Row="0" Grid.Column="0" Text="{Binding UserID}" HorizontalOptions="Start" VerticalOptions="Center" TextColor="White" FontAttributes="Bold"></Label>
                            <Label Grid.Row="0" Grid.Column="1" Text="{Binding UserName}" HorizontalOptions="Start" VerticalOptions="Center" TextColor="White" FontAttributes="Bold"></Label>
                            <Label Grid.Row="0" Grid.Column="2" Text="{Binding Email}" HorizontalOptions="Start" VerticalOptions="Center" TextColor="White" FontAttributes="Bold"></Label>
                            <Label Grid.Row="0" Grid.Column="3" Text="{Binding Telephone}" HorizontalOptions="Start" VerticalOptions="Center" TextColor="White" FontAttributes="Bold"></Label>
                            <Label Grid.Row="0" Grid.Column="4" Text="{Binding RegistDate}" HorizontalOptions="Start" VerticalOptions="Center" TextColor="White" FontAttributes="Bold"></Label>
                        </Grid>
                    </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
        </ListView>

배포결과:




이제  빌드 배포하고 디버깅모드에서 신규 사용자 정보를 입력하고 REGIST 버튼을 클릭하여 신규 사용자를 등록하면 헤당 데이터가 서버로 전달되어 데이터가 SQL DB에 저장된후 저장된 모든 사용자 정보를
다시 조회하여 화면의 사용자 목록 을 갱신하는것을 확인할수 있습니다. 

지금 까지 데이터 모델을 이용한 서버와 RESTful방식으로 데이터를 저장하고 조회하는 방법을 알아보았습니다.
모델 심화 편에서는  전체 신규/수정 기능을 저장 기능하나로  통합하고 수정 및 삭제 기능또한 구현해보도록 하고 단순 데이터 모델을 뷰모델형태로 확장하여 뷰모델의 바인딩 속성 구조를 단순화 시켜보도록 하겠습니다.

감사합니다.





Comments

Leave a Reply

*