PageRenderTime 169ms CodeModel.GetById 61ms app.highlight 68ms RepoModel.GetById 32ms app.codeStats 1ms

/articles/cloud-services-dotnet-multi-tier-app-using-service-bus-queues.md

https://github.com/bgoldy/azure-content
Markdown | 678 lines | 481 code | 197 blank | 0 comment | 0 complexity | b0b508b1261f8cb33e5133c4d9f19e55 MD5 | raw file
  1<properties linkid="dev-net-e2e-multi-tier" urlDisplayName="Multi-Tier Application" pageTitle=".NET Multi-Tier Application - Azure Tutorial" metaKeywords="Azure Service Bus queue tutorial, Azure queue tutorial, Azure worker role tutorial, Azure .NET queue tutorial, Azure C# queue tutorial, Azure C# worker role tutorial" description="A tutorial that helps you develop a multi-tier app in Azure that uses Service Bus queues to communicate between tiers. Samples in .NET." metaCanonical="" services="cloud-services,service-bus" documentationCenter=".NET" title=".NET Multi-Tier Application Using Service Bus Queues" authors="sethm" solutions="" manager="dwrede" editor="mattshel" />
  2
  3<tags ms.service="service-bus" ms.workload="tbd" ms.tgt_pltfrm="na" ms.devlang="dotnet" ms.topic="article" ms.date="01/01/1900" ms.author="sethm" />
  4
  5
  6
  7
  8
  9# .NET Multi-Tier Application Using Service Bus Queues
 10
 11Developing for Azure is easy using Visual Studio 2013 and the
 12free Azure SDK for .NET. If you do not already have Visual
 13Studio 2013, the SDK will automatically install Visual Studio Express 2013, so you can start developing for Azure entirely for
 14free. This guide assumes you have no prior experience using Windows
 15Azure. On completing this guide, you will have an application that uses
 16multiple Azure resources running in your local environment and
 17demonstrating how a multi-tier application works.
 18
 19You will learn:
 20
 21-   How to enable your computer for Azure development with a
 22    single download and install.
 23-   How to use Visual Studio to develop for Azure.
 24-   How to create a multi-tier application in Azure using web
 25    and worker roles.
 26-   How to communicate between tiers using Service Bus Queues.
 27
 28[WACOM.INCLUDE [create-account-note](../includes/create-account-note.md)]
 29
 30In this tutorial you'll build and run the multi-tier application in an Azure Cloud Service. The front end will be an ASP.NET MVC web role and the back end will be a worker-role. You could create the same multi-tier application with the front end as a web project that would be deployed to an Azure Web Site instead of a cloud service. For instructions about what to do differently an Azure Web Site front end, see the [Next steps](#nextsteps) section.
 31
 32A screenshot of the completed application is shown below:
 33
 34![][0]
 35
 36**Note** Azure also provides storage queue functionality. For more information about Azure storage queues and Service Bus queues, see [Azure Queues and Azure Service Bus Queues - Compared and Contrasted][sbqueuecomparison].  
 37
 38<h2><span class="short-header">Inter-role communication</span>Scenario overview: inter-role communication</h2>
 39
 40To submit an order for processing, the front end UI component, running
 41in the web role, needs to interact with the middle tier logic running in
 42the worker role. This example uses Service Bus brokered messaging for
 43the communication between the tiers.
 44
 45Using brokered messaging between the web and middle tiers decouples the
 46two components. In contrast to direct messaging (that is, TCP or HTTP),
 47the web tier does not connect to the middle tier directly; instead it
 48pushes units of work, as messages, into the Service Bus, which reliably
 49retains them until the middle tier is ready to consume and process them.
 50
 51The Service Bus provides two entities to support brokered messaging:
 52queues and topics. With queues, each message sent to the queue is
 53consumed by a single receiver. Topics support the publish/subscribe
 54pattern in which each published message is made available to each
 55subscription registered with the topic. Each subscription logically
 56maintains its own queue of messages. Subscriptions can also be
 57configured with filter rules that restrict the set of messages passed to
 58the subscription queue to those that match the filter. This example uses
 59Service Bus queues.
 60
 61![][1]
 62
 63This communication mechanism has several advantages over direct
 64messaging, namely:
 65
 66-   **Temporal decoupling.** With the asynchronous messaging pattern,
 67    producers and consumers need not be online at the same time. Service
 68    Bus reliably stores messages until the consuming party is ready to
 69    receive them. This allows the components of the distributed
 70    application to be disconnected, either voluntarily, for example, for
 71    maintenance, or due to a component crash, without impacting the
 72    system as a whole. Furthermore, the consuming application may only
 73    need to come online during certain times of the day.
 74
 75-   **Load leveling**. In many applications, system load varies over
 76    time whereas the processing time required for each unit of work is
 77    typically constant. Intermediating message producers and consumers
 78    with a queue means that the consuming application (the worker) only
 79    needs to be provisioned to accommodate average load rather than peak
 80    load. The depth of the queue will grow and contract as the incoming
 81    load varies. This directly saves money in terms of the amount of
 82    infrastructure required to service the application load.
 83
 84-   **Load balancing.** As load increases, more worker processes can be
 85    added to read from the queue. Each message is processed by only one
 86    of the worker processes. Furthermore, this pull-based load balancing
 87    allows for optimum utilization of the worker machines even if the
 88    worker machines differ in terms of processing power as they will
 89    pull messages at their own maximum rate. This pattern is often
 90    termed the competing consumer pattern.
 91
 92    ![][2]
 93
 94The following sections discuss the code that implements this
 95architecture.
 96
 97<h2><span class="short-header">Set up environment</span>Set up the development environment</h2>
 98
 99Before you can begin developing your Azure application, you need
