P/PromptTools
Instruction asset / webservice-instructions

WebService.instructions.md

從 Google Drive .github/instructions/WebService.instructions.md 匯入

共用指令內容

使用中

---

applyTo: '**/*'

---

WebService (ASMX) 開發規範

1. 檔案結構 (File Structure)

  • 標記檔案 (.asmx):

- 位置: 應放置於專案根目錄下的 WS/ 資料夾 (例如: /WS/UserWS.asmx)。

- 內容: 只能包含一行 @ WebService 指示詞,用於連結後置程式碼。

  • 程式碼後置檔案 (.cs):

- 位置: 必須放置於 /App_Code/WS/ 資料夾 (例如: /App_Code/WS/UserWS.cs)。

- 內容: 包含 WebService 類別的完整 C# 實作。

2. 核心規則

  • CodeBehind 路徑: .asmx 檔案中的 CodeBehind 屬性必須正確指向 App_Code/WS/ 中的對應 .cs 檔案 (例如 ~/App_Code/WS/UserWS.cs)。
  • Class 名稱: Class 屬性必須.cs 檔案中的類別名稱完全相符。
  • 職責: WebService 作為 API 的進入點,其職責是接收前端請求、呼叫 BLL 處理業務邏輯,並將結果回傳。
  • 無業務邏輯: WebService 不應包含任何業務邏輯,所有邏輯都應封裝在 BLL 層。

3. 程式碼範例

範例 A:標記檔案 (/WS/UserWS.asmx)


<%@ WebService Language="C#" CodeBehind="~/App_Code/WS/UserWS.cs" Class="UserWS" %>

範例 B:程式碼後置檔案 (/App_Code/WS/UserWS.cs)




using System.Collections.Generic;

using System.Web.Services;



[WebService(Namespace = "[http://tempuri.org/](http://tempuri.org/)")]

[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]

[System.Web.Script.Services.ScriptService]

public class UserWS : WebService

{

    [WebMethod(Description = "取得所有使用者")]

    public List<DtoUser> GetAllUsers()

    {

        BizUser _bizUser = new BizUser();

        return _bizUser.GetAllUsers();

    }

}

---

4. ⚠️ EnableSession 強制規範

> 教訓來源:2026-04 實際踩坑

> 未加 EnableSession = true 時,Session 屬性回傳 null,導致 BaseWebService.CurrEmpInfo 拋出 NullReferenceException,整支 WebMethod 失效。

4.1 規則

所有存取 Session(包括透過 BaseWebServiceUseright / UserightAlternative / CurrEmpInfo 屬性)的 [WebMethod]必須明確加上 EnableSession = true


// ✅ 正確

[WebMethod(Description = "儲存資料", EnableSession = true)]

public String SaveData(...)



// ❌ 錯誤:遺漏 EnableSession,Session == null → NullReferenceException

[WebMethod(Description = "儲存資料")]

public String SaveData(...)

4.2 完整 WebMethod 範本


[WebMethod(Description = "儲存 XXX 資料", EnableSession = true)]

public String SaveXxx(Decimal id, String name, Int32 isActive)

{

    try

    {

        // ✅ Useright 檢查必須在 try 區塊內,且為第一行

        if (!Useright) return JsonConvert.SerializeObject(new { success = false, message = "無權限" });



        DtoXxx dto = new DtoXxx

        {

            Id       = id,

            Name     = name     ?? String.Empty,

            IsActive = isActive,

            DataOp   = CurrEmpInfo != null ? CurrEmpInfo.EmpID : String.Empty

        };



        BizXxx biz = new BizXxx();

        Boolean ok = biz.Save(dto);

        return JsonConvert.SerializeObject(new { success = ok });

    }

    catch (Exception ex)

    {

        CHMC.Log.WriteLog(ex);

        return JsonConvert.SerializeObject(new { success = false, message = "系統發生錯誤,請稍後再試" });

    }

}

---

5. ⚠️ Useright 實作規範

> 教訓來源:2026-04 實際踩坑

> Useright 原先呼叫 BizPermission.IsQuery(EmpID, "/Index.aspx"),查詢 PMS 資料庫中的 APUrl

> 但若該 URL 未在 PMS 系統中登錄,IsQuery 永遠回傳 false → 所有 WebMethod 都回傳「無權限」。

5.1 規則

WS 層的 Useright 只驗證「Session 內有有效員工資訊」,不呼叫 BizPermission.IsQuery()

原因:

1. BizPermission.IsQuery() 依賴 PMS 資料庫中登錄的 APUrl 紀錄,容易因設定不一致造成永遠 false

2. 頁面層級的細部權限已由 BasePage.CheckAuthorization 把關

3. 進入後台頁面本身就已完成 SSO 驗證,WebMethod 只需確認 Session 合法即可

5.2 正確的 BaseWebService.Useright 實作


// ✅ BaseWebService.cs 中正確的 Useright 實作

protected Boolean Useright

{

    get

    {

        // 只驗證登入狀態,不查 PMS 資料庫

        return (CurrEmpInfo != null && !String.IsNullOrEmpty(CurrEmpInfo.EmpID));

    }

}

5.3 Useright 必須在 try 區塊內


// ✅ 正確:Useright 在 try 內,避免 BizPermission 例外逸出

public String SaveXxx(...)

{

    try

    {

        if (!Useright) return JsonConvert.SerializeObject(new { success = false, message = "無權限" });

        // ... 業務邏輯

    }

    catch (Exception ex) { ... }

}



// ❌ 錯誤:Useright 在 try 外,任何例外都會變成未捕獲例外

public String SaveXxx(...)

{

    if (!Useright) return JsonConvert.SerializeObject(new { success = false, message = "無權限" });

    try { ... }

    catch (Exception ex) { ... }

}

版本紀錄

1 個不可變版本
v1
從 Google Drive 初次匯入
2026/07/28 02:59:54