To have a valid copy of Visual Studio 2010 Professional, Premium, Ultimate ,or Test Professional, including SQL Server 2008 Express.
Preferably Windows 7 Professional, Enterprise, or Ultimate. I haven’t tested Vista or Visual Studio 2008. The Azure SDK - link at top of blog.
I am running Windows 7 Ultimate – 64-bit
1.6 GHz or faster non-Mac CPU 2+ GB RAM 20 GB Hard Disk
See section: Standalone Windows Azure SDK
Instructions for installing Azure SDK can be found here
Video that will help you verify your setup
Roy's Dissertation
When you create a new Windows Azure Project, it is actually composed of two separate projects. There are a couple of things to notice above about the Configuration Project and the RESTful Service Project:
Azure SDK Tools
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Security; using System.Web.SessionState; // These 3 using statements are needed for the Application_Start() method using Microsoft.WindowsAzure.ServiceRuntime; using Microsoft.WindowsAzure; using Microsoft.WindowsAzure.StorageClient; namespace FastMotorcycleList_WebRole { public class Global : System.Web.HttpApplication { protected void Application_Start(object sender, EventArgs e) { // Grab the configuration string string configValue = RoleEnvironment.GetConfigurationSettingValue("DataConnectionString"); // The account key will map to: // (1) development storage // (2) our storage account in a data center var account = CloudStorageAccount.Parse(configValue); // Create CloudTableClient tableClient = account.CreateCloudTableClient(); tableClient.CreateTableIfNotExist("lists"); } } }
DiagnosticMonitorConfiguration
using System; using System.Collections.Generic; using System.Linq; using Microsoft.WindowsAzure; using Microsoft.WindowsAzure.Diagnostics; using Microsoft.WindowsAzure.ServiceRuntime; namespace FastMotorcycleList_WebRole { public class WebRole : RoleEntryPoint { public override bool OnStart() { DiagnosticMonitorConfiguration diagnosticConfig = DiagnosticMonitor.GetDefaultInitialConfiguration(); diagnosticConfig.Directories.ScheduledTransferPeriod = TimeSpan.FromMinutes(1); diagnosticConfig.Directories.DataSources.Add( AzureLocalStorageTraceListener.GetLogDirectory()); return base.OnStart(); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Web; // These using statements need to be added // based on the code below using System.Diagnostics; using System.IO; using Microsoft.WindowsAzure.Diagnostics; using Microsoft.WindowsAzure.ServiceRuntime; namespace FastMotorcycleList_WebRole { public class AzureLocalStorageTraceListener : XmlWriterTraceListener { public AzureLocalStorageTraceListener() : base(Path.Combine(AzureLocalStorageTraceListener.GetLogDirectory().Path, "FastMotorcycleList.Web.svclog")) { } public static DirectoryConfiguration GetLogDirectory() { DirectoryConfiguration directory = new DirectoryConfiguration(); directory.Container = "mobile-tracefiles"; directory.DirectoryQuotaInMB = 10; directory.Path = RoleEnvironment.GetLocalResource("FastMotorcycleList.Web.svclog").RootPath; return directory; } } }
using System; using System.Collections.Generic; using System.Linq; using System.Web; // Added using statements using Microsoft.WindowsAzure; using Microsoft.WindowsAzure.ServiceRuntime; using Microsoft.WindowsAzure.StorageClient; using System.Data.Services.Client; namespace FastMotorcycleList_WebRole { // --------------------------------------------------------- // Purpose of Class: Provides basic create, read, delete operations to the service. // Abstracts away details of interacting with Azure Tables. // Notes: Uses FastMotorcycleList as persistant list public class FastMotorcycleListDataProvider { private FastMotorcycleList _list; // --------------------------------------------------------- // Purpose of Method: Connects to Azure Table Service and retrieves data // Notes: Uses web.config to read account credentials. // Developer needs to edit web.config to either point // to Azure Tables in local development environment // or up in cloud. public FastMotorcycleListDataProvider() { string configValue = RoleEnvironment.GetConfigurationSettingValue("DataConnectionString"); var account = CloudStorageAccount.Parse(configValue); _list = new FastMotorcycleList(account.TableEndpoint.ToString(), account.Credentials); } // --------------------------------------------------------- // Purpose of Method: Retrieves list from Azure Table Service // Notes: Uses "owner" for lookup // Owner is part of partitionkey so retrieval is fast public List<string> GetItems(string owner) { var results = from entity in _list.Items where entity.PartitionKey == owner select entity; var list = new List<string>(); foreach (var item in results) { list.Add(item.RowKey); } return list; } // --------------------------------------------------------- // Purpose of Method: Adds an entity to Azure Table Service // Notes: Each entity is associated with an owner public void AddItem(string owner, string item) { _list.AddObject("lists", new FastMotorcycleListItem(owner, item)); _list.SaveChanges(); } // --------------------------------------------------------- // Purpose of Method: Deletes an entity to Azure Table Service // Notes: Each entity is associated with an owner // --------------------------------------------------------- public void DeleteItem(string owner, string item) { var entity = (from i in _list.Items where i.PartitionKey == owner && i.RowKey == item select i).Single(); _list.DeleteObject(entity); _list.SaveChanges(); } } // --------------------------------------------------------- // Purpose of Class: Acts as the blueprint for an entity // Notes: The properties you add here define the // name value pairs that make up the table object public class FastMotorcycleListItem : TableServiceEntity { // --------------------------------------------------------- // Purpose of Method: Default constructor public FastMotorcycleListItem() { } // --------------------------------------------------------- // Purpose of Method: Represents the entity of 2 columns // (owner and list item) // Notes: No other properties defined because // only a two column table public FastMotorcycleListItem(string partitionKey, string rowKey) : base(partitionKey, rowKey) { } } // --------------------------------------------------------- // Purpose of Class: Abstracts away the fact that our Azure table // is in the cloud. TableServiceContext allows // us to code the entity as though it were // local public class FastMotorcycleList : TableServiceContext { // --------------------------------------------------------- // Purpose of Method: Connect to Azure Table Service // using storage credentials public FastMotorcycleList(string baseAddress, StorageCredentials storageCredentials) : base(baseAddress, storageCredentials) { } // --------------------------------------------------------- // Purpose of Method: Our list of entities is called "lists" public DataServiceQuery<FastMotorcycleListItem> Items { get { return this.CreateQuery<FastMotorcycleListItem>("lists"); } } } }
The storage system achieves good scalability by distributing the partitions across many storage nodes.
The system monitors the usage patterns of the partitions, and automatically balances these partitions across all the storage nodes.
Represents an Azure table, composed of multiple FastMotorCycleListItems.
At a lower level, represents a DataServiceContext object and allows the developer to use object oriented techniques to communicate with a table inside the Windows Azure Table service.
DataServiceContext to serve as a data access context class.
DataServiceContext supports functionality such as AddObject() to add an entity, UpdateObject() to update an entity, SaveChanges() to save changes to an entity, and CreateQuery<T> to create a query against the dataset.
The core functionality is supported in both synchronous and asynchronous versions.
DataServiceContext also supports batch operations.
Methods for FastMotorcycleListDataProvider
FastMotorcycleListService.svc will be edited to use a Web Service Host Factory. Using this approach a host instance is created dynamically in response to incoming messages. The managed hosting environments that support dynamic activation are Internet Information Services (IIS) and Windows Process Activation Service (WAS), which is supported in Windows Azure.
<%@ ServiceHost Debug="true" Factory="System.ServiceModel.Activation.WebServiceHostFactory" Service="FastMotorcycleList_WebRole.FastMotorcycleListService" %>
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.ServiceModel; using System.ServiceModel.Web; namespace FastMotorcycleList_WebRole { [ServiceContract] // --------------------------------------------------------- // Purpose of Class: The main class to service mobile clients RESTfully // // Notes: Uses FastMotorcycleListDataProvider public class FastMotorcycleListService { // --------------------------------------------------------- // Purpose: Helper class to abstract away the underlying // details of the Azure Table Service. private FastMotorcycleListDataProvider _data; // --------------------------------------------------------- // Purpose: Constructor for abstracted Azure Table Service public FastMotorcycleListService() { _data = new FastMotorcycleListDataProvider(); } // --------------------------------------------------------- // Purpose: Retrieve a list of Fast Motorcycles based on list // owner [OperationContract] [WebGet(UriTemplate = "/list/{owner}", ResponseFormat = WebMessageFormat.Json)] public List<string> GetItems(string owner) { return _data.GetItems(owner); } // --------------------------------------------------------- // Purpose: Add a new Fast Motorcycle based on owner [OperationContract] [WebInvoke(UriTemplate = "/list/{owner}", Method = "POST", RequestFormat = WebMessageFormat.Json)] public void AddItem(string owner, string item) { _data.AddItem(owner, item); } // --------------------------------------------------------- // Purpose: Delete a Fast Motorcycle based on Owner [OperationContract] [WebInvoke(UriTemplate = "/list/{owner}/{item}", Method = "DELETE")] public void DeleteItem(string owner, string item) { _data.DeleteItem(owner, item); } } }
<?xml version="1.0"?> <configuration> <configSections></configSections> <!--To collect diagnostic traces, uncomment the section below. To persist the traces to storage, update the DiagnosticsConnectionString setting with your storage credentials. To avoid performance degradation, remember to disable tracing on production deployments. <system.diagnostics> <sharedListeners> <add name="AzureLocalStorage" type="AzureShoppingList.Web.AzureLocalStorageTraceListener, AzureShoppingList.Web"/> </sharedListeners> <sources> <source name="System.ServiceModel" switchValue="Verbose, ActivityTracing"> <listeners> <add name="AzureLocalStorage"/> </listeners> </source> <source name="System.ServiceModel.MessageLogging" switchValue="Verbose"> <listeners> <add name="AzureLocalStorage"/> </listeners> </source> </sources> </system.diagnostics> --> <system.diagnostics> <trace> <listeners> <add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="AzureDiagnostics"> <filter type=""/> </add> </listeners> </trace> </system.diagnostics> <system.web> <compilation debug="true" targetFramework="4.0"/> </system.web> <system.webServer> <modules runAllManagedModulesForAllRequests="true"/> </system.webServer> </configuration>