• DinnerNow中的ASP.NET Ajax Extensions应用选餐流程


      继上一篇文章DinnerNow中的WCF应用 --- 首页数据加载,我们大概了解了一些关于DinnerNow的基本
    项目结构,以及其中比较主要的两个解决方案文件。

    接下来我会继续以实际网上选餐流程来说明关于DinnerNow中的ASP.NET Ajax Extensions应用场景及
    其设计方案。

      首先请大家看一下这张图,它标明了在订餐这一业务流程中"查询餐馆"这一用例 DinnerNow所实际执行的
    方法顺序,因为下文中的一些主要的js方法调用也是以这张图中所标明的流程来顺序处理的.



      当然我们还要再次用VS2008打开上文中所说的两个解决方案文件:
        安装目录下\solution\DinnerNow - Web\DinnerNow - Web.sln
                  \solution\DinnerNow - ServicePortfolio2\DinnerNow - ServicePortfolio2.sln

       不过这一回要说的重点内容集中在了DinnerNow - Web.sln下的DinnerNow.WebUX项目中.

      请看一下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方法定义如下:

     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方法定义如:   

    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脚本:

    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] = @p0AND ([t1].[MenuType] = @p1)

      而前面所说的GetMenuTypes方法大家也可以找到它最终要去访问的LINQ代码如下:

    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=\"hoverimage_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=\"images/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,imageLocation,menuId,menuItemId,name,preparationTime,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 
    = 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='images/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
       

  • 相关阅读:
    常用正则表达式大全
    js基础的自定义属性练习
    AngularJS中最重要的核心功能
    Architecture.the-reactive-manifesto
    iOS.ReactNative-3-about-viewmanager-uimanager-and-bridgemodule
    iOS.DistributionApp.1-mobile-provision-file[draft]
    iOS.DistributionApp.0-build-adhoc-distribution-for-tester
    iOS.ReactNative-5-make-react-native-to-support-dynamically-update
    OpenSource.organization-in-github
    iOS.Performance-trick-presentViewController-is-so-slow-in-didSelectRowAtIndexPath
  • 原文地址:https://www.cnblogs.com/daizhj/p/1203879.html
Copyright © 2020-2023  润新知