PageRenderTime 720ms CodeModel.GetById 202ms app.highlight 246ms RepoModel.GetById 155ms app.codeStats 1ms

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

https://github.com/alexey-ernest/azure-content
Markdown | 676 lines | 480 code | 196 blank | 0 comment | 0 complexity | b28820fc06e0763207e4b0fba9ad75bd 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
  4
  5
  6
  7# .NET Multi-Tier Application Using Service Bus Queues
  8
  9Developing for Azure is easy using Visual Studio 2013 and the
 10free Azure SDK for .NET. If you do not already have Visual
 11Studio 2013, the SDK will automatically install Visual Studio Express 2013, so you can start developing for Azure entirely for
 12free. This guide assumes you have no prior experience using Windows
 13Azure. On completing this guide, you will have an application that uses
 14multiple Azure resources running in your local environment and
 15demonstrating how a multi-tier application works.
 16
 17You will learn:
 18
 19-   How to enable your computer for Azure development with a
 20    single download and install.
 21-   How to use Visual Studio to develop for Azure.
 22-   How to create a multi-tier application in Azure using web
 23    and worker roles.
 24-   How to communicate between tiers using Service Bus Queues.
 25
 26[WACOM.INCLUDE [create-account-note](../includes/create-account-note.md)]
 27
 28In 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.
 29
 30A screenshot of the completed application is shown below:
 31
 32![][0]
 33
 34**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].  
 35
 36<h2><span class="short-header">Inter-role communication</span>Scenario overview: inter-role communication</h2>
 37
 38To submit an order for processing, the front end UI component, running
 39in the web role, needs to interact with the middle tier logic running in
 40the worker role. This example uses Service Bus brokered messaging for
 41the communication between the tiers.
 42
 43Using brokered messaging between the web and middle tiers decouples the
 44two components. In contrast to direct messaging (that is, TCP or HTTP),
 45the web tier does not connect to the middle tier directly; instead it
 46pushes units of work, as messages, into the Service Bus, which reliably
 47retains them until the middle tier is ready to consume and process them.
 48
 49The Service Bus provides two entities to support brokered messaging:
 50queues and topics. With queues, each message sent to the queue is
 51consumed by a single receiver. Topics support the publish/subscribe
 52pattern in which each published message is made available to each
 53subscription registered with the topic. Each subscription logically
 54maintains its own queue of messages. Subscriptions can also be
 55configured with filter rules that restrict the set of messages passed to
 56the subscription queue to those that match the filter. This example uses
 57Service Bus queues.
 58
 59![][1]
 60
 61This communication mechanism has several advantages over direct
 62messaging, namely:
 63
 64-   **Temporal decoupling.** With the asynchronous messaging pattern,
 65    producers and consumers need not be online at the same time. Service
 66    Bus reliably stores messages until the consuming party is ready to
 67    receive them. This allows the components of the distributed
 68    application to be disconnected, either voluntarily, for example, for
 69    maintenance, or due to a component crash, without impacting the
 70    system as a whole. Furthermore, the consuming application may only
 71    need to come online during certain times of the day.
 72
 73-   **Load leveling**. In many applications, system load varies over
 74    time whereas the processing time required for each unit of work is
 75    typically constant. Intermediating message producers and consumers
 76    with a queue means that the consuming application (the worker) only
 77    needs to be provisioned to accommodate average load rather than peak
 78    load. The depth of the queue will grow and contract as the incoming
 79    load varies. This directly saves money in terms of the amount of
 80    infrastructure required to service the application load.
 81
 82-   **Load balancing.** As load increases, more worker processes can be
 83    added to read from the queue. Each message is processed by only one
 84    of the worker processes. Furthermore, this pull-based load balancing
 85    allows for optimum utilization of the worker machines even if the
 86    worker machines differ in terms of processing power as they will
 87    pull messages at their own maximum rate. This pattern is often
 88    termed the competing consumer pattern.
 89
 90    ![][2]
 91
 92The following sections discuss the code that implements this
 93architecture.
 94
 95<h2><span class="short-header">Set up environment</span>Set up the development environment</h2>
 96
 97Before you can begin developing your Azure application, you need
 98to get the tools and set-up your development environment.
 99
