Porting DinnerNow.NET to Azure
July 4, 2009
I (along with Harin Sandhoo from AIS) recently worked on converting a subset of DinnerNow.net application to Azure. This post captures some of highlights of the porting effort.
DinnerNow.net is a reference application developed by Microsoft to showcase .NET 3.5 functionality. This application can be broken up into three subsystems:
1. Web site where customers can order food from a variety of restaurants in their local delivery area.
2. Smart client application that allows a restaurant manager to view the incoming orders and update their status.
3. Mobile application that allows a delivery person to be notified when orders are ready for delivery.
It made sense to start with porting the web site to Azure. In future, it may be interesting to look into building a Silverlight equivalent for the restaurant manager piece and perhaps, a live mesh based mobile delivery application.
DinnerNow.net web site is implemented as ASP.NET application hosted inside IIS 7. Data is currently stored in SQL 2005, a LINQ to SQL based data access layer is used to persist the data. Business service functionality is using WCF and workflow service (also hosted inside the IIS 7)
[ Readers who are not already familiar with Azure concepts such as roles, may find it useful to review this first ]
The Azure version of DinnerNow.net utilizes the web role to host ASP.NET code as well as the WCF services. For now (because of the limits on the # of projects under the CTP) the UI code and WCF endpoints are hosted within the same web role. In the future, it will make sense to move the WCF endpoints to a separate web role. An Azure Table based membership provider ( part of the Azure SDK sample) is used for authentication.
A worker role is used for some background processing tasks such as storing the order into the database. The communication between the web and worker role takes place via the Azure Queue.
The worker role is also responsible for communicating with the workflow program (ProcessOrder.xoml) that places the submitted order to a queue for further processing by the restaurants. As of July 1st, Azure Workflow Service has been taken down. As a result, we have taken out the workflow service related code. The key motivations for including Azure Workflow Service, in the first place, included 1) a robust host for the workflow program 2) connectivity to applications inside the enterprise (such as the restaurant manager application)
The biggest challenge in porting the application was related to the database. Even though the relational features for SDS have been announced, they are not yet available. This forced us to rely on Windows Azure Table as the persistence store. The key consideration in moving the data from relational DB to Azure Table is the partitioning strategy. Consider the following the dbml diagram depicting Order, OrderDetail and OrderPayment, LINQ to SQL classes. Azure Table supports a flexible schema that allows entities of different types to be stored within a single table. Since there was a need to retrieve Order and OrderDetails together, we clustered the two together inside a single table for efficient retrieval. We partitioned the data according to order id and the RowKey was used to differentiate between the entities (i.e. “OrderItem_”+ DateTime , “Order_” + DateTime). Since the sorting is lexicographic, we use fixed length format based on Ticks.
Azure Table supports ADO.NET Data Services and REST. Fortunately, the data access code is not significantly different. So for example, the existing LINQ to SQL query inside the GetOrdersForRestaurant method that looks like this:
var ordersByRestaurant = (from o in db.Orders.Distinct()
where (from od in db.OrderDetails where od.RestaurantId == restaurantId select od.OrderId).Contains(o.OrderId)
select new DinnerNow.Business.Data.Order()
is changed to the following query when working with Azure Table:
var qResult = (from oItems in _context.CreateQuery<OrderItemEntity>(OrderTableName)
where oItems.RestaurantId == restaurantId
For additional details please refer to the file OrderProcessing.cs in the sample code that accompanies this blog post.
The following diagram depicts the code view for the project. DinnerNow.CloudService is the Azure Service project that comprises of the web and worker role. The web role is mapped to the DinnerNow.WebUX project. Similarly the worker role is mapped to the DinnerNow.WorkerRole.
- It is recommended that configuration data be stored inside the CSCFG file (as opposed to web.config). This is because CSCFG file is stored outside the application package you upload to the Azure Portal – The application package is really a diff disk that gets applied to the base HyperV image. By storing the configuration data in the CSCFG file means that you can make changes without the need to upload a new application page. To read config setting from the CSCFG file use GetConfigurationSetting method of the RoleManage class. Like so:
var sslPort = Microsoft.ServiceHosting.ServiceRuntime.RoleManager.GetConfigurationSetting(“sslport”);
- Our code is based SDK March CTP.
- ASP.NET code is running in full trust (now available with the March CTP).
- Testing – We mostly relied on the mixed mode testing – wherein the code was executed in the developer fabric but the data was in the Azure Table.
- We used Cerebrata’s nifty cloud storage tool for all our testing – https://onlinedemo.cerebrata.com/Cerebrata.CloudStorage/default.aspx