DinnerNow.WebUX:UI 邏輯、WCF Client Proxy、AJAX 頁面DinnerNow.Web:基礎變數定義Microsoft.DPE.Samples.CardSpace:CardSpace 整合DinnerNow.ServiceHost:WCF 服務裝載站點DinnerNow.Services:服務契約與實作(IMenuSearchService, MenuSearchService)DinnerNow.Business:業務邏輯與 LINQ to SQL 資料存取SearchBar.ascx 使用 ObjectDataSource 綁定兩個下拉選單:
<asp:ObjectDataSource ID="RestaurantCategoryDataSource" TypeName="DinnerNow.RestaurantCategoryDataSource" SelectMethod="SelectAll" />
<asp:DropDownList DataSourceID="RestaurantCategoryDataSource" DataTextField="Description" DataValueField="RestaurantId" />
<asp:ObjectDataSource ID="MenuTypeDataSource" TypeName="DinnerNow.MenuTypeDataSource" SelectMethod="SelectAll" />
<asp:DropDownList DataSourceID="MenuTypeDataSource" DataTextField="MenuTypeName" DataValueField="MenuTypeName" />
// DinnerNow.WebUX\Code\DataSources\MenuTypeDataSource.cs
public IEnumerable<RestaurantCategory> SelectAll() {
try {
using (var client = new MenuSearchServiceClient("WSHttpBinding_IMenuSearchService")) {
return client.GetRestaurantCategories();
}
} catch { return null; }
}
<endpoint address="https://localhost/DinnerNow/service/MenuSearch.svc"
binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IMenuSearchService"
contract="MenuSearchService.IMenuSearchService"
name="WSHttpBinding_IMenuSearchService">
<identity><servicePrincipalName value="host" /></identity>
</endpoint>
ServiceHost 專案 web.config 服務定義:
<service behaviorConfiguration="DinnerNow.Services.MenuSearchServiceBehavior" name="DinnerNow.Services.MenuSearchService">
<endpoint address="" binding="wsHttpBinding" contract="DinnerNow.Services.IMenuSearchService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<endpoint address="ajax" behaviorConfiguration="DinnerNow.Services.MenuSearchServiceAjax" binding="webHttpBinding" bindingConfiguration="AjaxBinding" contract="DinnerNow.Services.IMenuSearchService" />
</service>
服務契約:
[ServiceContract(Namespace = "DinnerNow.Services")]
public interface IMenuSearchService {
[OperationContract][WebGet] IEnumerable<MenuType> GetMenuTypes();
[OperationContract][WebGet] IEnumerable<RestaurantCategory> GetRestaurantCategories();
[OperationContract][WebGet] IEnumerable<RestaurantHeader> FindRestaurant(string postalCode, string menuType, string restaurantCategoryId, string deadline);
[OperationContract][WebGet] IEnumerable<RestaurantMenuItem> GetMenuItemsForMenu(string restaurantId, string menuType);
}
服務實作:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class MenuSearchService : IMenuSearchService {
public IEnumerable<Business.Data.MenuType> GetMenuTypes() {
return new DinnerNow.Business.Menu().GetMenuTypes();
}
public IEnumerable<Business.Data.RestaurantCategory> GetRestaurantCategories() {
return new DinnerNow.Business.Menu().GetRestaurantCategories();
}
public IEnumerable<Business.Data.RestaurantHeader> FindRestaurant(string postalCode, string menuType, string restaurantCategoryId, string deadline) {
return new DinnerNow.Business.Menu().FindRestaurant(postalCode, menuType, new Guid(restaurantCategoryId), int.Parse(deadline));
}
public IEnumerable<Business.Data.RestaurantMenuItem> GetMenuItemsForMenu(string restaurantId, string menuType) {
return new DinnerNow.Business.Menu().GetMenuItemsForMenu(new Guid(restaurantId), menuType);
}
}
// DinnerNow.Business\Menu.cs
public IEnumerable<Business.Data.MenuType> GetMenuTypes() {
var q = from m in db.Menus
select new Business.Data.MenuType { MenuTypeName = m.MenuType.Trim() };
return q.Distinct().ToList();
}
public IEnumerable<Business.Data.RestaurantCategory> GetRestaurantCategories() {
// 類似查詢餐廳分類
}
生成 SQL:SELECT DISTINCT LTRIM(RTRIM(MenuType)) FROM Menu
| 層級 | 專案 | 職責 | 技術 |
|---|---|---|---|
| 資料存取 | DinnerNow.Business | LINQ to SQL 查詢、實體映射 | LINQ to SQL |
| 業務邏輯 | DinnerNow.Services | 服務實作、DTO 轉換 | WCF |
| 服務裝載 | DinnerNow.ServiceHost | 端點、綁定、行為配置 | WCF 配置 |
| 表現層 | DinnerNow.WebUX | UI 綁定、AJAX 呼叫、WCF Client | ASP.NET AJAX, WCF Client |
清晰分離關注點:資料存取可獨立單元測試、服務可多端點暴露(WS-HTTP、AJAX/JSON)、前端專注體驗優化。
DinnerNow 首頁資料載入展示了經典的「AJAX → WCF → LINQ to SQL」三層呼叫鏈。ObjectDataSource 綁定 DataSource 類別,透過 WCF Client Proxy 呼叫服務,服務委派給 Business 層 LINQ 查詢。這種架構支援團隊平行開發:DBA 優化 SQL、後端實作服務契約、前端設計互動體驗。