1001.  To install the Azure SDK for .NET, click the button below:
101
102    [Get Tools and SDK][]
103
1042. 	Click **install the SDK**.
105
1063. 	Choose the link for the version of Visual Studio you are using. The steps in this tutorial use Visual Studio 2013:
107
108	![][32]
109
1104. 	When prompted to run or save the installation file, click
111    **Run**:
112
113    ![][3]
114
1155.  In the Web Platform Installer, click **Install** and proceed with the installation:
116
117    ![][33]
118
1196.  Once the installation is complete, you will have everything
120    necessary to start developing. The SDK includes tools that let you
121    easily develop Azure applications in Visual Studio. If you
122    do not have Visual Studio installed, it also installs the free
123    Visual Studio Express for Web.
124
125<h2><span class="short-header">Set up the namespace</span>Set up the Service Bus namespace</h2>
126
127The next step is to create a service namespace, and to obtain a shared
128secret key. A service namespace provides an application boundary for
129each application exposed through Service Bus. A shared secret key is
130automatically generated by the system when a service namespace is
131created. The combination of service namespace and shared secret key
132provides a credential for Service Bus to authenticate access to an
133application.
134
135Note 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. 
136
137###Set up the namespace using the Management Portal
138
1391.  Log into the [Azure Management Portal][].
140
1412.  In the left navigation pane of the Management Portal, click
142    **Service Bus**.
143
1443.  In the lower pane of the Management Portal, click **Create**.
145
146    ![][6]
147
1484.  In the **Add a new namespace** dialog, enter a namespace name.
149    The system immediately checks to see if the name is available.   
150    ![][7]
151
1525.  After making sure the namespace name is available, choose the
153    country or region in which your namespace should be hosted (make
154    sure you use the same country/region in which you are deploying your
155    compute resources).
156
157    IMPORTANT: Pick the **same region** that you intend to choose for
158    deploying your application. This will give you the best performance.
159
1606.  Click the check mark. The system now creates your service
161    namespace and enables it. You might have to wait several minutes as
162    the system provisions resources for your account.
163
164	![][27]
165
1667.  In the main window, click the name of your service namespace.
167
168	![][30]
169
1708. Click **Connection Information**.
171
172	![][31]
173
1749.  In the **Access connection information** pane, find the **Default Issuer** and **Default Key** values.
175
17610.  Make a note of the key, or copy it to the clipboard.
177
178###Manage namespaces and messaging entities using the Visual Studio Server Explorer
179
180To 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. 
181
182Make a note of the **SharedAccessKey** value, or copy it to the clipboard:
183
184![][34]
185
186<h2><span class="short-header">Create a web role</span>Create a web role</h2>
187
188In this section, you will build the front end of your application. You
189will first create the various pages that your application displays.
190After that, you will add the code for submitting items to a Service Bus
191Queue and displaying status information about the queue.
192
193### Create the project
194
1951.  Using administrator privileges, start either Microsoft Visual Studio
196    2013 or Microsoft Visual Studio Express. To start Visual
197    Studio with administrator privileges, right-click **Microsoft Visual
198    Studio 2013 (or Microsoft Visual Studio Express)** and
199    then click **Run as administrator**. The Azure compute emulator,
200    discussed later in this guide, requires that Visual Studio be
201    launched with administrator privileges.
202
203    In Visual Studio, on the **File** menu, click **New**, and then
204    click **Project**.
205
206    ![][8]
207
208
2092.  From **Installed Templates**, under **Visual C#**, click **Cloud** and
210    then click **Azure Cloud Service**. Name the project
211    **MultiTierApp**. Then click **OK**.
212
213    ![][9]
214
2153.  From **.NET Framework 4.5** roles, double-click **ASP.NET Web
216    Role**.
217
218    ![][10]
219
2204.  Hover over **WebRole1** under **Azure Cloud Service solution**, click
221    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".)
222
223    ![][11]
224
2255.  From the **New ASP.NET Project** dialog, in the **Select a template** list, click **MVC**,
226    then click **OK**.
227
228    ![][12]
229
2306.  In **Solution Explorer**, right-click **References**, then click
231    **Manage NuGet Packages...** or **Add Library Package Reference**.
232
2337.  Select **Online** on the left-hand side of the dialog. Search for
234    "**WindowsAzure**" and select the **Azure Service
235    Bus** item. Then complete the installation and close this dialog.
236
237    ![][13]
238
2398.  Note that the required client assemblies are now referenced and some
240    new code files have been added.
241
2429.  In **Solution Explorer**, right click **Models** and click **Add**,
243    then click **Class**. In the Name box, type the name
244    **OnlineOrder.cs**. Then click **Add**.
245
246### Write the code for your web role
247
248In this section, you will create the various pages that your application
249displays.
250
2511.  In the **OnlineOrder.cs** file in Visual Studio, replace the
252    existing namespace definition with the following code:
253
254        namespace FrontendWebRole.Models
255        {
256            public class OnlineOrder
257            {
258                public string Customer { get; set; }
259                public string Product { get; set; }
260            }
261        }
262
2632.  In **Solution Explorer**, double-click
264    **Controllers\HomeController.cs**. Add the following **using**
265    statements at the top of the file to include the namespaces for the
266    model you just created, as well as Service Bus:
267
268        using FrontendWebRole.Models;
269        using Microsoft.ServiceBus.Messaging;
270        using Microsoft.ServiceBus;
271
2723.  Also in the **HomeController.cs** file in Visual Studio, replace the
273    existing namespace definition with the following code. This code
274    contains methods for handling the submission of items to the queue:
275
276        namespace FrontendWebRole.Controllers
277        {
278            public class HomeController : Controller
279            {
280                public ActionResult Index()
281                {
282                    // Simply redirect to Submit, since Submit will serve as the
283                    // front page of this application
284                    return RedirectToAction("Submit");
285                }
286
287                public ActionResult About()
288                {
289                    return View();
290                }
291
292                // GET: /Home/Submit
293                // Controller method for a view you will create for the submission
294                // form
295                public ActionResult Submit()
296                {
297                    // Will put code for displaying queue message count here.
298
299                    return View();
300                }
301
302                // POST: /Home/Submit
303                // Controller method for handling submissions from the submission
304                // form 
305                [HttpPost]
306				// Attribute to help prevent cross-site scripting attacks and 
307				// cross-site request forgery  
308    			[ValidateAntiForgeryToken] 
309                public ActionResult Submit(OnlineOrder order)
310                {
311                    if (ModelState.IsValid)
312                    {
313                        // Will put code for submitting to queue here.
314                    
315                        return RedirectToAction("Submit");
316                    }
317                    else
318                    {
319                        return View(order);
320                    }
321                }
322            }
323        }
324
3254.  From the **Build** menu, click **Build Solution**.
326
3275.  Now, you will create the view for the **Submit()** method you
328    created above. Right-click within the Submit() method, and choose
329    **Add View**
330
331    ![][14]
332
3336.  A dialog appears for creating the view. Select the
334    **OnlineOrder** class in the **Model class** dropdown, and choose
335    **Create** in the **Template** dropdown.
336
337    ![][15]
338
3397.  Click **Add**.
340
3418.  Now, you will change the displayed name of your application. In the
342    **Solution Explorer**, double-click the
343    **Views\Shared\\_Layout.cshtml** file to open it in the Visual
344    Studio editor.
345
3469.  Replace all occurrences of **My ASP.NET MVC Application** with
347    **LITWARE'S Awesome Products**.
348
34910.	Replace **"your logo here"** with **LITWARE'S Awesome Products**:
350
351	![][16]
352
35311. Remove the **Home**, **About**, and **Contact** links. Delete the highlighted code:
354
355	![][28]
356  
357
35812. Finally, modify the submission page to include some information about
359    the queue. In **Solution Explorer**, double-click the
360    **Views\Home\Submit.cshtml** file to open it in the Visual Studio
361    editor. Add the following line after **&lt;h2>Submit&lt;/h2>**. For now,
362    the **ViewBag.MessageCount** is empty. You will populate it later.
363
364        <p>Current Number of Orders in Queue Waiting to be Processed: @ViewBag.MessageCount</p>
365             
366
36713. You now have implemented your UI. You can press **F5** to run your
368    application and confirm that it looks as expected.
369
370    ![][17]
371
372### Write the code for submitting items to a Service Bus queue
373
374Now, you will add code for submitting items to a queue. You will first
375create a class that contains your Service Bus Queue connection
376information. Then, you will initialize your connection from
377**Global.aspx.cs**. Finally, you will update the submission code you
378created earlier in **HomeController.cs** to actually submit items to a
379Service Bus Queue.
380
3811.  In Solution Explorer, right-click **FrontendWebRole** (right-click the project, not the role). Click **Add**, and then click **Class**.
382
3832.  Name the class **QueueConnector.cs**. Click **Add** to create the class.
384
3853.  You will now paste in code that encapsulates your connection
386    information and contains methods for initializing the connection to
387    a Service Bus Queue. In QueueConnector.cs, paste in the following code, and enter in
388    values for **Namespace**, **IssuerName**, and **IssuerKey**. You can
389    obtain these values either from the [Management Portal][Azure Management Portal], or from the Visual Studio Server Explorer under the **Service Bus** node.
390
391        using System;
392        using System.Collections.Generic;
393        using System.Linq;
394        using System.Web;
395        using Microsoft.ServiceBus.Messaging;
396        using Microsoft.ServiceBus;
397
398        namespace FrontendWebRole
399        {
400            public static class QueueConnector
401            {
402                // Thread-safe. Recommended that you cache rather than recreating it
403                // on every request.
404                public static QueueClient OrdersQueueClient;
405
406                // Obtain these values from the Management Portal
407                public const string Namespace = "your service bus namespace";
408                public const string IssuerName = "issuer name";
409                public const string IssuerKey = "issuer key";
410
411                // The name of your queue
412                public const string QueueName = "OrdersQueue";
413
414                public static NamespaceManager CreateNamespaceManager()
415                {
416                    // Create the namespace manager which gives you access to
417                    // management operations
418                    var uri = ServiceBusEnvironment.CreateServiceUri(
419                        "sb", Namespace, String.Empty);
420                    var tP = TokenProvider.CreateSharedSecretTokenProvider(
421                        IssuerName, IssuerKey);
422                    return new NamespaceManager(uri, tP);
423                }
424
425                public static void Initialize()
426                {
427                    // Using Http to be friendly with outbound firewalls
428                    ServiceBusEnvironment.SystemConnectivity.Mode = 
429                        ConnectivityMode.Http;
430
431                    // Create the namespace manager which gives you access to 
432                    // management operations
433                    var namespaceManager = CreateNamespaceManager();
434
435                    // Create the queue if it does not exist already
436                    if (!namespaceManager.QueueExists(QueueName))
437                    {
438                        namespaceManager.CreateQueue(QueueName);
439                    }
440
441                    // Get a client to the queue
442                    var messagingFactory = MessagingFactory.Create(
443                        namespaceManager.Address, 
444                        namespaceManager.Settings.TokenProvider);
445                    OrdersQueueClient = messagingFactory.CreateQueueClient(
446                        "OrdersQueue");
447                }
448            }
449        }
450
4514.  Now, you will ensure your **Initialize** method gets called. In **Solution Explorer**, double-click **Global.asax\Global.asax.cs**.
452
4535.  Add the following line to the bottom of the **Application_Start**
454    method:
455
456        FrontendWebRole.QueueConnector.Initialize();
457
4586.  Finally, you will update your web code you created earlier, to
459    submit items to the queue. In **Solution Explorer**,
460    double-click **Controllers\HomeController.cs** that you created
461    earlier.
462
4637.  Update the **Submit()** method as follows to get the message count
464    for the queue:
465
466        public ActionResult Submit()
467        {            
468            // Get a NamespaceManager which allows you to perform management and
469            // diagnostic operations on your Service Bus Queues.
470            var namespaceManager = QueueConnector.CreateNamespaceManager();
471
472            // Get the queue, and obtain the message count.
473            var queue = namespaceManager.GetQueue(QueueConnector.QueueName);
474            ViewBag.MessageCount = queue.MessageCount;
475
476            return View();
477        }
478
4798.  Update the **Submit(OnlineOrder order)** method as follows to submit
480    order information to the queue:
481
482        public ActionResult Submit(OnlineOrder order)
483        {
484            if (ModelState.IsValid)
485            {
486                // Create a message from the order
487                var message = new BrokeredMessage(order);
488                
489                // Submit the order
490                QueueConnector.OrdersQueueClient.Send(message);
491                return RedirectToAction("Submit");
492            }
493            else
494            {
495                return View(order);
496            }
497        }
498
4999.  You can now run your application again. Each time you submit an
500    order, the message count increases.
501
502    ![][18]
503
504<h2><span class="short-header">Configuration manager</span>Cloud configuration manager</h2>
505
506Azure 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.
507
508### Connection string
509
510To 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:
511
512	<ConfigurationSettings>
513    ...
514    	<Setting name="Microsoft.ServiceBus.ConnectionString" value="Endpoint=sb://[yourServiceNamespace].servicebus.windows.net/;SharedSecretIssuer=[issuerName];SharedSecretValue=[yourDefaultKey]" />
515	</ConfigurationSettings>
516
517The following code retrieves the connection string, creates a queue, and initializes the connection to the queue:
518
519	QueueClient Client; 
520
521	string connectionString =
522     CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ConnectionString");
523	
524    var namespaceManager =
525     NamespaceManager.CreateFromConnectionString(connectionString); 
526
527	if (!namespaceManager.QueueExists(QueueName))
528    {
529        namespaceManager.CreateQueue(QueueName);
530    }
531
532	// Initialize the connection to Service Bus Queue
533	Client = QueueClient.CreateFromConnectionString(connectionString, QueueName);
534
535The code in the following section uses these configuration management APIs.
536
537<h2><span class="short-header">Create worker role</span>Create the worker role</h2>
538
539You will now create the worker role that processes the order
540submissions. 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.
541
5421. 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. 
543
5443. 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.
545
546	![][21]
547
5482. In Server Explorer, expand **Azure**, then right-click **Service Bus**, then click **Add New Connection**.
549
5503. In the **Add Connection** dialog, type the name of the service namespace, the issuer name, and the issuer key. Then click **OK** to connect.
551
552	![][22]
553
5544.  In Visual Studio, in **Solution Explorer** right-click the
555    **Roles** folder under the **MultiTierApp** project.
556
5575.  Click **Add**, and then click **New Worker Role Project**. The **Add New Role Project** dialog appears.
558
559	![][26]
560
5616.  In the **Add New Role Project dialog**, click **Worker Role with Service Bus Queue**, as in the following figure:
562
563	![][23]
564
5657.  In the **Name** box, name the project **OrderProcessingRole**. Then click **Add**.
566
5678.  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.
568
569	![][24]
570
5719.  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**.
572
57310.  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.
574
575	![][25]
576
57711.  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**.
578
57912. Browse to the subfolder for **FrontendWebRole\Models**, and double-click **OnlineOrder.cs** to add it to this project.
580
58113. In WorkerRole.cs, replace the value of the **QueueName** variable in **WorkerRole.cs** from `"ProcessingQueue"` to `"OrdersQueue"` as in the following code:
582
583		// The name of your queue
584		const string QueueName = "OrdersQueue";
585
58614. Add the following using statement at the top of the WorkerRole.cs file:
587
588		using FrontendWebRole.Models;
589
59015. In the `Run()` function, inside the `OnMessage` call, add the following code inside the `try` clause:
591
592		Trace.WriteLine("Processing", receivedMessage.SequenceNumber.ToString());
593		// View the message as an OnlineOrder
594		OnlineOrder order = receivedMessage.GetBody<OnlineOrder>();
595		Trace.WriteLine(order.Customer + ": " + order.Product, "ProcessingMessage");
596		receivedMessage.Complete();
597
59816.  You have completed the application. You can test the full
599    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
600    worker role by viewing the Azure Compute Emulator UI. You
601    can do this by right-clicking the emulator icon in the notification
602    area of your taskbar and selecting **Show Compute Emulator UI**.
603
604    ![][19]
605
606    ![][20]
607
608<h2><a name="nextsteps"></a><span class="short-header">Next steps</span>Next steps</h2>  
609
610To learn more about Service Bus, see the following resources:  
611  
612* [Azure Service Bus][sbmsdn]  
613* [Service Bus How To's][sbwacom]  
614* [How to Use Service Bus Queues][sbwacomqhowto]  
615
616To learn more about multi-tier scenarios, or to learn how to deploy an application to a cloud service, see:  
617
618* [.NET Multi-Tier Application Using Storage Tables, Queues, and Blobs][mutitierstorage]  
619
620You 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].
621
622To 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:
623
6241. 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.
625
6262. 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.
627
6283. You can test the front-end and back-end separately, or you can run both simultaneously in separate Visual Studio instances.
629
630To 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].
631
632
633  [0]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-01.png
634  [1]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-100.png
635  [sbqueuecomparison]: http://msdn.microsoft.com/en-us/library/windowsazure/hh767287.aspx
636  [2]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-101.png
637  [Get Tools and SDK]: http://go.microsoft.com/fwlink/?LinkId=271920
638  [3]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-3.png
639  
640  
641  
642  [Azure Management Portal]: http://manage.windowsazure.com
643  [6]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/sb-queues-03.png
644  [7]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/sb-queues-04.png
645  [8]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-09.png
646  [9]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-10.jpg
647  [10]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-11.png
648  [11]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-02.png
649  [12]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-12.png
650  [13]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-13.png
651  [14]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-33.png
652  [15]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-34.png
653  [16]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-35.png
654  [17]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-36.png
655  [18]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-37.png
656  
657  [19]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-38.png
658  [20]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-39.png
659  [21]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/SBExplorer.png
660  [22]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/SBExplorerAddConnect.png
661  [23]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/SBWorkerRole1.png
662  [24]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/SBExplorerProperties.png
663  [25]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/SBWorkerRoleProperties.png
664  [26]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/SBNewWorkerRole.png
665  [27]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-27.png
666  [28]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-multi-tier-40.png
667  [30]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/sb-queues-09.png
668  [31]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/sb-queues-06.png
669  [32]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-41.png
670  [33]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/getting-started-4-2-WebPI.png
671  [34]: ./media/cloud-services-dotnet-multi-tier-app-using-service-bus-queues/VSProperties.png
672  [sbmsdn]: http://msdn.microsoft.com/en-us/library/windowsazure/ee732537.aspx  
673  [sbwacom]: /en-us/documentation/services/service-bus/  
674  [sbwacomqhowto]: /en-us/develop/net/how-to-guides/service-bus-queues/  
675  [mutitierstorage]: /en-us/develop/net/tutorials/multi-tier-web-site/1-overview/ 
676  [executionmodels]: http://www.windowsazure.com/en-us/develop/net/fundamentals/compute/