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

简介:

我们大概了解了一些关于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 ]   =   @p0 AND  ( [ 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。如果大家感兴趣的话,敬请留意:)

  好了,今天的文章就先到这里了,如果大家有什么问题欢迎与我交流.



本文转自 daizhenjun 51CTO博客,原文链接:http://blog.51cto.com/daizhj/339019,如需转载请自行联系原作者

相关文章
|
2月前
|
存储 Shell Linux
快速上手基于 BaGet 的脚本自动化构建 .net 应用打包
本文介绍了如何使用脚本自动化构建 `.net` 应用的 `nuget` 包并推送到指定服务仓库。首先概述了 `BaGet`——一个开源、轻量级且高性能的 `NuGet` 服务器,支持多种存储后端及配置选项。接着详细描述了 `BaGet` 的安装、配置及使用方法,并提供了 `PowerShell` 和 `Bash` 脚本实例,用于自动化推送 `.nupkg` 文件。最后总结了 `BaGet` 的优势及其在实际部署中的便捷性。
126 10
|
3月前
|
Linux C++ Windows
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
|
9天前
|
开发框架 监控 .NET
【Azure App Service】部署在App Service上的.NET应用内存消耗不能超过2GB的情况分析
x64 dotnet runtime is not installed on the app service by default. Since we had the app service running in x64, it was proxying the request to a 32 bit dotnet process which was throwing an OutOfMemoryException with requests >100MB. It worked on the IaaS servers because we had the x64 runtime install
|
22天前
|
JSON 算法 安全
JWT Bearer 认证在 .NET Core 中的应用
【10月更文挑战第30天】JWT(JSON Web Token)是一种开放标准,用于在各方之间安全传输信息。它由头部、载荷和签名三部分组成,用于在用户和服务器之间传递声明。JWT Bearer 认证是一种基于令牌的认证方式,客户端在请求头中包含 JWT 令牌,服务器验证令牌的有效性后授权用户访问资源。在 .NET Core 中,通过安装 `Microsoft.AspNetCore.Authentication.JwtBearer` 包并配置认证服务,可以实现 JWT Bearer 认证。具体步骤包括安装 NuGet 包、配置认证服务、启用认证中间件、生成 JWT 令牌以及在控制器中使用认证信息
|
2月前
|
数据采集 JSON API
.NET 3.5 中 HttpWebRequest 的核心用法及应用
【9月更文挑战第7天】在.NET 3.5环境下,HttpWebRequest 类是处理HTTP请求的一个核心组件,它封装了HTTP协议的细节,使得开发者可以方便地发送HTTP请求并接收响应。本文将详细介绍HttpWebRequest的核心用法及其实战应用。
124 6
|
3月前
|
Linux iOS开发 开发者
跨平台开发不再难:.NET Core如何让你的应用在Windows、Linux、macOS上自如游走?
【8月更文挑战第28天】本文提供了一份详尽的.NET跨平台开发指南,涵盖.NET Core简介、环境配置、项目结构、代码编写、依赖管理、构建与测试、部署及容器化等多个方面,帮助开发者掌握关键技术与最佳实践,充分利用.NET Core实现高效、便捷的跨平台应用开发与部署。
186 3
|
3月前
|
缓存 Java API
【揭秘】.NET高手不愿透露的秘密:如何让应用瞬间提速?
【8月更文挑战第28天】本文通过对比的方式,介绍了针对 .NET 应用性能瓶颈的优化方法。以一个存在响应延迟和并发处理不足的 Web API 项目为例,从性能分析入手,探讨了使用结构体减少内存分配、异步编程提高吞吐量、EF Core 惰性加载减少数据库访问以及垃圾回收机制优化等多个方面,帮助开发者全面提升 .NET 应用的性能和稳定性。通过具体示例,展示了如何在不同场景下选择最佳实践,以实现更高效的应用体验。
46 3
|
3月前
|
前端开发 JavaScript 开发工具
跨域联姻:React.NET——.NET应用与React的完美融合,解锁前后端高效协作新姿势。
【8月更文挑战第28天】探索React.NET,这是将热门前端框架React与强大的.NET后端无缝集成的创新方案。React以其组件化和虚拟DOM技术著称,能构建高性能、可维护的用户界面;.NET则擅长企业级应用开发。React.NET作为桥梁,使.NET应用轻松采用React构建前端,并优化开发流程与性能。通过直接托管React组件,.NET应用简化了部署流程,同时支持服务器端渲染(SSR),提升首屏加载速度与SEO优化。
78 1
|
3月前
|
存储 缓存 安全
.NET 在金融行业的应用:高并发交易系统的构建与优化之路
【8月更文挑战第28天】在金融行业,交易系统需具备高并发处理、低延迟及高稳定性和安全性。利用.NET构建此类系统时,可采用异步编程提升并发能力,优化数据库访问以降低延迟,使用缓存减少数据库访问频率,借助分布式事务确保数据一致性,并加强安全性措施。通过综合优化,满足金融行业的严苛要求。
49 1
|
3月前
|
大数据 开发工具 开发者
从零到英雄:.NET核心技术带你踏上编程之旅,构建首个应用,开启你的数字世界探险!
【8月更文挑战第28天】本文带领读者从零开始,使用强大的.NET平台搭建首个控制台应用。无论你是新手还是希望扩展技能的开发者,都能通过本文逐步掌握.NET的核心技术。从环境搭建到创建项目,再到编写和运行代码,详细步骤助你轻松上手。通过计算两数之和的小项目,你不仅能快速入门,还能为未来开发更复杂的应用奠定基础。希望本文为你的.NET学习之旅开启新篇章!
34 1