23.06.05 Day87

오윤범·2023년 6월 5일
0

RestAPI

1) Views/Shared/_Layout.cshtml 수정
2) Home/Index.cshtml 수정

RestAPI를 WPF에서 사용하기

1) WPF 애플리케이션으로 프로젝트 생성
2) 누겟 패키지 관리

3) MainWindow.xaml 디자인

<mah:MetroWindow x:Class="TodoItemApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TodoItemApp"
        mc:Ignorable="d"
        Title="TodoList" Height="450" Width="800" Loaded="MetroWindow_Loaded">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="3*"/>
            <ColumnDefinition Width="2*"/>
        </Grid.ColumnDefinitions>

        <DataGrid Grid.Column="0" x:Name="GrdTodoItems" Margin="10" Background="Gainsboro"></DataGrid>

        <Grid Grid.Column="1" Margin="20">
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
                <RowDefinition/>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <TextBox Grid.Row="0" x:Name="TxtId" mah:TextBoxHelper.AutoWatermark="True" mah:TextBoxHelper.Watermark="Id"
                     FontSize="14" Margin="5"/>
            <TextBox Grid.Row="1" x:Name="TxtTitle" mah:TextBoxHelper.AutoWatermark="True" mah:TextBoxHelper.Watermark="Title"
                     FontSize="14" Margin="5"/>
            <mah:DateTimePicker Grid.Row="2" x:Name="DtpTodoDate" mah:TextBoxHelper.AutoWatermark="True" mah:TextBoxHelper.Watermark="TodoDate"
                                FontSize="14" Margin="5"/>
            <ComboBox Grid.Row="3" x:Name="CboIsComplete" FontSize="14" Margin="5"
                      mah:TextBoxHelper.AutoWatermark="True" mah:TextBoxHelper.Watermark="IsComplete"/>
            <StackPanel Orientation="Horizontal" Grid.Row="4">
                <Button x:Name="BtnInsert" Content="Insert" FontSize="14" Width="90" Margin="1,10"/>
                <Button x:Name="BtnUpdate" Content="Update" FontSize="14" Width="90" Margin="1,10"/>
                <Button x:Name="BtnDelete" Content="Delete" FontSize="14" Width="90" Margin="1,10"/>
            </StackPanel>
        </Grid>
    </Grid>
</mah:MetroWindow>

Day87

1) 누겟 패키지 관리

  • Microsoft.AspNet.WebApi.Client 설치

2) Models/TodoItem , TodoItemsCollection 클래스 추가

  • TodoItem.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;

namespace TodoItemApp.Models
{
    public class TodoItem
    {
        [Key]
        public int Id { get; set; }

        [Column(TypeName = "Varchar(100)")]
        public string? Title { get; set; }

        public string TodoDate { get; set; }
        public int IsComplete { get; set; }
    }
}
  • TodoItemsCollection.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Specialized;

namespace TodoItemApp.Models
{
    public class TodoItemsCollection : ObservableCollection<TodoItem>
    {
        public void CopyForm(IEnumerable<TodoItem> todoItems)
        {
            this.Items.Clear();//초기화
            foreach (TodoItem item in todoItems)
            {
                this.Items.Add(item);//데이터 추가
            }
            //데이터 변경을 알림
            this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        }
    }
}

3) MainWindow.xaml.cs 수정

using MahApps.Metro.Controls;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using TodoItemApp.Models;
using System.Net.Http.Headers;
using MahApps.Metro.Controls.Dialogs;
using System.Diagnostics;