100to get the tools and set-up your development environment.
101
1021.  To install the Azure SDK for .NET, click the button below:
103
104    [Get Tools and SDK][]
105
1062. 	Click **install the SDK**.
107
1083. 	Choose the link for the version of Visual Studio you are using. The steps in this tutorial use Visual Studio 2013:
109
110	![][32]
111
1124. 	When prompted to run or save the installation file, click
113    **Run**:
114
115    ![][3]
116
1175.  In the Web Platform Installer, click **Install** and proceed with the installation:
118
119    ![][33]
120
1216.  Once the installation is complete, you will have everything
122    necessary to start developing. The SDK includes tools that let you
123    easily develop Azure applications in Visual Studio. If you
124    do not have Visual Studio installed, it also installs the free
125    Visual Studio Express for Web.
126
127<h2><span class="short-header">Set up the namespace</span>Set up the Service Bus namespace</h2>
128
129The next step is to create a service namespace, and to obtain a shared
130secret key. A service namespace provides an application boundary for
131each application exposed through Service Bus. A shared secret key is
132automatically generated by the system when a service namespace is
133created. The combination of service namespace and shared secret key
134provides a credential for Service Bus to authenticate access to an
135application.
136
137Note that you can also manage namespaces and Service Bus messaging entities using the Visual Studio Server Explorer, but you can only create new namespaces from within the portal. 
138
139###Set up the namespace using the Management Portal
140
1411.  Log into the [Azure Management Portal][].
142
1432.  In the left navigation pane of the Management Portal, click
144    **Service Bus**.
145
1463.  In the lower pane of the Management Portal, click **Create**.
147
148    ![][6]
149
1504.  In the **Add a new namespace** dialog, enter a namespace name.
151    The system immediately checks to see if the name is available.   
152    ![][7]
153
1545.  After making sure the namespace name is available, choose the
155    country or region in which your namespace should be hosted (make
156    sure you use the same country/region in which you are deploying your
157    compute resources).
158
159    IMPORTANT: Pick the **same region** that you intend to choose for
160    deploying your application. This will give you the best performance.
161
1626.  Click the check mark. The system now creates your service
163    namespace and enables it. You might have to wait several minutes as
164    the system provisions resources for your account.
165
166	![][27]
167
1687.  In the main window, click the name of your service namespace.
169
170	![][30]
171
1728. Click **Connection Information**.
173
174	![][31]
175
1769.  In the **Access connection information** pane, find the **Default Issuer** and **Default Key** values.
177
17810.  Make a note of the key, or copy it to the clipboard.
179
180###Manage namespaces and messaging entities using the Visual Studio Server Explorer
181
182To manage a namespace and obtain connection information using Visual Studio instead of the Management Portal, follow the procedure described [here](http://http://msdn.microsoft.com/en-us/library/windowsazure/ff687127.aspx), in the section titled **To connect to Azure from Visual Studio**. When you sign in to Azure, the **Service Bus** node under the **Microsoft Azure** tree in Server Explorer is automatically populated with any namespaces you've already created. Right-click any namespace, and then click **Properties** to see the connection string and other metadata associated with this namespace displayed in the Visual Studio **Properties** pane. 
183
184Make a note of the **SharedAccessKey** value, or copy it to the clipboard:
185
186![][34]
187
188<h2><span class="short-header">Create a web role</span>Create a web role</h2>
189
190In this section, you will build the front end of your application. You
191will first create the various pages that your application displays.
192After that, you will add the code for submitting items to a Service Bus
193Queue and displaying status information about the queue.
194
195### Create the project
196
1971.  Using administrator privileges, start either Microsoft Visual Studio
198    2013 or Microsoft Visual Studio Express. To start Visual
199    Studio with administrator privileges, right-click **Microsoft Visual
200    Studio 2013 (or Microsoft Visual Studio Express)** and
201    then click **Run as administrator**. The Azure compute emulator,
202    discussed later in this guide, requires that Visual Studio be
203    launched with administrator privileges.
204
205    In Visual Studio, on the **File** menu, click **New**, and then
206    click **Project**.
207
208    ![][8]
209
210
2112.  From **Installed Templates**, under **Visual C#**, click **Cloud** and
212    then click **Azure Cloud Service**. Name the project
213    **MultiTierApp**. Then click **OK**.
214
215    ![][9]
216
2173.  From **.NET Framework 4.5** roles, double-click **ASP.NET Web
218    Role**.
219
220    ![][10]
221
2224.  Hover over **WebRole1** under **Azure Cloud Service solution**, click
223    the pencil icon, and rename the web role to **FrontendWebRole**. Then Click **OK**. (Make sure you enter "Frontend" with a lower-case "e", not "FrontEnd".)
224
225    ![][11]
226
2275.  From the **New ASP.NET Project** dialog, in the **Select a template** list, click **MVC**,
228    then click **OK**.
229
230    ![][12]
231
2326.  In **Solution Explorer**, right-click **References**, then click
233    **Manage NuGet Packages...** or **Add Library Package Reference**.
234
2357.  Select **Online** on the left-hand side of the dialog. Search for
236    "**WindowsAzure**" and select the **Azure Service
237    Bus** item. Then complete the installation and close this dialog.
238
239    ![][13]
240
2418.  Note that the required client assemblies are now referenced and some
242    new code files have been added.
243
2449.  In **Solution Explorer**, right click **Models** and click **Add**,
245    then click **Class**. In the Name box, type the name
246    **OnlineOrder.cs**. Then click **Add**.
247
248### Write the code for your web role
249
250In this section, you will create the various pages that your application
251displays.
252
2531.  In the **OnlineOrder.cs** file in Visual Studio, replace the
254    existing namespace definition with the following code:
255
256        namespace FrontendWebRole.Models
257        {
258            public class OnlineOrder
259            {
260                public string Customer { get; set; }
261                public string Product { get; set; }
262            }
263        }
264
2652.  In **Solution Explorer**, double-click
266    **Controllers\HomeController.cs**. Add the following **using**
267    statements at the top of the file to include the namespaces for the
268    model you just created, as well as Service Bus:
269
270        using FrontendWebRole.Models;
271        using Microsoft.ServiceBus.Messaging;
272        using Microsoft.ServiceBus;
273
2743.  Also in the **HomeController.cs** file in Visual Studio, replace the
275    existing namespace definition with the following code. This code
276    contains methods for handling the submission of items to the queue:
277
278        namespace FrontendWebRole.Controllers
279        {
280            public class HomeController : Controller
281            {
282                public ActionResult Index()
283                {
284                    // Simply redirect to Submit, since Submit will serve as the
285                    // front page of this application
286                    return RedirectToAction("Submit");
287                }
288
289                public ActionResult About()
290                {
291                    return View();
292                }
293
294                // GET: /Home/Submit
295                // Controller method for a view you will create for the submission
296                // form
297                public ActionResult Submit()
298                {
299                    // Will put code for displaying queue message count here.
300
301                    return View();
302                }
303
304                // POST: /Home/Submit
305                // Controller method for handling submissions from the submission
306                // form 
307                [HttpPost]
308				// Attribute to help prevent cross-site scripting attacks and 
309				// cross-site request forgery  
310    			[ValidateAntiForgeryToken] 
311                public ActionResult Submit(OnlineOrder order)
312                {
313                    if (ModelState.IsValid)
314                    {
315                        // Will put code for submitting to queue here.
316                    
317                        return RedirectToAction("Submit");
318                    }
319                    else
320                    {
321                        return View(order);
322                    }
323                }
324            }
325        }
326
3274.  From the **Build** menu, click **Build Solution**.
328
3295.  Now, you will create the view for the **Submit()** method you
330    created above. Right-click within the Submit() method, and choose
331    **Add View**
332
333    ![][14]
334
3356.  A dialog appears for creating the view. Select the
336    **OnlineOrder** class in the **Model class** dropdown, and choose
337    **Create** in the **Template** dropdown.
338
339    ![][15]
340
3417.  Click **Add**.
342
3438.  Now, you will change the displayed name of your application. In the
344    **Solution Explorer**, double-click the
345    **Views\Shared\\_Layout.cshtml** file to open it in the Visual
346    Studio editor.
347
3489.  Replace all occurrences of **My ASP.NET MVC Application** with
349    **LITWARE'S Awesome Products**.
350
35110.	Replace **"your logo here"** with **LITWARE'S Awesome Products**:
352
353	![][16]
354
35511. Remove the **Home**, **About**, and **Contact** links. Delete the highlighted code:
356
357	![][28]
358  
359
36012. Finally, modify the submission page to include some information about
361    the queue. In **Solution Explorer**, double-click the
362    **Views\Home\Submit.cshtml** file to open it in the Visual Studio
363    editor. Add the following line after **&lt;h2>Submit&lt;/h2>**. For now,
364    the **ViewBag.MessageCount** is empty. You will populate it later.
365
366        <p>Current Number of Orders in Queue Waiting to be Processed: @ViewBag.MessageCount</p>
367             
368
36913. You now have implemented your UI. You can press **F5** to run your
370    application and confirm that it looks as expected.
371
372    ![][17]
373
374### Write the code for submitting items to a Service Bus queue
375
376Now, you will add code for submitting items to a queue. You will first
377create a class that contains your Service Bus Queue connection
378information. Then, you will initialize your connection from
379**Global.aspx.cs**. Finally, you will update the submission code you
380created earlier in **HomeController.cs** to actually submit items to a
381Service Bus Queue.
382
3831.  In Solution Explorer, right-click **FrontendWebRole** (right-click the project, not the role). Click **Add**, and then click **Class**.
384
3852.  Name the class **QueueConnector.cs**. Click **Add** to create the class.
386
3873.  You will now paste in code that encapsulates your connection
388    information and contains methods for initializing the connection to
389    a Service Bus Queue. In QueueConnector.cs, paste in the following code, and enter in
390    values for **Namespace**, **IssuerName**, and **IssuerKey**. You can
391    obtain these values either from the [Management Portal][Azure Management Portal], or from the Visual Studio Server Explorer under the **Service Bus** node.
392
393        using System;
394        using System.Collections.Generic;
395        using System.Linq;
396        using System.Web;
397        using Microsoft.ServiceBus.Messaging;
398        using Microsoft.ServiceBus;
399
400        namespace FrontendWebRole
401        {
402            public static class QueueConnector
403            {
404                // Thread-safe. Recommended that you cache rather than recreating it
405                // on every request.
406                public static QueueClient OrdersQueueClient;
407
408                // Obtain these values from the Management Portal
409                public const string Namespace = "your service bus namespace";
410                public const string IssuerName = "issuer name";
411                public const string IssuerKey = "issuer key";
412
413                // The name of your queue
414                public const string QueueName = "OrdersQueue";
415
416                public static NamespaceManager CreateNamespaceManager()
417                {
418                    // Create the namespace manager which gives you access to
419                    // management operations
420                    var uri = ServiceBusEnvironment.CreateServiceUri(
421                        "sb", Namespace, String.Empty);
422                    var tP = TokenProvider.CreateSharedSecretTokenProvider(
423                        IssuerName, IssuerKey);
424                    return new NamespaceManager(uri, tP);
425                }
426
427                public static void Initialize()
428                {
429                    // Using Http to be friendly with outbound firewalls
430                    ServiceBusEnvironment.SystemConnectivity.Mode = 
431                        ConnectivityMode.Http;
432
433                    // Create the namespace manager which gives you access to 
434                    // management operations
435                    var namespaceManager = CreateNamespaceManager();
436
437                    // Create the queue if it does not exist already
438                    if (!namespaceManager.QueueExists(QueueName))
439                    {
440                        namespaceManager.CreateQueue(QueueName);
441                    }
442
443                    // Get a client to the queue
444                    var messagingFactory = MessagingFactory.Create(
445                        namespaceManager.Address, 
446                        namespaceManager.Settings.TokenProvider);
447                    OrdersQueueClient = messagingFactory.CreateQueueClient(
448                        "OrdersQueue");
449                }
450            }
451        }
452
4534.  Now, you will ensure your **Initialize** method gets called. In **Solution Explorer**, double-click **Global.asax\Global.asax.cs**.
454
4555.  Add the following line to the bottom of the **Application_Start**
456    method:
457
458        FrontendWebRole.QueueConnector.Initialize();
459
4606.  Finally, you will update your web code you created earlier, to
461    submit items to the queue. In **Solution Explorer**,
462    double-click **Controllers\HomeController.cs** that you created
463    earlier.
464
4657.  Update the **Submit()** method as follows to get the message count
466    for the queue:
467
468        public ActionResult Submit()
469        {            
470            // Get a NamespaceManager which allows you to perform management and
471            // diagnostic operations on your Service Bus Queues.
472            var namespaceManager = QueueConnector.CreateNamespaceManager();
473
474            // Get the queue, and obtain the message count.
475            var queue = namespaceManager.GetQueue(QueueConnector.QueueName);
476            ViewBag.MessageCount = queue.MessageCount;
477
478            return View();
479        }
480
4818.  Update the **Submit(OnlineOrder order)** method as follows to submit
482    order information to the queue:
483
484        public ActionResult Submit(OnlineOrder order)
485        {
486            if (ModelState.IsValid)
487            {
488                // Create a message from the order
489                var message = new BrokeredMessage(order);
490                
491                // Submit the order
492                QueueConnector.OrdersQueueClient.Send(message);
493                return RedirectToAction("Submit");
494            }
495            else
496            {
497                return View(order);
498            }
499        }
500
5019.  You can now run your application again. Each time you submit an
502    order, the message count increases.
503
504    ![][18]
505
506<h2><span class="short-header">Configuration manager</span>Cloud configuration manager</h2>
507
508Azure supports a set of managed APIs that provides a consistent way to create new instances of Azure service clients (such as the Service Bus) across Microsoft cloud services. These APIs enable you to instantiate these clients (for example, **CloudBlobClient**, **QueueClient**, **TopicClient**) regardless of where the application is hosted -- on-premises, in a Microsoft cloud service, in web sites, or in a persistent VM Role. You can also use these APIs to retrieve the configuration information necessary for instantiating these clients, and to change the configuration without having to redeploy the calling application. The APIs are located in the [Microsoft.WindowsAzure.Configuration.CloudConfigurationManager][] class. There are also APIs on the client side.
509
510### Connection string
511
512To instantiate a client (for example, a Service Bus **QueueClient**), you can represent the configuration information as a connection string. On the client side, there is a **CreateFromConnectionString()** method that instantiates that client type by using that connection string. For example, given the following configuration section:
513
514	<ConfigurationSettings>
515    ...
516    	<Setting name="Microsoft.ServiceBus.ConnectionString" value="Endpoint=sb://[yourServiceNamespace].servicebus.windows.net/;SharedSecretIssuer=[issuerName];SharedSecretValue=[yourDefaultKey]" />
517	</ConfigurationSettings>
518
519The following code retrieves the connection string, creates a queue, and initializes the connection to the queue:
520
521	QueueClient Client; 
522
523	string connectionString =
524     CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ConnectionString");
525	
526    var namespaceManager =
527     NamespaceManager.CreateFromConnectionString(connectionString); 
528
529	if (!namespaceManager.QueueExists(QueueName))
530    {
531        namespaceManager.CreateQueue(QueueName);
532    }
533
534	// Initialize the connection to Service Bus Queue
535	Client = QueueClient.CreateFromConnectionString(connectionString, QueueName);
536
537The code in the following section uses these configuration management APIs.
538
539<h2><span class="short-header">Create worker role</span>Create the worker role</h2>
540
541You will now create the worker role that processes the order
542submissions. This example uses the **Worker Role with Service Bus Queue** Visual Studio project template. First, you will use Server Explorer in Visual Studio to obtain the required credentials.
543
5441. If you've already connected Visual Studio to your Azure account, as described in the section **Set up the namespace using the Visual Studio Server Explorer,** skip ahead to step 5. 
545
5463. From the menu bar in Visual Studio, choose **View**, and then click **Server Explorer**. A **Service Bus** node appears under **Azure** within the Server Explorer hierarchy, as in the following figure.
547
548	![][21]
549
5502. In Server Explorer, expand **Azure**, then right-click **Service Bus**, then click **Add New Connection**.
551
5523. In the **Add Connection** dialog, type the name of the service namespace, the issuer name, and the issuer key. Then click **OK** to connect.
553
554	![][22]
555
5564.  In Visual Studio, in **Solution Explorer** right-click the
557    **Roles** folder under the **MultiTierApp** project.
558
5595.  Click **Add**, and then click **New Worker Role Project**. The **Add New Role Project** dialog appears.
560
561	![][26]
562
5636.  In the **Add New Role Project dialog**, click **Worker Role with Service Bus Queue**, as in the following figure:
564
565	![][23]
566
5677.  In the **Name** box, name the project **OrderProcessingRole**. Then click **Add**.
568
5698.  In Server Explorer, right-click the name of your service namespace, then click **Properties**. In the Visual Studio **Properties** pane, the first entry contains a connection string that is populated with the service namespace endpoint containing the required authorization credentials. For example, see the following figure. Double-click **ConnectionString**, and then press **Ctrl+C** to copy this string to the clipboard.
570
571	![][24]
572
5739.  In Solution Explorer, right-click the **OrderProcessingRole** you created in step 7 (make sure that you right-click **OrderProcessingRole** under **Roles**, and not the class). Then click **Properties**.
574
57510.  In the **Settings** tab of the **Properties** dialog, click inside the **Value** box for **Microsoft.ServiceBus.ConnectionString**, and then paste the endpoint value you copied in step 8.
576
577	![][25]
578
57911.  Create an **OnlineOrder** class to represent the orders as you process them from the queue. You can reuse a class you have already created. In Solution Explorer, right-click the **OrderProcessingRole** project (right-click the project, not the role). Click **Add**, then click **Existing Item**.
580
58112. Browse to the subfolder for **FrontendWebRole\Models**, and double-click **OnlineOrder.cs** to add it to this project.
582
58313. In WorkerRole.cs, replace the value of the **QueueName** variable in **WorkerRole.cs** from `"ProcessingQueue"` to `"OrdersQueue"` as in the following code:
584
585		// The name of your queue
586		const string QueueName = "OrdersQueue";
587
58814. Add the following using statement at the top of the WorkerRole.cs file:
589
590		using FrontendWebRole.Models;
591
59215. In the `Run()` function, inside the `OnMessage` call, add the following code inside the `try` clause:
593
594		Trace.WriteLine("Processing", receivedMessage.SequenceNumber.ToString());
595		// View the message as an OnlineOrder
596		OnlineOrder order = receivedMessage.GetBody<OnlineOrder>();
597		Trace.WriteLine(order.Customer + ": " + order.Product, "ProcessingMessage");
598		receivedMessage.Complete();
599
60016.  You have completed the application. You can test the full
601    application as you did earlier, by pressing F5. Note that the message count does not increment, because the worker role processes items from the queue and marks them as complete. You can see the trace output of your
602    worker role by viewing the Azure Compute Emulator UI. You
603    can do this by right-clicking the emulator icon in the notification
604    area of your taskbar and selecting **Show Compute Emulator UI**.
605
606    ![][19]
607
608    ![][20]
609
610<h2><a name="nextsteps"></a><span class="short-header">Next steps</span>Next steps</h2>  
611
612To learn more about Service Bus, see the following resources:  
613  
614* [Azure Service Bus][sbmsdn]  
615* [Service Bus How To's][sbwacom]  
616* [How to Use Service Bus Queues][sbwacomqhowto]  
617
618To learn more about multi-tier scenarios, or to learn how to deploy an application to a cloud service, see:  
619
620* [.NET Multi-Tier Application Using Storage Tables, Queues, and Blobs][mutitierstorage]  
621
622You might want to implement the front-end of a multi-tier application in an Azure Web Site instead of an Azure Cloud Service. To learn more about the difference between web sites and cloud services, see [Azure Execution Models][executionmodels].
623
624To implement the application you create in this tutorial as a standard web project instead of as a cloud service web role, follow the steps in this tutorial with the following differences:
625
6261. When you create the project, choose the **ASP.NET MVC 4 Web Application** project template in the **Web** category instead of the **Cloud Service** template in the **Cloud** category. Then follow the same directions for creating the MVC application, until you get to the **Cloud configuration manager** section.
627
6282. When you create the worker role, create it in a new, separate solution, similar to the original instructions for the web role. Now however, you're creating just the worker role in the cloud service project. Then follow the same directions for creating the worker role.
629
6303. You can test the front-end and back-end separately, or you can run both simultaneously in separate Visual Studio instances.
631
632To learn how to deploy the front end to an Azure Web Site, see [Deploying an ASP.NET Web Application to an Azure Web Site](http://www.windowsazure.com/en-us/develop/net/tutorials/get-started/). To learn how to deploy the back end to an Azure Cloud Service, see [.NET Multi-Tier Application Using Storage Tables, Queues, and Blobs][mutitierstorage].
633
634
635  [0]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-01.png
636  [1]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-100.png
637  [sbqueuecomparison]: http://msdn.microsoft.com/en-us/library/windowsazure/hh767287.aspx
638  [2]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-101.png
639  [Get Tools and SDK]: http://go.microsoft.com/fwlink/?LinkId=271920
640  [3]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-3.png
641  
642  
643  
644  [Azure Management Portal]: http://manage.windowsazure.com
645  [6]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/sb-queues-03.png
646  [7]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/sb-queues-04.png
647  [8]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-09.png
648  [9]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-10.jpg
649  [10]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-11.png
650  [11]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-02.png
651  [12]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-12.png
652  [13]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-13.png
653  [14]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-33.png
654  [15]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-34.png
655  [16]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-35.png
656  [17]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-36.png
657  [18]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-37.png
658  
659  [19]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-38.png
660  [20]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-39.png
661  [21]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/SBExplorer.png
662  [22]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/SBExplorerAddConnect.png
663  [23]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/SBWorkerRole1.png
664  [24]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/SBExplorerProperties.png
665  [25]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/SBWorkerRoleProperties.png
666  [26]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/SBNewWorkerRole.png
667  [27]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-27.png
668  [28]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-40.png
669  [30]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/sb-queues-09.png
670  [31]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/sb-queues-06.png
671  [32]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-41.png
672  [33]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-4-2-WebPI.png
673  [34]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/VSProperties.png
674  [sbmsdn]: http://msdn.microsoft.com/en-us/library/windowsazure/ee732537.aspx  
675  [sbwacom]: /en-us/documentation/services/service-bus/  
676  [sbwacomqhowto]: /en-us/develop/net/how-to-guides/service-bus-queues/  
677  [mutitierstorage]: /en-us/develop/net/tutorials/multi-tier-web-site/1-overview/ 
678  [executionmodels]: http://www.windowsazure.com/en-us/develop/net/fundamentals/compute/