DinnerNow中的ASP.NET Ajax Extensions應用---選餐流程

  繼上一篇文章DinnerNow中的WCF應用 --- 首頁數據加載,咱們大概瞭解了一些關於DinnerNow的基本項目結構,以及其中比較主要的兩個解決方案文件。接下來我會繼續以實際網上選餐流程來講明關於DinnerNow中的ASP.NET Ajax Extensions應用場景及其設計方案。javascript

  首先請你們看一下這張圖,它標明瞭在訂餐這一業務流程中"查詢餐館"這一用例 DinnerNow所實際執行的方法順序,由於下文中的一些主要的js方法調用也是以這張圖中所標明的流程來順序處理的.
html



  固然咱們還要再次用VS2008打開上文中所說的兩個解決方案文件:
    安裝目錄下\solution\DinnerNow - Web\DinnerNow - Web.sln
              \solution\DinnerNow - ServicePortfolio2\DinnerNow - ServicePortfolio2.sln
java

   不過這一回要說的重點內容集中在了DinnerNow - Web.sln下的DinnerNow.WebUX項目中.ajax

  請看一下search.aspx頁面的運行效果圖:
  

     上圖中的數據請求在上一篇文章中已說過,就是:
service.FindRestaurant(PARAMETERS.map.PostalCode,
PARAMETERS.map.MenuType,
PARAMETERS.map.RestaurantCategory,
PARAMETERS.map.DeadLine,
onRestaurantSeachSuccess, //當操做請求成功後的回調方法
onRestaurantSeachFailed, null);
       
上面的回調方法的內容以下:
    服務器

function onRestaurantSeachSuccess(searchResult)  // searchResult爲請求返回的數據 
{
    var restaurantContainer 
=  document.getElementById( " restaurantList " );
    restaurantContainer.innerHTML 
=   "" ;
    
    
for  (var i = 0 ; i < searchResult.length; i ++ )  // 綁定數據並進行顯示
    {
        var restaurantHtml
=   " <a href=\ " javascript:restaurantSelection_Click( ' "
                 +  searchResult[i].RestaurantId  +   " ', ' "
                
+  searchResult[i].LogoImageLocation  + " ', ' "
                
+  searchResult[i].Name  + " ');\ " >< img src = \ ""
                
+  searchResult[i].LogoImageLocation  +   " \ "  alt = \ ""
                
+  searchResult[i].Name  +   " \ "  width = \ " 154\ "  height = \ " 90\ "   class = \ " thingreenline\ "   /></ a > " ;
        var restaurantElement = document.createElement( " span " );
        restaurantElement.innerHTML 
=  restaurantHtml;
        
        restaurantContainer.appendChild(restaurantElement);
    }
    
   DisplayDiv(
" SearchResultsDivision " );
}

  經過這個方法的調用實現了上面圖中的顯示效果,當咱們單擊了其中某個餐館的圖標以後.
會顯示下面的頁面:

   

       而單擊事件的執行方法以下:
架構

function  restaurantSelection_Click(identifier, logo, name)
{
    
/* ********* RestaurantSelected ********** */ 生成餐館的信息,如LOGO,餐館名稱,說明等
    document.getElementById(
" restaurantImage " ).src  =  logo;
    document.getElementById(
" restaurantName " ).innerHTML  =  name;
 
    document.getElementById(
" restaurantDescription " ).innerHTML  =   " Since 1923, the offering fas, friendly and courteous service.  We use only the best ingredients and maintain a skilled staff to answer your questions.  We have built our reputation on our commitment to providing quality service, which has earned us many valuable customers. " ;
   
    document.getElementById(
" restaurantMenuFeed " ).href  =   " service/syndication.svc/rss/restaurants/ " +  name;
   
    
var  restaurant  =  document.getElementById( " restaurantID " );
    restaurant.innerHTML 
=  identifier;
    
/* ********* RestaurantSelected ********** */
    
    
var  service  =   new  DinnerNow.Services.IMenuSearchService(); // 加載菜單列表
     var  menuType  =  return_MenuType();
    
var  selectedMenuType  =  document.getElementById( " selectedMenuItemCategory " );
    selectedMenuType.value 
=  menuType;
    service.GetMenuItemsForMenu(identifier,menuType,restaurantSelection_onSuccess,restaurantSelection_onFailed,
null ); // 請求並加載菜單列表
    service.GetMenuTypes(getMenuTypes_onSuccess, getMenuTypes_onFailed,  null ); // 加載菜單類型(上圖中的屬性頁:Breakfast,Dinner,Lunch)
}


      其中的GetMenuItemsForMenu,GetMenuTypes方法最終會去調用MenuSearchService類中的同名方法(MenuSearchService.cs文件在DinnerNow.ServicesDinnerNow - ServicePortfolio2.sln解決方案),因此這裏咱們還要再切換到ServicePortfolio2.sln下,找到位於DinnerNow.Services項目下的MenuSearchService.cs文件。其中的GetMenuItemsForMenu方法定義以下:app

  public  IEnumerable < DinnerNow.Business.Data.RestaurantMenuItem >  GetMenuItemsForMenu( string  restaurantId,  string  menuType)
 {
     Business.Menu menu 
=   new  DinnerNow.Business.Menu();
     
return  menu.GetMenuItemsForMenu( new  Guid(restaurantId), menuType); // 獲取指定類型的菜單數據
 }

      代碼段中的menu.GetMenuItemsForMenu方法定義如:   ide

public  IEnumerable < DinnerNow.Business.Data.RestaurantMenuItem >  GetMenuItemsForMenu(Guid restaurantId,  string  menuType)
{
    var results 
=  from mi  in  db.MenuItems
                  join m 
in  db.Menus on mi.MenuId equals m.MenuId
                  
where  m.RestaurantId  ==  restaurantId
                  
&&  m.MenuType  ==  menuType
                  select 
new  Business.Data.RestaurantMenuItem()
                  {
                      Description 
=  mi.Description,
                      ImageLocation 
=  mi.ImageLocation,
                      MenuId 
=  mi.MenuId,
                      MenuItemId 
=  mi.MenuItemId,
                      Name 
=  mi.Name,
                      PreparationTime 
=  mi.PreparationTime,
                      Price 
=  mi.Price
                  };
    
return  results.ToList();
}

  上面的LINQ查詢至關於下面的SQL腳本:ui

SELECT   [ t0 ] . [ MenuItemId ] [ t0 ] . [ MenuId ] [ t0 ] . [ Name ] [ t0 ] . [ Description ] [ t0 ] . [ ImageLocation ] [ t0 ] . [ Price ] [ t0 ] . [ PreparationTime ]
FROM   [ dbo ] . [ MenuItem ]   AS   [ t0 ]
INNER   JOIN   [ dbo ] . [ Menu ]   AS   [ t1 ]   ON   [ t0 ] . [ MenuId ]   =   [ t1 ] . [ MenuId ]
WHERE  ( [ t1 ] . [ RestaurantId ]   =   @p0 AND  ( [ t1 ] . [ MenuType ]   =   @p1 )

  而前面所說的GetMenuTypes方法你們也能夠找到它最終要去訪問的LINQ代碼以下:this

public  IEnumerable < DinnerNow.Business.Data.MenuType >  GetMenuTypes()
{
      var s 
=  (from m  in  db.Menus
              select 
new  DinnerNow.Business.Data.MenuType()
              {
                  MenuTypeName 
=  m.MenuType.Trim() 
              }).Distinct();
      
return  s.ToList();
}

     這裏由於代碼很簡單,就很少說了.

  經過這個業務流程能夠看出DinnerNow基本架構思想:
ajax 請求數據 ---> wcf 服務配置  ---> linq 數據訪問

      這樣架構讓整個軟件的架構,流程及開發層次很是清楚。另外由於使用了 Ajax Extensions,使得開發和閱讀JS代碼感受就像是在寫C#代碼,使得軟件的可讀性和可維護性上也有很好提高和擴展空間.另外就是在UE上也使在咱們能夠在一個頁面上完成挑選餐館,選擇食物並進行訂餐的整個流程(接下來將會依次說明).避免了頻繁提交頁面請求而致使的操做繁鎖和服務器訪問超時問題,以及用戶等待時間過長(體驗差)和其它易於出錯的問題.


  下面接着上面的JS代碼中的GetMenuItemsForMenu請求的回調方法restaurantSelection_onSuccess來繼續咱們的操做流程:          

  // 綁定菜單列表數據並進行顯示
function  restaurantSelection_onSuccess(result)
{
    
var  menuItemContainer  =  document.getElementById( " menuList " );
    menuItemContainer.innerHTML 
=   "" ;

    
/* ******* MenuItems ********* */             
    
for  ( var  i = 0 ; i < result.length; i ++ )
    {
        
var  menuItem  =  result[i];
        
        
var  menuItemHtml  =   " <table width='100%' border='0' align='center' cellpadding='8' cellspacing='0' class='thinblueline'><tr><td width='150' align='center' valign='top'><div class='hoverarea'><div><a href=\ ""
                + menuItem.ImageLocation + 
" \ "  target='_blank'> <img id=\ " MenuItemImage\ "  src=\ ""
                + menuItem.ImageLocation + 
" \ "  alt=\ ""
                + menuItem.Name +
" \ " /><img id=\ " Img1\ "  src=\ ""
                + menuItem.ImageLocation+ 
" \ "  alt=\ ""
                + menuItem.Name+
" \ "  class=\ " hoverp_w_picpath_preview\ " /></a></div></div></td><td valign='top'><strong>Item #  "
                
+  i  +   " </strong><br/><strong> "
                
+  menuItem.Name + " </strong><br/> "
                
+  menuItem.Description + " <br/><br/><div align='left'><strong>Estimated Delivery Time:  "
                
+  menuItem.PreparationTime + "  minutes</strong></div></td><td width='80' align='right' valign='top'><strong>$ "
                
+  menuItem.Price + " </strong><br/><br/><a class=\ " noUnderline\ "  href=\ " javascript:AddItemToShoppingCart( ' "
                + menuItem.Description + "
' ' "
                + menuItem.ImageLocation + "
' ' "
                + menuItem.MenuId + "
' ' "
                + menuItem.MenuItemId + "
' ' "
                + menuItem.Name + "
' ' "
                + menuItem.PreparationTime + "
' ' "
                + menuItem.Price + "
' );\ " ><img src=\ " p_w_picpaths / selectbutton.gif\" border=\"0\"  / >< / a>< / td >< / tr>< / table > " ;
                
        var menuItemElement=document.createElement(
" span " );
        menuItemElement.innerHTML = menuItemHtml;
    
        menuItemContainer.appendChild(menuItemElement);
    }
    /******** MenuItems **********/
    
    DisplayDivContent4(
" shoppingCart " );
    DisplayDiv(
" MenuDivision " );
}

  看到這裏,咱們在回到頁面上看一下當咱們單擊菜單旁邊的"select"按鈕以後所顯示的頁面內容:


  而單擊所執行的JS方法以下(該方法用於將訂餐數據加載到購物車中):   

function  AddItemToShoppingCart(description,p_w_picpathLocation,menuId,menuItemId,name,preparationTime,price)
{
    
var  menuItem  =   new  DinnerNow.Business.Data.RestaurantMenuItem();

    menuItem.Description 
=  description;
    menuItem.ImageLocation 
=  p_w_picpathLocation;
    menuItem.MenuId 
=  menuId;
    menuItem.MenuItemId 
=  menuItemId;
    menuItem.Name 
=  name;
    menuItem.PreparationTime 
=  preparationTime;
    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 );
}

      其中的DinnerNow.ShoppingCartService.AddItem調用會生成以下的ajax請求:

AddItem: function (selectedItem,restaurant,selectedSortOption,succeededCallback, failedCallback, userContext) {
// / <param name="selectedItem" type="DinnerNow.Business.Data.RestaurantMenuItem">DinnerNow.WebUX.MenuSearchService.RestaurantMenuItem</param>
//
/ <param name="restaurant" type="DinnerNow.Business.Data.RestaurantHeader">DinnerNow.WebUX.MenuSearchService.RestaurantHeader</param>
//
/ <param name="selectedSortOption" type="Number">System.Int32</param>
//
/ <param name="succeededCallback" type="Function" optional="true" mayBeNull="true"></param>
//
/ <param name="failedCallback" type="Function" optional="true" mayBeNull="true"></param>
//
/ <param name="userContext" optional="true" mayBeNull="true"></param>
return   this ._invoke( this ._get_path(),  ' AddItem ' , false ,{selectedItem:selectedItem,restaurant:restaurant,selectedSortOption:selectedSortOption},succeededCallback,failedCallback,userContext); }

  而最終ajax請求會成爲對以下方法的調用(DinnerNow.WebUX\Code\ShoppingCartService.cs文件中):

[OperationContract]
public  List < ShoppingCartItem >  AddItem(RestaurantMenuItem selectedItem, RestaurantHeader restaurant,  int  selectedSortOption)
{
    ShoppingCartItem shoppingCartItem 
=   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(shoppingCartItem);

    
return   this .RefreshItems(selectedSortOption);
}


      經過這個方法咱們能夠實現將選定的食物放入購物車,並將購物車中已有商品的類型,價格,數據等信息返回到請求頁面中.並經過下面的JS方法來顯示相應的數據信息.

function  _refreshShoppingCart(result)
{
    
var  shoppingCartContainer  =  document.getElementById( " shoppingCartList " );
    shoppingCartContainer.innerHTML 
=   "" ;
    
    
var  restaurantId  =   "" ;
    
var  firsth  =   true ;
    
    
var  html  =   "" ;

    
/* ******* Shopping Cart Items ********* */
    
for  ( var  i = 0 ; i < result.length; i ++ )
    {
        
var  shoppingCartItem  =  result[i];
        
var  subtotal  =  (shoppingCartItem.Price  *  shoppingCartItem.Quantity); // 商品價格*數量
         var  restaurantItemHtml = "" ;
        
var  endPrevRestaurantItemHtml  = "" ;
        
        
if  (restaurantId  !=  shoppingCartItem.RestaurantIdentifier  &&  menuSort  !=   1 )
        {
            
if  ( ! firsth)
                endPrevRestaurantItemHtml 
=   " </table></td></tr> " ;
            
            firsth 
=   false
            restaurantId 
=  shoppingCartItem.RestaurantIdentifier;
            restaurantItemHtml 
=   " <table width='100%' border='0' align='center' cellpadding='4' cellspacing='4' bgcolor='#5686B4' class='thinblueline'><tr><td align='left' bgcolor='#31465B' class='boldWhite'> "
                    
+  shoppingCartItem.RestaurantName  +   " </td></tr><tr><td> " ;
        }
       
        
var  shoppingCartHtml  =   " <table width='100%' border='0' cellspacing='2' cellpadding='2' bgcolor='#5686B4'><tr><td align='left'><a class='noUnderline' href=\ " javascript:DeleteItemFromShoppingCart( ' "
                + shoppingCartItem.MenuItemIdentifier + "
' );\ " ><img src='p_w_picpaths/delete.gif' alt='Remove item' width='17' height='16'/></a></td><td align='left' width='60%'> "
                
+  shoppingCartItem.MenuItemName  +   " </td><td align='left'><input type='text' id=' "
                
+  shoppingCartItem.MenuItemIdentifier  +   " _itemViewQuantityBox' size='2' class='checkOutFormsField' onchange=\ " updateShoppingCartQuantity( ' "
                + shoppingCartItem.MenuItemIdentifier + "
' );\ "  value =' "
                
+  shoppingCartItem.Quantity  +   " '></input></td><td align='left' nowrap='nowrap' class='bodyTextWhite'> $ "
                
+  subtotal  +   " </td></tr> " ;
         
         html 
+=  endPrevRestaurantItemHtml + restaurantItemHtml + shoppingCartHtml + " </table><br/> " ;
    }
    
/* ******* Shopping Cart Items ********* */

    
if  (html  !=   "" )
        html
+= " </td></tr></table> " ;
        
    
var  shoppingCartElement = document.createElement( " span " );                   
    shoppingCartElement.innerHTML 
=  html;
    
    shoppingCartContainer.appendChild(shoppingCartElement);
    
// ajax調用計算購物車中的Total,ETA信息
    DinnerNow.ShoppingCartService.Totals(getTotals_onSuccess, getTotals_onFailed, null );
}

      能夠看出,整個選購流程仍是有些複雜的,但在操做上卻很流暢,讓人感受不出什麼繁鎖.這其實都要得益於ajax的適當應用.固然微軟的Ajax Extensions無形中也下降了AJAX代碼的開發門檻:)

  在下一篇文章中,咱們將會繼續訂餐流程,不太重點將會轉移動到DinnerNow - ServicePortfolio2.sln解決方案下,而且由於DinnerNow中使用了WWF(Windows Work Flow Foundation), 因此下一篇文章的內容可能會更偏向於WWF。若是你們感興趣的話,敬請留意:)

  好了,今天的文章就先到這裏了,若是你們有什麼問題歡迎與我交流.
          關鍵字:DinnerNow, Ajax Extensions

相關文章
相關標籤/搜索