namespace TodoItemApp
{
    public class DivCode
    {
        public string Key { get; set; }
        public string Value { get; set; } 
    }
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : MetroWindow
    {
        private List<DivCode> divCodes= new List<DivCode>();
        HttpClient client = new HttpClient();
        TodoItemsCollection todoItems = new TodoItemsCollection();

        public MainWindow()
        {
            InitializeComponent();
        }

        private async void MetroWindow_Loaded(object sender, RoutedEventArgs e)
        {
            divCodes.Add(new DivCode { Key = "True", Value = "1" });
            divCodes.Add(new DivCode { Key = "False", Value = "0" });
            CboIsComplete.ItemsSource=divCodes;
            CboIsComplete.DisplayMemberPath = "Key"; //콤보박스에 True/False 추가

            //yyyy-MM--dd HH:mm:ss 
            DtpTodoDate.Culture = new System.Globalization.CultureInfo("ko-KR");
            //RestAPI 기본 URI 호출
            client.BaseAddress = new Uri("https://localhost:7188/");//RestAPI 서버 기본 URL
            //헤더 설정
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            GetData();//데이터 로드 메서드 호출
        }

        private async void GetData()
        {
            //데이터그리드 ItemsSource에 todoItems 바인딩
            GrdTodoItems.ItemsSource = todoItems;
            //Api 호출 핵심
            try
            {
                HttpResponseMessage? response = await client.GetAsync("api/TodoItems");
                response.EnsureSuccessStatusCode();

                var items = await response.Content.ReadAsAsync<IEnumerable<TodoItem>>();
                todoItems.CopyForm(items);
            }
            catch (Newtonsoft.Json.JsonException jEx)
            {
                await (this.ShowMessageAsync("error", jEx.Message, MessageDialogStyle.Affirmative, new MetroDialogSettings()
                { AnimateShow = true, AnimateHide = true }));
            }
            catch (HttpRequestException ex)
            {
                await (this.ShowMessageAsync("error", ex.Message, MessageDialogStyle.Affirmative, new MetroDialogSettings()
                { AnimateShow = true, AnimateHide = true }));
            }
        }

        private async void BtnInsert_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                var todoItem = new TodoItem()
                {
                    Id = 0,
                    Title = TxtTitle.Text,
                    TodoDate = ((DateTime)DtpTodoDate.SelectedDateTime).ToString("yyyy-MM-dd HH:mm:ss"),
                    IsComplete = Int32.Parse((CboIsComplete.SelectedItem as DivCode).Value)
                };

                var response = await client.PostAsJsonAsync("api/TodoItems", todoItem);
                response.EnsureSuccessStatusCode();

                GetData();

                TxtId.Text = TxtTitle.Text = string.Empty;
                CboIsComplete.SelectedIndex = -1;
            }
            catch (Newtonsoft.Json.JsonException jEx)
            {
                await (this.ShowMessageAsync("error", jEx.Message, MessageDialogStyle.Affirmative, new MetroDialogSettings()
                { AnimateShow = true, AnimateHide = true }));
            }
            catch (HttpRequestException ex)
            {
                await (this.ShowMessageAsync("error", ex.Message, MessageDialogStyle.Affirmative, new MetroDialogSettings()
                { AnimateShow = true, AnimateHide = true }));
            }
        }

        private async void BtnUpdate_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                var todoItem = new TodoItem()
                {
                    Id = Int32.Parse(TxtId.Text),
                    Title = TxtTitle.Text,
                    TodoDate = ((DateTime)DtpTodoDate.SelectedDateTime).ToString("yyyy-MM-dd HH:mm:ss"),
                    IsComplete = Int32.Parse((CboIsComplete.SelectedItem as DivCode).Value)
                };
                //Update할때는 Put
                var response = await client.PutAsJsonAsync($"api/TodoItems/{todoItem.Id}", todoItem);
                response.EnsureSuccessStatusCode();

                GetData();

                TxtId.Text = TxtTitle.Text = string.Empty;
                CboIsComplete.SelectedIndex = -1;
            }
            catch (Newtonsoft.Json.JsonException jEx)
            {
                await(this.ShowMessageAsync("error", jEx.Message, MessageDialogStyle.Affirmative, new MetroDialogSettings()
                { AnimateShow = true, AnimateHide = true }));
            }
            catch (HttpRequestException ex)
            {
                await(this.ShowMessageAsync("error", ex.Message, MessageDialogStyle.Affirmative, new MetroDialogSettings()
                { AnimateShow = true, AnimateHide = true }));
            }
        }

        private async void BtnDelete_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                var Id = Int32.Parse(TxtId.Text);

                //Update할때는 Put
                var response = await client.DeleteAsync($"api/TodoItems/{Id}");
                response.EnsureSuccessStatusCode();

                GetData();

                TxtId.Text = TxtTitle.Text = string.Empty;
                CboIsComplete.SelectedIndex = -1;
            }
            catch (Newtonsoft.Json.JsonException jEx)
            {
                await(this.ShowMessageAsync("error", jEx.Message, MessageDialogStyle.Affirmative, new MetroDialogSettings()
                { AnimateShow = true, AnimateHide = true }));
            }
            catch (HttpRequestException ex)
            {
                await(this.ShowMessageAsync("error", ex.Message, MessageDialogStyle.Affirmative, new MetroDialogSettings()
                { AnimateShow = true, AnimateHide = true }));
            }
        }

        private async void GrdTodoItems_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            try
            {
                var Id = ((TodoItem)GrdTodoItems.SelectedItem).Id;
                HttpResponseMessage? response = await client.GetAsync($"api/TodoItems/{Id}");
                response.EnsureSuccessStatusCode();

                var item = await response.Content.ReadAsAsync<TodoItem>();
                TxtId.Text = item.Id.ToString();
                TxtTitle.Text = item.Title;
                DtpTodoDate.SelectedDateTime = DateTime.Parse(item.TodoDate);
                //1인 경우에는 0번을 인덱스를 할당 즉 True이면 콤보박스의 0번째(True)를 할당 , 그 외는 1번(False)
                CboIsComplete.SelectedIndex = item.IsComplete == 1 ? 0 : 1;
            }
            catch (Newtonsoft.Json.JsonException jEx)
            {
                await(this.ShowMessageAsync("error", jEx.Message, MessageDialogStyle.Affirmative, new MetroDialogSettings()
                { AnimateShow = true, AnimateHide = true }));
            }
            catch (HttpRequestException ex)
            {
                await(this.ShowMessageAsync("error", ex.Message, MessageDialogStyle.Affirmative, new MetroDialogSettings()
                { AnimateShow = true, AnimateHide = true }));
            }
            catch(Exception ex)
            {
                //아래 비동기 메시지 주석은 화면에 출력하지 않기 위해 Debug.WriteLine으로 뺀것
                //await(this.ShowMessageAsync("error", ex.Message, MessageDialogStyle.Affirmative, new MetroDialogSettings()
                //{ AnimateShow = true, AnimateHide = true }));
                Debug.WriteLine($"이외 예외 {ex.Message}");
            }
        }
    }
}

실행화면

0개의 댓글