首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

DinnerNow 架構實戰(2):ASP.NET AJAX Extensions 打造無縫點餐體驗——從搜尋到購物車的完整前後端互動流程

     編輯:關於.NET

業務流程時序圖概覽

用戶操作 → AJAX 呼叫 → WCF 服務 → LINQ 查詢 → 回傳 JSON → 前端動態渲染,全程無整頁重新整理。

點餐流程時序圖

搜尋結果顯示:AJAX 回調渲染餐廳列表

SearchBar.ascx 中的搜尋按鈕點擊處理:

function searchButton_Click() {
    var params = { PostalCode, MenuType, RestaurantCategory, DeadLine };
    if (!isInSearchPage) {
        window.location.href = "search.aspx?" + $.param(params); // 首次搜尋導向結果頁
    } else {
        var svc = new DinnerNow.Services.IMenuSearchService();
        svc.FindRestaurant(params.PostalCode, params.MenuType, params.RestaurantCategory, params.DeadLine,
            onRestaurantSeachSuccess, onRestaurantSeachFailed, null);
    }
}

function onRestaurantSeachSuccess(result) {
    var container = document.getElementById("restaurantList");
    container.innerHTML = "";
    result.forEach(function(r) {
        var html = `<a href="javascript:restaurantSelection_Click('${r.RestaurantId}', '${r.LogoImageLocation}', '${r.Name}')">`
                 + `<img src="${r.LogoImageLocation}" alt="${r.Name}" width="154" height="90" /></a>`;
        var span = document.createElement("span");
        span.innerHTML = html;
        container.appendChild(span);
    });
    DisplayDiv("SearchResultsDivision");
}

餐廳選擇:載入菜單與分類

function restaurantSelection_Click(id, logo, name) {
    // 更新餐廳資訊區
    document.getElementById("restaurantImage").src = logo;
    document.getElementById("restaurantName").innerHTML = name;
    document.getElementById("restaurantID").innerHTML = id;

    var svc = new DinnerNow.Services.IMenuSearchService();
    var menuType = return_MenuType();
    svc.GetMenuItemsForMenu(id, menuType, restaurantSelection_onSuccess, restaurantSelection_onFailed, null);
    svc.GetMenuTypes(getMenuTypes_onSuccess, getMenuTypes_onFailed, null);
}

菜單項目渲染:動態生成含「加入購物車」按鈕的 HTML

function restaurantSelection_onSuccess(result) {
    var container = document.getElementById("menuList");
    container.innerHTML = "";
    result.forEach(function(item, i) {
        var html = `<table class='thinblueline'><tr>`
            + `<td><img src="${item.ImageLocation}" /></td>`
            + `<td><strong>${item.Name}</strong><br>${item.Description}<br>`
            + `預計 ${item.PreparationTime} 分鐘</td>`
            + `<td><strong>$${item.Price}</strong><br>`
            + `<a href="javascript:AddItemToShoppingCart(...)"><img src="images/selectbutton.gif" /></a></td>`
            + `</tr></table>`;
        var span = document.createElement("span");
        span.innerHTML = html;
        container.appendChild(span);
    });
    DisplayDiv("MenuDivision");
}

加入購物車:客戶端建構 DTO → AJAX 呼叫 ShoppingCartService

function AddItemToShoppingCart(description, imageLocation, menuId, menuItemId, name, prepTime, price) {
    var menuItem = new DinnerNow.Business.Data.RestaurantMenuItem();
    menuItem.Description = description; menuItem.ImageLocation = imageLocation;
    menuItem.MenuId = menuId; menuItem.MenuItemId = menuItemId;
    menuItem.Name = name; menuItem.PreparationTime = prepTime; menuItem.Price = price;

    var restaurant = new DinnerNow.Business.Data.RestaurantHeader();
    restaurant.RestaurantId = document.getElementById("restaurantID").innerHTML;
    restaurant.Name = document.getElementById("restaurantName").innerHTML;
    restaurant.LogoImageLocation = document.getElementById("restaurantImage").src;

    DinnerNow.ShoppingCartService.AddItem(menuItem, restaurant, menuSort,
        addItemToShoppingCart_onSuccess, addItemToShoppingCart_onFailed, null);
}

ShoppingCartService:WebUX 端本地服務(非 WCF 遠端)

DinnerNow.WebUX\Code\ShoppingCartService.cs 以 [OperationContract] 暴露給 AJAX:

[OperationContract]
public List<ShoppingCartItem> AddItem(RestaurantMenuItem selectedItem, RestaurantHeader restaurant, int selectedSortOption) {
    var cartItem = new ShoppingCartItem {
        DeliveryTime = selectedItem.PreparationTime,
        MenuItemIdentifier = selectedItem.MenuItemId.ToString(),
        MenuItemName = selectedItem.Name,
        PreparationTime = selectedItem.PreparationTime,
        Price = selectedItem.Price,
        Quantity = 1,
        RestaurantIdentifier = restaurant.RestaurantId.ToString(),
        RestaurantImageLocation = restaurant.LogoImageLocation,
        RestaurantName = restaurant.Name,
        RestaurantItem = selectedItem,
        Restaurant = restaurant
    };
    shoppingCart.AddItem(cartItem); // Session/記憶體購物車邏輯
    return RefreshItems(selectedSortOption);
}

購物車重繪:彙總金額、數量、ETA

function _refreshShoppingCart(result) {
    var container = document.getElementById("shoppingCartList");
    container.innerHTML = "";
    // 按餐廳分組渲染,含數量輸入框、刪除按鈕、小計
    result.forEach(function(item) {
        // ... 生成複雜 HTML 表格結構 ...
    });
    // 非同步取得總計
    DinnerNow.ShoppingCartService.Totals(getTotals_onSuccess, getTotals_onFailed, null);
}

ASP.NET AJAX Extensions 關鍵優勢

  • Proxy 類別自動生成:ScriptManager 註冊 <asp:ServiceReference Path="~/service/MenuSearch.svc/ajax" />,自動產生 JS Proxy(DinnerNow.Services.IMenuSearchService),呼叫語法如 C# 般強型別。
  • JSON 序列化透明化:複雜 DTO(RestaurantMenuItem, RestaurantHeader)自動雙向序列化,無需手寫 JSON.parse/stringify。
  • 成功/失敗回調模式:統一 onSuccess(result)/onFailed(error) 簽章,錯誤處理集中化。
  • UpdatePanel 整合:局部更新無需手寫 DOM 操作(本案例採用手工 DOM 以示細粒度控制)。

架構亮點:前端狀態管理

購物車狀態維持在 ShoppingCartService(WebUX 專案)的 Session/靜態集合中,而非資料庫。這適合「瀏覽-選購」臨時狀態,下單時才持久化至後端訂單系統。分離關注點:前端服務負責 UI 狀態,後端 WCF 負責業務查詢。

總結

DinnerNow 點餐流程展示了 ASP.NET AJAX Extensions 如何構建類桌面應用的 Web 體驗:JS Proxy 呼叫 WCF 服務查詢資料 → 客戶端組裝 DTO 呼叫本地購物車服務 → 回調渲染動態 HTML。這種「厚客戶端、薄伺服器端點」模式,將渲染邏輯前移,大幅降低伺服器壓力與頻寬佔用,同時保持代碼結構清晰、可維護。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved