using Newtonsoft.Json; using System; using System.IO; using System.Net; using System.Text; using System.Threading.Tasks; using 報到系統客戶端.Models; namespace 報到系統客戶端.Services { /// /// API 服務基礎類別 /// 處理 HTTP 請求、Session cookie、錯誤處理 /// public class ApiService { private static ApiService _instance; private static readonly object _lockObject = new object(); private string _baseUrl; private CookieContainer _cookieContainer; // 用於儲存 cookie 的檔案路徑 private string _cookiePath; public static JsonSerializerSettings jsonConvertSettings = new JsonSerializerSettings { DateTimeZoneHandling = DateTimeZoneHandling.Local }; public static object DeserializeObject(string value) { return JsonConvert.DeserializeObject(value, jsonConvertSettings); } public static T DeserializeObject(string value) { return (T)JsonConvert.DeserializeObject(value, typeof(T), jsonConvertSettings); } /// /// 取得單例實例 /// public static ApiService Instance { get { if (_instance == null) { lock (_lockObject) { if (_instance == null) { _instance = new ApiService(); } } } return _instance; } } private ApiService() { // 從設定檔讀取基底 URL _baseUrl = ConfigService.Instance.GetApiBaseUrl(); if (string.IsNullOrWhiteSpace(_baseUrl)) { _baseUrl = "http://localhost:58792"; } // 初始化 Cookie 容器 _cookieContainer = new CookieContainer(); _cookiePath = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "報到系統客戶端", "cookies.txt" ); // 嘗試載入已儲存的 Cookie LoadCookies(); } /// /// 設定基底 URL /// public string BaseUrl { set { _baseUrl = value; } get { return _baseUrl; } } /// /// 執行 POST 請求 /// public async Task PostAsync(string servicePath, string methodName, object parameters) { try { string url = $"{_baseUrl}{servicePath}/{methodName}"; HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.Method = "POST"; request.ContentType = "application/json; charset=utf-8"; request.CookieContainer = _cookieContainer; request.KeepAlive = true; // 序列化參數 string jsonData = JsonConvert.SerializeObject(parameters ?? new { }); // 寫入請求體 byte[] data = Encoding.UTF8.GetBytes(jsonData); request.ContentLength = data.Length; using (Stream requestStream = request.GetRequestStream()) { await requestStream.WriteAsync(data, 0, data.Length); } // 取得回應 using (HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync()) { // 更新 Cookie(用於 Session 管理) _cookieContainer.Add(response.ResponseUri, response.Cookies); SaveCookies(); using (StreamReader reader = new StreamReader(response.GetResponseStream())) { string responseJson = await reader.ReadToEndAsync(); // 解析回應 dynamic result = DeserializeObject(responseJson); // ASP.NET Web Service 會將結果包在 "d" 屬性中 if (result.d != null) { string dataJson = JsonConvert.SerializeObject(result.d); return DeserializeObject(dataJson); } else { return DeserializeObject(responseJson); } } } } catch (WebException ex) { return new BaseResponse { Success = false, Message = $"網路錯誤: {ex.Message}" }; } catch (Exception ex) { return new BaseResponse { Success = false, Message = $"錯誤: {ex.Message}" }; } } /// /// 同步版本的 POST 請求(用於向後相容) /// public BaseResponse Post(string servicePath, string methodName, object parameters) { try { string url = $"{_baseUrl}{servicePath}/{methodName}"; HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.Method = "POST"; request.ContentType = "application/json; charset=utf-8"; request.CookieContainer = _cookieContainer; request.KeepAlive = true; // 序列化參數 string jsonData = JsonConvert.SerializeObject(parameters ?? new { }); // 寫入請求體 byte[] data = Encoding.UTF8.GetBytes(jsonData); request.ContentLength = data.Length; using (Stream requestStream = request.GetRequestStream()) { requestStream.Write(data, 0, data.Length); } // 取得回應 using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { // 更新 Cookie(用於 Session 管理) _cookieContainer.Add(response.ResponseUri, response.Cookies); SaveCookies(); using (StreamReader reader = new StreamReader(response.GetResponseStream())) { string responseJson = reader.ReadToEnd(); // 解析回應 dynamic result = DeserializeObject(responseJson); // ASP.NET Web Service 會將結果包在 "d" 屬性中 if (result.d != null) { string dataJson = JsonConvert.SerializeObject(result.d); return DeserializeObject(dataJson); } else { return DeserializeObject(responseJson); } } } } catch (WebException ex) { return new BaseResponse { Success = false, Message = $"網路錯誤: {ex.Message}" }; } catch (Exception ex) { return new BaseResponse { Success = false, Message = $"錯誤: {ex.Message}" }; } } /// /// 清除所有 Session cookie /// public void ClearSession() { _cookieContainer = new CookieContainer(); DeleteCookies(); } /// /// 儲存 Cookie 到檔案 /// private void SaveCookies() { try { string directory = Path.GetDirectoryName(_cookiePath); if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } using (StreamWriter sw = new StreamWriter(_cookiePath, false, Encoding.UTF8)) { foreach (Cookie cookie in _cookieContainer.GetCookies(new Uri(_baseUrl))) { sw.WriteLine($"{cookie.Name}={cookie.Value}"); } } } catch { // 忽略儲存錯誤 } } /// /// 從檔案載入 Cookie /// private void LoadCookies() { try { if (File.Exists(_cookiePath)) { using (StreamReader sr = new StreamReader(_cookiePath, Encoding.UTF8)) { string line; while ((line = sr.ReadLine()) != null) { if (string.IsNullOrWhiteSpace(line)) continue; string[] parts = line.Split(new[] { '=' }, 2); if (parts.Length == 2) { Cookie cookie = new Cookie(parts[0], parts[1]) { Path = "/", HttpOnly = true }; _cookieContainer.Add(new Uri(_baseUrl), cookie); } } } } } catch { // 忽略載入錯誤 } } /// /// 刪除儲存的 Cookie 檔案 /// private void DeleteCookies() { try { if (File.Exists(_cookiePath)) { File.Delete(_cookiePath); } } catch { // 忽略刪除錯誤 } } } }