iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 8
1
Modern Web

一袋.NET要扛幾樓?打造容器化的ASP.NET Core網站!系列 第 8

[Day 8] 建立商品列表的頁面 - 1

本篇同步發文在個人Blog: 一袋.NET要扛幾樓?打造容器化的ASP.NET Core網站!系列文章 - (8) 建立商品列表的頁面 - 1

前幾篇文章已完成商品列表的Web Api,這篇開始建立網頁介面,串接商品的Web Api並呈現商品列表。

1. 建立Web網頁專案

開啟VS,在RPGShop方案的src新增Presentation的方案資料夾,並在Presentation資料夾加入新的ASP.NET Core專案,專案名稱為WebMvc,選擇專案類型Web應用程式(模型-檢視-控制器),先不要用任何HTTPS、Docker與驗證,如圖1。

圖1

按下建立,會產生預設的HomeController和Model、View,如圖2。

圖2

2. 新增HttpClient與商品服務Api互動的基礎模組

在WebMvc專案新增資料夾Infrastructure,會將一些HttpClient的抽象與實作,以及定義與商品服務Api的Url Pattern,建立在這個資料夾內。

2.1 新增介面: IHttpClient

定義常用的Http Get/Post/Put/Delete的非同步函式:

    using System.Net.Http;
    using System.Threading.Tasks;
    
    namespace WebMvc.Infrastructure
    {
        public interface IHttpClient
        {
            Task<string> GetStringAsync(string uri);
            Task<HttpResponseMessage> PostAsync<T>(string uri, T item);
            Task<HttpResponseMessage> DeleteAsync(string uri);
            Task<HttpResponseMessage> PutAsync<T>(string uri, T item);
        }
    }

2.2 新增IHttpClient的實作: CustomHttpClient

  建立一個CustomHttpClient類別並實作IHttpClient,會從Constructor注入System.Net.Http的HttpClient和logger。

  其中Post和Put的方法有大部分共通的寫法,於是可以寫成共同的函式DoPostPutAsync,而要放在Body的資料,使用Newtonsoft.Json序列化成Json。

    using Microsoft.Extensions.Logging;
    using Newtonsoft.Json;
    using System;
    using System.Net.Http;
    using System.Threading.Tasks;
    
    namespace WebMvc.Infrastructure
    {
        public class CustomHttpClient : IHttpClient
        {
            private HttpClient _client;
            private ILogger<CustomHttpClient> _logger;
    
            public CustomHttpClient(HttpClient client, ILogger<CustomHttpClient> logger)
            {
                _client = client;
                _logger = logger;
            }
    
            public async Task<HttpResponseMessage> DeleteAsync(string uri)
            {
                var requestMessage = new HttpRequestMessage(HttpMethod.Delete, uri);
     
                return await _client.SendAsync(requestMessage);
            }
    
            public async Task<string> GetStringAsync(string uri)
            {
                var requestMessage = new HttpRequestMessage(HttpMethod.Get, uri);
                var response = await _client.SendAsync(requestMessage);
                return await response.Content.ReadAsStringAsync();
            }
    
            public async Task<HttpResponseMessage> PostAsync<T>(string uri, T item)
            {
                return await DoPostPutAsync(HttpMethod.Post, uri, item);
            }
    
            public async Task<HttpResponseMessage> PutAsync<T>(string uri, T item)
            {
                return await DoPostPutAsync(HttpMethod.Put, uri, item);
            }
    
            private async Task<HttpResponseMessage> DoPostPutAsync<T>(HttpMethod method, string uri, T item)
            {
                if (method != HttpMethod.Post && method != HttpMethod.Put)
                {
                    throw new ArgumentException("Value must be either post or put.", nameof(method));
                }
    
                var requestMessage = new HttpRequestMessage(method, uri)
                {
                    Content = new StringContent(JsonConvert.SerializeObject(item), System.Text.Encoding.UTF8, "application/json")
                };
    
                var response = await _client.SendAsync(requestMessage);
    
                if (response.StatusCode == System.Net.HttpStatusCode.InternalServerError)
                {
                    throw new HttpRequestException();
                }
    
                return response;
            }
        }
    }

2.3 新增ApiPaths類別

  所有跟Api互動的Url Pattern,都在此類別規範,而我們這商品列表的頁面需要

  1. 商品類型列表
  2. 商品分頁列表
    namespace WebMvc.Infrastructure
    {
        public static class ApiPaths
        { 
            public static class Catalog
            {
                public static string GetAllCatalogItems(string baseUri, int pageIndex, int pageSize, int? type)
                {
                    string typeQueryString = "";
                    if (type.HasValue)
                    {
                        typeQueryString = type.Value.ToString();
                    }
    
                    return $"{baseUri}items?catalogTypeId={typeQueryString}&pageIndex={pageIndex}&pageSize={pageSize}";
                }
    
                public static string GetAllTypes(string baseUri)
                {
                    return $"{baseUri}catalogTypes";
                }
            }
        }
    }

  下一篇將寫從Api互動的Service與網頁呈現的內容


上一篇
[Day 7] 建立商品服務的Api - 5
下一篇
[Day 9] 建立商品列表的頁面 - 2
系列文
一袋.NET要扛幾樓?打造容器化的ASP.NET Core網站!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言