diff --git a/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/BasicSendReceiveUsingQueueClient/BasicSendReceiveUsingQueueClient.csproj b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/BasicSendReceiveUsingQueueClient/BasicSendReceiveUsingQueueClient.csproj
new file mode 100644
index 0000000..768aae7
--- /dev/null
+++ b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/BasicSendReceiveUsingQueueClient/BasicSendReceiveUsingQueueClient.csproj
@@ -0,0 +1,12 @@
+
+
+
+ Exe
+ netcoreapp2.0
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/BasicSendReceiveUsingQueueClient/Program.cs b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/BasicSendReceiveUsingQueueClient/Program.cs
new file mode 100644
index 0000000..e601a02
--- /dev/null
+++ b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/BasicSendReceiveUsingQueueClient/Program.cs
@@ -0,0 +1,112 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+namespace BasicSendReceiveUsingQueueClient
+{
+ using Microsoft.Azure.ServiceBus;
+ using System;
+ using System.Text;
+ using System.Threading;
+ using System.Threading.Tasks;
+
+ class Program
+ {
+ // Connection String for the namespace can be obtained from the Azure portal under the
+ // 'Shared Access policies' section.
+ const string ServiceBusConnectionString = "{ServiceBus connection string}";
+ const string QueueName = "{Queue Name}";
+ static IQueueClient queueClient;
+
+ static void Main(string[] args)
+ {
+ MainAsync().GetAwaiter().GetResult();
+ }
+
+ static async Task MainAsync()
+ {
+ const int numberOfMessages = 10;
+ queueClient = new QueueClient(ServiceBusConnectionString, QueueName);
+
+ Console.WriteLine("======================================================");
+ Console.WriteLine("Press any key to exit after receiving all the messages.");
+ Console.WriteLine("======================================================");
+
+ // Register QueueClient's MessageHandler and receive messages in a loop
+ RegisterOnMessageHandlerAndReceiveMessages();
+
+ // Send Messages
+ await SendMessagesAsync(numberOfMessages);
+
+ Console.ReadKey();
+
+ await queueClient.CloseAsync();
+ }
+
+ static void RegisterOnMessageHandlerAndReceiveMessages()
+ {
+ // Configure the MessageHandler Options in terms of exception handling, number of concurrent messages to deliver etc.
+ var messageHandlerOptions = new MessageHandlerOptions(ExceptionReceivedHandler)
+ {
+ // Maximum number of Concurrent calls to the callback `ProcessMessagesAsync`, set to 1 for simplicity.
+ // Set it according to how many messages the application wants to process in parallel.
+ MaxConcurrentCalls = 1,
+
+ // Indicates whether MessagePump should automatically complete the messages after returning from User Callback.
+ // False below indicates the Complete will be handled by the User Callback as in `ProcessMessagesAsync` below.
+ AutoComplete = false
+ };
+
+ // Register the function that will process messages
+ queueClient.RegisterMessageHandler(ProcessMessagesAsync, messageHandlerOptions);
+ }
+
+ static async Task ProcessMessagesAsync(Message message, CancellationToken token)
+ {
+ // Process the message
+ Console.WriteLine($"Received message: SequenceNumber:{message.SystemProperties.SequenceNumber} Body:{Encoding.UTF8.GetString(message.Body)}");
+
+ // Complete the message so that it is not received again.
+ // This can be done only if the queueClient is created in ReceiveMode.PeekLock mode (which is default).
+ await queueClient.CompleteAsync(message.SystemProperties.LockToken);
+
+ // Note: Use the cancellationToken passed as necessary to determine if the queueClient has already been closed.
+ // If queueClient has already been Closed, you may chose to not call CompleteAsync() or AbandonAsync() etc. calls
+ // to avoid unnecessary exceptions.
+ }
+
+ // Use this Handler to look at the exceptions received on the MessagePump
+ static Task ExceptionReceivedHandler(ExceptionReceivedEventArgs exceptionReceivedEventArgs)
+ {
+ Console.WriteLine($"Message handler encountered an exception {exceptionReceivedEventArgs.Exception}.");
+ var context = exceptionReceivedEventArgs.ExceptionReceivedContext;
+ Console.WriteLine("Exception context for troubleshooting:");
+ Console.WriteLine($"- Endpoint: {context.Endpoint}");
+ Console.WriteLine($"- Entity Path: {context.EntityPath}");
+ Console.WriteLine($"- Executing Action: {context.Action}");
+ return Task.CompletedTask;
+ }
+
+ static async Task SendMessagesAsync(int numberOfMessagesToSend)
+ {
+ try
+ {
+ for (var i = 0; i < numberOfMessagesToSend; i++)
+ {
+ // Create a new message to send to the queue
+ string messageBody = $"Message {i}";
+ var message = new Message(Encoding.UTF8.GetBytes(messageBody));
+
+ // Write the body of the message to the console
+ Console.WriteLine($"Sending message: {messageBody}");
+
+ // Send the message to the queue
+ await queueClient.SendAsync(message);
+ }
+ }
+ catch (Exception exception)
+ {
+ Console.WriteLine($"{DateTime.Now} :: Exception: {exception.Message}");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/BasicSendReceiveUsingQueueClient/readme.md b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/BasicSendReceiveUsingQueueClient/readme.md
new file mode 100644
index 0000000..c5452ac
--- /dev/null
+++ b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/BasicSendReceiveUsingQueueClient/readme.md
@@ -0,0 +1,171 @@
+# Get started sending and receiving messages from ServiceBus queues using QueueClient
+
+In order to run the sample in this directory, replace the following bracketed values in the `Program.cs` file.
+
+```csharp
+// Connection String for the namespace can be obtained from the Azure portal under the
+// `Shared Access policies` section.
+const string ServiceBusConnectionString = "{ServiceBus connection string}";
+const string QueueName = "{Queue Name}";
+```
+
+Once you replace the above values run the following from a command prompt:
+
+```
+dotnet restore
+dotnet build
+dotnet run
+```
+
+## The Sample Program
+To keep things reasonably simple, the sample program keeps send and receive code within a single hosting application.
+Typically in real world applications these roles are often spread across applications, services, or at least across
+independently deployed and run tiers of applications or services. For clarity, the send and receive activities are kept as
+separate methods as if they were different apps.
+
+For further information on how to create this sample on your own, follow the rest of the tutorial.
+
+## What will be accomplished
+In this tutorial, we will write a console application to send and receive messages to a ServiceBus queue using a QueueClient.
+QueueClient offers a simple API surface to send message(or messages in a batch) and offers a simple MessagePump model to receive messages.
+Once a message process handler is registered as shown below, the User code does not have to write explicit code to receive messages and
+if configured using `MessageHandlerOptions`, does not have to write explicit code to renew message locks or complete messages or improve
+the degree of concurrency of message processing. Hence the queueClient can be used in scenarios where the User wants to get started
+quickly or the scenarios where they need basic send/receive and wants to achieve that with as little code writing as possible.
+
+## Prerequisites
+1. [.NET Core](https://www.microsoft.com/net/core)
+2. An Azure subscription.
+3. [A ServiceBus namespace](https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-create-namespace-portal)
+4. [A ServiceBus queue](https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-dotnet-get-started-with-queues#2-create-a-queue-using-the-azure-portal)
+
+### Create a console application
+
+- Create a new .NET Core application. Check out [this link](https://docs.microsoft.com/en-us/dotnet/articles/core/getting-started) with help to create a new application on your operating system.
+
+### Add the ServiceBus client reference
+
+1. Add the following to your project.json, making sure that the solution references the `Microsoft.Azure.ServiceBus` project.
+
+ ```json
+ "Microsoft.Azure.ServiceBus": "1.0.0"
+ ```
+
+### Write some code to send and receive messages from the queue
+1. Add the following using statement to the top of the Program.cs file.
+
+ ```csharp
+ using Microsoft.Azure.ServiceBus;
+ ```
+
+1. Add the following variables to the `Program` class, and replace the placeholder values:
+
+ ```csharp
+ const string ServiceBusConnectionString = "{Service Bus connection string}";
+ const string QueueName = "{Queue Name}";
+ static IQueueClient queueClient;
+ ```
+
+1. Create a new Task called `ProcessMessagesAsync` that knows how to handle received messages with the following code:
+
+ ```csharp
+ static async Task ProcessMessagesAsync(Message message, CancellationToken token)
+ {
+ // Process the message
+ Console.WriteLine($"Received message: SequenceNumber:{message.SystemProperties.SequenceNumber} Body:{Encoding.UTF8.GetString(message.Body)}");
+
+ // Complete the message so that it is not received again.
+ // This can be done only if the queueClient is opened in ReceiveMode.PeekLock mode (which is default).
+ await queueClient.CompleteAsync(message.SystemProperties.LockToken);
+ }
+ ```
+
+1. Create a new Task called `ExceptionReceivedHandler` to look at the exceptions received on the MessagePump. This will be useful for debugging purposes.
+
+ ```csharp
+ // Use this Handler to look at the exceptions received on the MessagePump
+ static Task ExceptionReceivedHandler(ExceptionReceivedEventArgs exceptionReceivedEventArgs)
+ {
+ Console.WriteLine($"Message handler encountered an exception {exceptionReceivedEventArgs.Exception}.");
+ return Task.CompletedTask;
+ }
+ ```
+
+1. Create a new method called 'RegisterOnMessageHandlerAndReceiveMessages' to register the `ProcessMessagesAsync` and the
+`ExceptionReceivedHandler` with the necessary `MessageHandlerOptions` parameters to start receiving messages
+
+ ```csharp
+ static void RegisterOnMessageHandlerAndReceiveMessages()
+ {
+ // Configure the MessageHandler Options in terms of exception handling, number of concurrent messages to deliver etc.
+ var messageHandlerOptions = new MessageHandlerOptions(ExceptionReceivedHandler)
+ {
+ // Maximum number of Concurrent calls to the callback `ProcessMessagesAsync`, set to 1 for simplicity.
+ // Set it according to how many messages the application wants to process in parallel.
+ MaxConcurrentCalls = 1,
+
+ // Indicates whether MessagePump should automatically complete the messages after returning from User Callback.
+ // False value below indicates the Complete will be handled by the User Callback as seen in `ProcessMessagesAsync`.
+ AutoComplete = false
+ };
+
+ // Register the function that will process messages
+ queueClient.RegisterMessageHandler(ProcessMessagesAsync, messageHandlerOptions);
+ }
+ ```
+
+1. Create a new method called `SendMessagesAsync` with the following code:
+
+ ```csharp
+ // Sends messages to the queue.
+ static async Task SendMessagesAsync(int numberOfMessagesToSend)
+ {
+ for (var i = 0; i < numberOfMessagesToSend; i++)
+ {
+ try
+ {
+ // Create a new message to send to the queue
+ string messageBody = $"Message {i}";
+ var message = new Message(Encoding.UTF8.GetBytes(messageBody));
+
+ // Write the body of the message to the console
+ Console.WriteLine($"Sending message: {messageBody}");
+
+ // Send the message to the queue
+ await queueClient.SendAsync(message);
+ }
+ catch (Exception exception)
+ {
+ Console.WriteLine($"{DateTime.Now} :: Exception: {exception.Message}");
+ }
+ }
+ }
+ ```
+
+1. Create a new method called `MainAsync` with the following code:
+
+ ```csharp
+ static async Task MainAsync(string[] args)
+ {
+ queueClient = new QueueClient(ServiceBusConnectionString, QueueName);
+
+ // Register QueueClient's MessageHandler and receive messages in a loop
+ RegisterOnMessageHandlerAndReceiveMessages();
+
+ // Send Messages
+ await SendMessagesToQueue(10);
+
+ Console.WriteLine("Press any key to exit after receiving all the messages.");
+ Console.ReadKey();
+
+ await queueClient.CloseAsync();
+ }
+ ```
+
+1. Add the following code to the `Main` method:
+
+ ```csharp
+ MainAsync(args).GetAwaiter().GetResult();
+ ```
+
+Congratulations! You have now sent and received messages to a ServiceBus queue, using QueueClient.
diff --git a/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/BasicSendReceiveUsingTopicSubscriptionClient/BasicSendReceiveUsingTopicSubscriptionClient.csproj b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/BasicSendReceiveUsingTopicSubscriptionClient/BasicSendReceiveUsingTopicSubscriptionClient.csproj
new file mode 100644
index 0000000..768aae7
--- /dev/null
+++ b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/BasicSendReceiveUsingTopicSubscriptionClient/BasicSendReceiveUsingTopicSubscriptionClient.csproj
@@ -0,0 +1,12 @@
+
+
+
+ Exe
+ netcoreapp2.0
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/BasicSendReceiveUsingTopicSubscriptionClient/Program.cs b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/BasicSendReceiveUsingTopicSubscriptionClient/Program.cs
new file mode 100644
index 0000000..6d7c742
--- /dev/null
+++ b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/BasicSendReceiveUsingTopicSubscriptionClient/Program.cs
@@ -0,0 +1,116 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+namespace BasicSendReceiveUsingTopicSubscriptionClient
+{
+ using Microsoft.Azure.ServiceBus;
+ using System;
+ using System.Text;
+ using System.Threading;
+ using System.Threading.Tasks;
+
+ class Program
+ {
+ // Connection String for the namespace can be obtained from the Azure portal under the
+ // 'Shared Access policies' section.
+ const string ServiceBusConnectionString = "{ServiceBus connection string}";
+ const string TopicName = "{Topic Name}";
+ const string SubscriptionName = "{Subscription Name}";
+ static ITopicClient topicClient;
+ static ISubscriptionClient subscriptionClient;
+
+ static void Main(string[] args)
+ {
+ MainAsync().GetAwaiter().GetResult();
+ }
+
+ static async Task MainAsync()
+ {
+ const int numberOfMessages = 10;
+ topicClient = new TopicClient(ServiceBusConnectionString, TopicName);
+ subscriptionClient = new SubscriptionClient(ServiceBusConnectionString, TopicName, SubscriptionName);
+
+ Console.WriteLine("======================================================");
+ Console.WriteLine("Press any key to exit after receiving all the messages.");
+ Console.WriteLine("======================================================");
+
+ // Register Subscription's MessageHandler and receive messages in a loop
+ RegisterOnMessageHandlerAndReceiveMessages();
+
+ // Send Messages
+ await SendMessagesAsync(numberOfMessages);
+
+ Console.ReadKey();
+
+ await subscriptionClient.CloseAsync();
+ await topicClient.CloseAsync();
+ }
+
+ static void RegisterOnMessageHandlerAndReceiveMessages()
+ {
+ // Configure the MessageHandler Options in terms of exception handling, number of concurrent messages to deliver etc.
+ var messageHandlerOptions = new MessageHandlerOptions(ExceptionReceivedHandler)
+ {
+ // Maximum number of Concurrent calls to the callback `ProcessMessagesAsync`, set to 1 for simplicity.
+ // Set it according to how many messages the application wants to process in parallel.
+ MaxConcurrentCalls = 1,
+
+ // Indicates whether MessagePump should automatically complete the messages after returning from User Callback.
+ // False below indicates the Complete will be handled by the User Callback as in `ProcessMessagesAsync` below.
+ AutoComplete = false
+ };
+
+ // Register the function that will process messages
+ subscriptionClient.RegisterMessageHandler(ProcessMessagesAsync, messageHandlerOptions);
+ }
+
+ static async Task ProcessMessagesAsync(Message message, CancellationToken token)
+ {
+ // Process the message
+ Console.WriteLine($"Received message: SequenceNumber:{message.SystemProperties.SequenceNumber} Body:{Encoding.UTF8.GetString(message.Body)}");
+
+ // Complete the message so that it is not received again.
+ // This can be done only if the subscriptionClient is created in ReceiveMode.PeekLock mode (which is default).
+ await subscriptionClient.CompleteAsync(message.SystemProperties.LockToken);
+
+ // Note: Use the cancellationToken passed as necessary to determine if the subscriptionClient has already been closed.
+ // If subscriptionClient has already been Closed, you may chose to not call CompleteAsync() or AbandonAsync() etc. calls
+ // to avoid unnecessary exceptions.
+ }
+
+ // Use this Handler to look at the exceptions received on the MessagePump
+ static Task ExceptionReceivedHandler(ExceptionReceivedEventArgs exceptionReceivedEventArgs)
+ {
+ Console.WriteLine($"Message handler encountered an exception {exceptionReceivedEventArgs.Exception}.");
+ var context = exceptionReceivedEventArgs.ExceptionReceivedContext;
+ Console.WriteLine("Exception context for troubleshooting:");
+ Console.WriteLine($"- Endpoint: {context.Endpoint}");
+ Console.WriteLine($"- Entity Path: {context.EntityPath}");
+ Console.WriteLine($"- Executing Action: {context.Action}");
+ return Task.CompletedTask;
+ }
+
+ static async Task SendMessagesAsync(int numberOfMessagesToSend)
+ {
+ try
+ {
+ for (var i = 0; i < numberOfMessagesToSend; i++)
+ {
+ // Create a new message to send to the topic
+ string messageBody = $"Message {i}";
+ var message = new Message(Encoding.UTF8.GetBytes(messageBody));
+
+ // Write the body of the message to the console
+ Console.WriteLine($"Sending message: {messageBody}");
+
+ // Send the message to the topic
+ await topicClient.SendAsync(message);
+ }
+ }
+ catch (Exception exception)
+ {
+ Console.WriteLine($"{DateTime.Now} :: Exception: {exception.Message}");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/BasicSendReceiveUsingTopicSubscriptionClient/readme.md b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/BasicSendReceiveUsingTopicSubscriptionClient/readme.md
new file mode 100644
index 0000000..ee8eef3
--- /dev/null
+++ b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/BasicSendReceiveUsingTopicSubscriptionClient/readme.md
@@ -0,0 +1,185 @@
+# Get started sending messages to a topic using topicClient and receiving those messages from Subscription using SubscriptionClient
+
+In order to run the sample in this directory, replace the following bracketed values in the `Program.cs` file.
+
+```csharp
+// Connection String for the namespace can be obtained from the Azure portal under the
+// `Shared Access policies` section.
+const string ServiceBusConnectionString = "{Service Bus connection string}";
+const string TopicName = "{Topic Name}";
+const string SubscriptionName = "{Subscription Name}";
+```
+
+Once you replace the above values run the following from a command prompt:
+
+```
+dotnet restore
+dotnet build
+dotnet run
+```
+
+## The Sample Program
+To keep things reasonably simple, the sample program keeps send and receive code within a single hosting application.
+Typically in real world applications these roles are often spread across applications, services, or at least across
+independently deployed and run tiers of applications or services. For clarity, the send and receive activities are kept as
+separate methods as if they were different apps.
+
+For further information on how to create this sample on your own, follow the rest of the tutorial.
+
+## What will be accomplished
+Topics are similar to Queues for the send side of the application. However unlike Queues, Topic can have zero or more subscriptions,
+from which messages can be retrieved and each of subscription act like independent queues. Whether a message is selected into the
+subscription is determined by the Filter condition for the subscription.
+
+In this tutorial, we will write a console application to send messages to the topic using topicClient and receive those messages using
+SubscriptionClient. TopicClient offers a simple API surface to send message(or messages in a batch). SubscriptionClient offers a simple
+MessagePump model to receive messages. TopicClient cannot be used to receive messages and SubscriptionClient cannot be used to send messages.
+Once a message process handler is registered as shown below, the User code does not have to write explicit code to receive messages and if
+configured using `MessageHandlerOptions`, does not have to write explicit code to renew message locks or complete messages or improve the
+degree of concurrency of message processing. Hence the Subscriptionclient can be used in scenarios where the User wants to get started
+quickly or the scenarios where they need basic send/receive and wants to achieve that with as little code writing as possible.
+
+## Prerequisites
+1. [.NET Core](https://www.microsoft.com/net/core)
+2. An Azure subscription.
+3. [A ServiceBus namespace](https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-create-namespace-portal)
+4. [A ServiceBus Topic](https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-dotnet-how-to-use-topics-subscriptions#2-create-a-topic-using-the-azure-portal)
+5. [A ServiceBus Subscription](https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-dotnet-how-to-use-topics-subscriptions)
+
+### Create a console application
+
+- Create a new .NET Core application. Check out [this link](https://docs.microsoft.com/en-us/dotnet/articles/core/getting-started) with help to create a new application on your operating system.
+
+### Add the ServiceBus client reference
+
+1. Add the following to your project.json, making sure that the solution references the `Microsoft.Azure.ServiceBus` project.
+
+ ```json
+ "Microsoft.Azure.ServiceBus": "1.0.0"
+ ```
+
+### Write some code to send messages to the topic and receive messages from the subscription
+1. Add the following using statement to the top of the Program.cs file.
+
+ ```csharp
+ using Microsoft.Azure.ServiceBus;
+ ```
+
+1. Add the following variables to the `Program` class, and replace the placeholder values:
+
+ ```csharp
+ const string ServiceBusConnectionString = "{Service Bus connection string}";
+ const string TopicName = "{Topic Name}";
+ const string SubscriptionName = "{Subscription Name}";
+ static ITopicClient topicClient;
+ static ISubscriptionClient subscriptionClient;
+ ```
+
+1. Create a new Task called `ProcessMessagesAsync` that knows how to handle received messages with the following code:
+
+ ```csharp
+ static async Task ProcessMessagesAsync(Message message, CancellationToken token)
+ {
+ // Process the message
+ Console.WriteLine($"Received message: SequenceNumber:{message.SystemProperties.SequenceNumber} Body:{Encoding.UTF8.GetString(message.Body)}");
+
+ // Complete the message so that it is not received again.
+ // This can be done only if the subscriptionClient is opened in ReceiveMode.PeekLock mode (which is default).
+ await subscriptionClient.CompleteAsync(message.SystemProperties.LockToken);
+ }
+ ```
+
+1. Create a new Task called `ExceptionReceivedHandler` to look at the exceptions received on the MessagePump. This will be useful for debugging purposes.
+
+ ```csharp
+ // Use this Handler to look at the exceptions received on the MessagePump
+ static Task ExceptionReceivedHandler(ExceptionReceivedEventArgs exceptionReceivedEventArgs)
+ {
+ Console.WriteLine($"Message handler encountered an exception {exceptionReceivedEventArgs.Exception}.");
+ return Task.CompletedTask;
+ }
+ ```
+
+1. Create a new method called 'RegisterOnMessageHandlerAndReceiveMessages' to register the `ProcessMessagesAsync` and the
+`ExceptionReceivedHandler` with the necessary `MessageHandlerOptions` parameters to start receiving messages
+
+ ```csharp
+ static void RegisterOnMessageHandlerAndReceiveMessages()
+ {
+ // Configure the MessageHandler Options in terms of exception handling, number of concurrent messages to deliver etc.
+ var messageHandlerOptions = new MessageHandlerOptions(ExceptionReceivedHandler)
+ {
+ // Maximum number of Concurrent calls to the callback `ProcessMessagesAsync`, set to 1 for simplicity.
+ // Set it according to how many messages the application wants to process in parallel.
+ MaxConcurrentCalls = 1,
+
+ // Indicates whether MessagePump should automatically complete the messages after returning from User Callback.
+ // False below indicates the Complete will be handled by the User Callback as in `ProcessMessagesAsync` below.
+ AutoComplete = false
+ };
+
+ // Register the function that will process messages
+ subscriptionClient.RegisterMessageHandler(ProcessMessagesAsync, messageHandlerOptions);
+ }
+ ```
+
+1. Create a new method called `SendMessagesAsync` with the following code:
+
+ ```csharp
+ static async Task SendMessagesAsync(int numberOfMessagesToSend)
+ {
+ for (var i = 0; i < numberOfMessagesToSend; i++)
+ {
+ try
+ {
+ // Create a new message to send to the topic
+ string messageBody = $"Message {i}";
+ var message = new Message(Encoding.UTF8.GetBytes(messageBody));
+
+ // Write the body of the message to the console
+ Console.WriteLine($"Sending message: {messageBody}");
+
+ // Send the message to the topic
+ await topicClient.SendAsync(message);
+ }
+ catch (Exception exception)
+ {
+ Console.WriteLine($"{DateTime.Now} :: Exception: {exception.Message}");
+ }
+ }
+ }
+ ```
+
+1. Create a new method called `MainAsync` with the following code:
+
+ ```csharp
+ static async Task MainAsync(string[] args)
+ {
+ const int numberOfMessages = 10;
+ topicClient = new TopicClient(ServiceBusConnectionString, TopicName);
+ subscriptionClient = new SubscriptionClient(ServiceBusConnectionString, TopicName, SubscriptionName);
+
+ Console.WriteLine("======================================================");
+ Console.WriteLine("Press any key to exit after receiving all the messages.");
+ Console.WriteLine("======================================================");
+
+ // Register Subscription's MessageHandler and receive messages in a loop
+ RegisterOnMessageHandlerAndReceiveMessages();
+
+ // Send Messages
+ await SendMessagesAsync(numberOfMessages);
+
+ Console.ReadKey();
+
+ await subscriptionClient.CloseAsync();
+ await topicClient.CloseAsync();
+ }
+ ```
+
+1. Add the following code to the `Main` method:
+
+ ```csharp
+ MainAsync(args).GetAwaiter().GetResult();
+ ```
+
+Congratulations! You have now sent messages to a ServiceBus Topic and received messages from a ServiceBus Subscription.
diff --git a/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/BasicSessionSendReceiveUsingQueueClient/BasicSessionSendReceiveUsingQueueClient.csproj b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/BasicSessionSendReceiveUsingQueueClient/BasicSessionSendReceiveUsingQueueClient.csproj
new file mode 100644
index 0000000..768aae7
--- /dev/null
+++ b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/BasicSessionSendReceiveUsingQueueClient/BasicSessionSendReceiveUsingQueueClient.csproj
@@ -0,0 +1,12 @@
+
+
+
+ Exe
+ netcoreapp2.0
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/BasicSessionSendReceiveUsingQueueClient/Program.cs b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/BasicSessionSendReceiveUsingQueueClient/Program.cs
new file mode 100644
index 0000000..aa629c1
--- /dev/null
+++ b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/BasicSessionSendReceiveUsingQueueClient/Program.cs
@@ -0,0 +1,134 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+namespace BasicSessionSendReceiveUsingQueueClient
+{
+ using Microsoft.Azure.ServiceBus;
+ using System;
+ using System.Collections.Generic;
+ using System.Text;
+ using System.Threading;
+ using System.Threading.Tasks;
+
+ class Program
+ {
+ // Connection String for the namespace can be obtained from the Azure portal under the
+ // 'Shared Access policies' section.
+ const string ServiceBusConnectionString = "{ServiceBus connection string}";
+ const string QueueName = "{Queue Name of a Queue that supports sessions}";
+ static IQueueClient queueClient;
+
+ static void Main(string[] args)
+ {
+ MainAsync().GetAwaiter().GetResult();
+ }
+
+ static async Task MainAsync()
+ {
+ const int numberOfSessions = 5;
+ const int numberOfMessagesPerSession = 3;
+
+ queueClient = new QueueClient(ServiceBusConnectionString, QueueName);
+
+ Console.WriteLine("======================================================");
+ Console.WriteLine("Press any key to exit after receiving all the messages.");
+ Console.WriteLine("======================================================");
+
+ // Register Session Handler and Receive Session Messages
+ RegisterOnSessionHandlerAndReceiveSessionMessages();
+
+ // Send messages with sessionId set
+ await SendSessionMessagesAsync(numberOfSessions, numberOfMessagesPerSession);
+
+ Console.ReadKey();
+
+ await queueClient.CloseAsync();
+ }
+
+ static void RegisterOnSessionHandlerAndReceiveSessionMessages()
+ {
+ // Configure the SessionHandler Options in terms of exception handling, number of concurrent sessions to deliver etc.
+ var sessionHandlerOptions =
+ new SessionHandlerOptions(ExceptionReceivedHandler)
+ {
+ // Maximum number of Concurrent calls to the callback `ProcessSessionMessagesAsync`
+ // Value 2 below indicates the callback can be called with a message for 2 unique
+ // session Id's in parallel. Set it according to how many messages the application
+ // wants to process in parallel.
+ MaxConcurrentSessions = 2,
+
+ // Indicates the maximum time the Session Pump should wait for receiving messages for sessions.
+ // If no message is received within the specified time, the pump will close that session and try to get messages
+ // from a different session. Default is to wait for 1 minute to fetch messages for a session. Set to a 1 second
+ // value here to allow the sample execution to finish fast but ideally leave this as 1 minute unless there
+ // is a specific reason to timeout earlier.
+ MessageWaitTimeout = TimeSpan.FromSeconds(1),
+
+ // Indicates whether SessionPump should automatically complete the messages after returning from User Callback.
+ // False below indicates the Complete will be handled by the User Callback as in `ProcessSessionMessagesAsync`.
+ AutoComplete = false
+ };
+
+ // Register the function that will process session messages
+ queueClient.RegisterSessionHandler(ProcessSessionMessagesAsync, sessionHandlerOptions);
+ }
+
+ static async Task ProcessSessionMessagesAsync(IMessageSession session, Message message, CancellationToken token)
+ {
+ Console.WriteLine($"Received Session: {session.SessionId} message: SequenceNumber: {message.SystemProperties.SequenceNumber} Body:{Encoding.UTF8.GetString(message.Body)}");
+
+ // Complete the message so that it is not received again.
+ // This can be done only if the queueClient is created in ReceiveMode.PeekLock mode (which is default).
+ await session.CompleteAsync(message.SystemProperties.LockToken);
+
+ // Note: Use the cancellationToken passed as necessary to determine if the queueClient has already been closed.
+ // If queueClient has already been Closed, you may chose to not call CompleteAsync() or AbandonAsync() etc. calls
+ // to avoid unnecessary exceptions.
+ }
+
+ // Use this Handler to look at the exceptions received on the SessionPump
+ static Task ExceptionReceivedHandler(ExceptionReceivedEventArgs exceptionReceivedEventArgs)
+ {
+ Console.WriteLine($"Message handler encountered an exception {exceptionReceivedEventArgs.Exception}.");
+ var context = exceptionReceivedEventArgs.ExceptionReceivedContext;
+ Console.WriteLine("Exception context for troubleshooting:");
+ Console.WriteLine($"- Endpoint: {context.Endpoint}");
+ Console.WriteLine($"- Entity Path: {context.EntityPath}");
+ Console.WriteLine($"- Executing Action: {context.Action}");
+ return Task.CompletedTask;
+ }
+
+ static async Task SendSessionMessagesAsync(int numberOfSessions, int messagesPerSession)
+ {
+ const string SessionPrefix = "session";
+
+ if (numberOfSessions == 0 || messagesPerSession == 0)
+ {
+ await Task.FromResult(false);
+ }
+
+ for (int i = 0; i < numberOfSessions; i++)
+ {
+ var messagesToSend = new List();
+ string sessionId = SessionPrefix + i;
+ for (int j = 0; j < messagesPerSession; j++)
+ {
+ // Create a new message to send to the queue
+ string messageBody = "test" + j;
+ var message = new Message(Encoding.UTF8.GetBytes(messageBody));
+ // Assign a SessionId for the message
+ message.SessionId = sessionId;
+ messagesToSend.Add(message);
+
+ // Write the sessionId, body of the message to the console
+ Console.WriteLine($"Sending SessionId: {message.SessionId}, message: {messageBody}");
+ }
+
+ // Send a batch of messages corresponding to this sessionId to the queue
+ await queueClient.SendAsync(messagesToSend);
+ }
+
+ Console.WriteLine($"Sent {messagesPerSession} messages each for {numberOfSessions} sessions.");
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/BasicSessionSendReceiveUsingQueueClient/readme.md b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/BasicSessionSendReceiveUsingQueueClient/readme.md
new file mode 100644
index 0000000..a5a4448
--- /dev/null
+++ b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/BasicSessionSendReceiveUsingQueueClient/readme.md
@@ -0,0 +1,201 @@
+# Get started sending and receiving session based messages from Service Bus queues using QueueClient
+
+In order to run the sample in this directory, replace the following bracketed values in the `Program.cs` file.
+
+```csharp
+// Connection String for the namespace can be obtained from the Azure portal under the
+// `Shared Access policies` section.
+const string ServiceBusConnectionString = "{Service Bus connection string}";
+const string QueueName = "{Queue Name of a Queue that supports sessions}";
+```
+
+Once you replace the above values run the following from a command prompt:
+
+```
+dotnet restore
+dotnet build
+dotnet run
+```
+
+## The Sample Program
+To keep things reasonably simple, the sample program keeps send and receive code within a single hosting application.
+Typically in real world applications these roles are often spread across applications, services, or at least across
+independently deployed and run tiers of applications or services. For clarity, the send and receive activities are kept as
+separate methods as if they were different apps.
+
+For further information on how to create this sample on your own, follow the rest of the tutorial.
+
+## What will be accomplished
+In this tutorial, we will write a console application to send and receive sessionful messages to a ServiceBus queue using a QueueClient.
+Sessions are used in scenarios where User requires unbounded sequences of related messages. Messages within a session are always delivered
+in a First In First Out Order. Sending session based messages to a queue using QueueClient is same as sending other messages but the
+messages are stamped with an additional `SessionId` property. QueueClient offers a simple SessionPump model to receive messages related
+to a session. Once a session handler is registered as shown below, the User code does not have to write explicit code to receive sessions
+and if configured using `SessionHandlerOptions`, does not have to write explicit code to renew session locks or complete messages or improve
+the degree of concurrency of session processing. Hence the queueClient can be used in scenarios where the User wants to get started quickly
+or the scenarios where they need basic session based send/receive and wants to achieve that with as little code writing as possible.
+
+## Prerequisites
+1. [.NET Core](https://www.microsoft.com/net/core)
+2. An Azure subscription.
+3. [A ServiceBus namespace](https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-create-namespace-portal)
+4. [A ServiceBus queue](https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-dotnet-get-started-with-queues#2-create-a-queue-using-the-azure-portal)
+
+### Create a console application
+
+- Create a new .NET Core application. Check out [this link](https://docs.microsoft.com/en-us/dotnet/articles/core/getting-started) with help to create a new application on your operating system.
+
+### Add the ServiceBus client reference
+
+1. Add the following to your project.json, making sure that the solution references the `Microsoft.Azure.ServiceBus` project.
+
+ ```json
+ "Microsoft.Azure.ServiceBus": "1.0.0"
+ ```
+
+### Write some code to send and receive messages from the queue
+1. Add the following using statement to the top of the Program.cs file.
+
+ ```csharp
+ using Microsoft.Azure.ServiceBus;
+ ```
+
+1. Add the following variables to the `Program` class, and replace the placeholder values:
+
+ ```csharp
+ const string ServiceBusConnectionString = "{Service Bus connection string}";
+ const string QueueName = "{Queue Name of a Queue that supports sessions}";
+ static IQueueClient queueClient;
+ ```
+
+1. Create a new Task called `ProcessSessionMessagesAsync` that knows how to handle received messages from a session with the following code:
+
+ ```csharp
+ static async Task ProcessSessionMessagesAsync(IMessageSession session, Message message, CancellationToken token)
+ {
+ Console.WriteLine($"Received Session: {session.SessionId} message: SequenceNumber: {message.SystemProperties.SequenceNumber} Body:{Encoding.UTF8.GetString(message.Body)}");
+
+ // Complete the message so that it is not received again.
+ // This can be done only if the queueClient is created in ReceiveMode.PeekLock mode (which is default).
+ await session.CompleteAsync(message.SystemProperties.LockToken);
+
+ // Note: Use the cancellationToken passed as necessary to determine if the queueClient has already been closed.
+ // If queueClient has already been Closed, you may chose to not call CompleteAsync() or AbandonAsync() etc. calls
+ // to avoid unnecessary exceptions.
+ }
+ ```
+
+1. Create a new Task called `ExceptionReceivedHandler` to look at the exceptions received on the MessagePump. This will be useful for debugging purposes.
+
+ ```csharp
+ // Use this Handler to look at the exceptions received on the SessionPump
+ static Task ExceptionReceivedHandler(ExceptionReceivedEventArgs exceptionReceivedEventArgs)
+ {
+ Console.WriteLine($"Message handler encountered an exception {exceptionReceivedEventArgs.Exception}.");
+ return Task.CompletedTask;
+ }
+ ```
+
+1. Create a new method called 'RegisterOnSessionHandlerAndReceiveSessionMessages' to register the `ProcessSessionMessagesAsync` and the
+`ExceptionReceivedHandler` with the necessary `SessionHandlerOptions` parameters to start receiving messages from sessions
+
+ ```csharp
+ static void RegisterOnSessionHandlerAndReceiveSessionMessages()
+ {
+ // Configure the SessionHandler Options in terms of exception handling, number of concurrent sessions to deliver etc.
+ var sessionHandlerOptions =
+ new SessionHandlerOptions(ExceptionReceivedHandler)
+ {
+ // Maximum number of Concurrent calls to the callback `ProcessSessionMessagesAsync`
+ // Value 2 below indicates the callback can be called with a message for 2 unique
+ // session Id's in parallel. Set it according to how many messages the application
+ // wants to process in parallel.
+ MaxConcurrentSessions = 2,
+
+ // Indicates the maximum time the Session Pump should wait for receiving messages for sessions.
+ // If no message is received within the specified time, the pump will close that session and try to get messages
+ // from a different session. Default is to wait for 1 minute to fetch messages for a session. Set to a 1 second
+ // value here to allow the sample execution to finish fast but ideally leave this as 1 minute unless there
+ // is a specific reason to timeout earlier.
+ MessageWaitTimeout = TimeSpan.FromSeconds(1),
+
+ // Indicates whether SessionPump should automatically complete the messages after returning from User Callback.
+ // False below indicates the Complete will be handled by the User Callback as in `ProcessSessionMessagesAsync`.
+ AutoComplete = false
+ };
+
+ // Register the function that will process session messages
+ queueClient.RegisterSessionHandler(ProcessSessionMessagesAsync, sessionHandlerOptions);
+ }
+ ```
+
+1. Create a new method called `SendSessionMessagesAsync` that sends sessionful messages to the queue with the following code:
+
+ ```csharp
+ static async Task SendSessionMessagesAsync(int numberOfSessions, int messagesPerSession)
+ {
+ const string SessionPrefix = "session";
+
+ if (numberOfSessions == 0 || messagesPerSession == 0)
+ {
+ await Task.FromResult(false);
+ }
+
+ for (int i = 0; i < numberOfSessions; i++)
+ {
+ var messagesToSend = new List();
+ string sessionId = SessionPrefix + i;
+ for (int j = 0; j < messagesPerSession; j++)
+ {
+ // Create a new message to send to the queue
+ string messageBody = "test" + j;
+ var message = new Message(Encoding.UTF8.GetBytes(messageBody));
+ // Assign a SessionId for the message
+ message.SessionId = sessionId;
+ messagesToSend.Add(message);
+
+ // Write the sessionId, body of the message to the console
+ Console.WriteLine($"Sending SessionId: {message.SessionId}, message: {messageBody}");
+ }
+
+ // Send a batch of messages corresponding to this sessionId to the queue
+ await queueClient.SendAsync(messagesToSend);
+ }
+
+ Console.WriteLine($"Sent {messagesPerSession} messages each for {numberOfSessions} sessions.");
+ }
+ ```
+
+1. Create a new method called `MainAsync` with the following code:
+
+ ```csharp
+ static async Task MainAsync(string[] args)
+ {
+ const int numberOfSessions = 5;
+ const int numberOfMessagesPerSession = 3;
+
+ queueClient = new QueueClient(ServiceBusConnectionString, QueueName);
+
+ Console.WriteLine("======================================================");
+ Console.WriteLine("Press any key to exit after receiving all the messages.");
+ Console.WriteLine("======================================================");
+
+ // Register Session Handler and Receive Session Messages
+ RegisterOnSessionHandlerAndReceiveSessionMessages();
+
+ // Send messages with sessionId set
+ await SendSessionMessagesAsync(numberOfSessions, numberOfMessagesPerSession);
+
+ Console.ReadKey();
+
+ await queueClient.CloseAsync();
+ }
+ ```
+
+1. Add the following code to the `Main` method:
+
+ ```csharp
+ MainAsync(args).GetAwaiter().GetResult();
+ ```
+
+Congratulations! You have now sent and received session based messages to a ServiceBus queue, using QueueClient.
diff --git a/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/Microsoft.Azure.ServiceBus.Samples.sln b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/Microsoft.Azure.ServiceBus.Samples.sln
new file mode 100644
index 0000000..42ed7a4
--- /dev/null
+++ b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/Microsoft.Azure.ServiceBus.Samples.sln
@@ -0,0 +1,52 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26430.16
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BasicSendReceiveUsingQueueClient", "BasicSendReceiveUsingQueueClient\BasicSendReceiveUsingQueueClient.csproj", "{C7403021-8C99-4FD2-AD6D-943F1ABB439F}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SendReceiveUsingMessageSenderReceiver", "SendReceiveUsingMessageSenderReceiver\SendReceiveUsingMessageSenderReceiver.csproj", "{45D687AA-081B-4D4E-82C3-58A2BD5F02A8}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BasicSessionSendReceiveUsingQueueClient", "BasicSessionSendReceiveUsingQueueClient\BasicSessionSendReceiveUsingQueueClient.csproj", "{3F7B9F6A-0B84-4B4E-A68F-77D4E35EDD57}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SessionSendReceiveUsingSessionClient", "SessionSendReceiveUsingSessionClient\SessionSendReceiveUsingSessionClient.csproj", "{C61629D8-2605-4554-8747-9503572E2B2D}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BasicSendReceiveUsingTopicSubscriptionClient", "BasicSendReceiveUsingTopicSubscriptionClient\BasicSendReceiveUsingTopicSubscriptionClient.csproj", "{BAA95098-988E-48A1-B8B5-5367B7B2A667}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TopicSubscriptionWithRuleOperationsSample", "TopicSubscriptionWithRuleOperationsSample\TopicSubscriptionWithRuleOperationsSample.csproj", "{BCFACFBC-0DFE-4444-8682-AEFA98D1E398}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {C7403021-8C99-4FD2-AD6D-943F1ABB439F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C7403021-8C99-4FD2-AD6D-943F1ABB439F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C7403021-8C99-4FD2-AD6D-943F1ABB439F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C7403021-8C99-4FD2-AD6D-943F1ABB439F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {45D687AA-081B-4D4E-82C3-58A2BD5F02A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {45D687AA-081B-4D4E-82C3-58A2BD5F02A8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {45D687AA-081B-4D4E-82C3-58A2BD5F02A8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {45D687AA-081B-4D4E-82C3-58A2BD5F02A8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3F7B9F6A-0B84-4B4E-A68F-77D4E35EDD57}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3F7B9F6A-0B84-4B4E-A68F-77D4E35EDD57}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3F7B9F6A-0B84-4B4E-A68F-77D4E35EDD57}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3F7B9F6A-0B84-4B4E-A68F-77D4E35EDD57}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C61629D8-2605-4554-8747-9503572E2B2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C61629D8-2605-4554-8747-9503572E2B2D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C61629D8-2605-4554-8747-9503572E2B2D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C61629D8-2605-4554-8747-9503572E2B2D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BAA95098-988E-48A1-B8B5-5367B7B2A667}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BAA95098-988E-48A1-B8B5-5367B7B2A667}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BAA95098-988E-48A1-B8B5-5367B7B2A667}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BAA95098-988E-48A1-B8B5-5367B7B2A667}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BCFACFBC-0DFE-4444-8682-AEFA98D1E398}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BCFACFBC-0DFE-4444-8682-AEFA98D1E398}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BCFACFBC-0DFE-4444-8682-AEFA98D1E398}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BCFACFBC-0DFE-4444-8682-AEFA98D1E398}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/SendReceiveUsingMessageSenderReceiver/Program.cs b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/SendReceiveUsingMessageSenderReceiver/Program.cs
new file mode 100644
index 0000000..9917c58
--- /dev/null
+++ b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/SendReceiveUsingMessageSenderReceiver/Program.cs
@@ -0,0 +1,87 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+namespace SendReceiveUsingMessageSenderReceiver
+{
+ using Microsoft.Azure.ServiceBus;
+ using Microsoft.Azure.ServiceBus.Core;
+ using System;
+ using System.Text;
+ using System.Threading.Tasks;
+
+ class Program
+ {
+ // Connection String for the namespace can be obtained from the Azure portal under the
+ // 'Shared Access policies' section.
+ const string ServiceBusConnectionString = "{ServiceBus connection string}";
+ const string QueueName = "{Queue Name}";
+ static IMessageSender messageSender;
+ static IMessageReceiver messageReceiver;
+
+ static void Main(string[] args)
+ {
+ MainAsync().GetAwaiter().GetResult();
+ }
+
+ static async Task MainAsync()
+ {
+ const int numberOfMessages = 10;
+ messageSender = new MessageSender(ServiceBusConnectionString, QueueName);
+ messageReceiver = new MessageReceiver(ServiceBusConnectionString, QueueName, ReceiveMode.PeekLock);
+
+ // Send Messages
+ await SendMessagesAsync(numberOfMessages);
+
+ // Receive Messages
+ await ReceiveMessagesAsync(numberOfMessages);
+
+ Console.WriteLine("=========================================================");
+ Console.WriteLine("Completed Receiving all messages... Press any key to exit");
+ Console.WriteLine("=========================================================");
+
+ Console.ReadKey();
+
+ await messageSender.CloseAsync();
+ await messageReceiver.CloseAsync();
+ }
+
+ static async Task ReceiveMessagesAsync(int numberOfMessagesToReceive)
+ {
+ while(numberOfMessagesToReceive-- > 0)
+ {
+ // Receive the message
+ Message message = await messageReceiver.ReceiveAsync();
+
+ // Process the message
+ Console.WriteLine($"Received message: SequenceNumber:{message.SystemProperties.SequenceNumber} Body:{Encoding.UTF8.GetString(message.Body)}");
+
+ // Complete the message so that it is not received again.
+ // This can be done only if the MessageReceiver is created in ReceiveMode.PeekLock mode (which is default).
+ await messageReceiver.CompleteAsync(message.SystemProperties.LockToken);
+ }
+ }
+
+ static async Task SendMessagesAsync(int numberOfMessagesToSend)
+ {
+ try
+ {
+ for (var i = 0; i < numberOfMessagesToSend; i++)
+ {
+ // Create a new message to send to the queue
+ string messageBody = $"Message {i}";
+ var message = new Message(Encoding.UTF8.GetBytes(messageBody));
+
+ // Write the body of the message to the console
+ Console.WriteLine($"Sending message: {messageBody}");
+
+ // Send the message to the queue
+ await messageSender.SendAsync(message);
+ }
+ }
+ catch (Exception exception)
+ {
+ Console.WriteLine($"{DateTime.Now} :: Exception: {exception.Message}");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/SendReceiveUsingMessageSenderReceiver/SendReceiveUsingMessageSenderReceiver.csproj b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/SendReceiveUsingMessageSenderReceiver/SendReceiveUsingMessageSenderReceiver.csproj
new file mode 100644
index 0000000..768aae7
--- /dev/null
+++ b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/SendReceiveUsingMessageSenderReceiver/SendReceiveUsingMessageSenderReceiver.csproj
@@ -0,0 +1,12 @@
+
+
+
+ Exe
+ netcoreapp2.0
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/SendReceiveUsingMessageSenderReceiver/readme.md b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/SendReceiveUsingMessageSenderReceiver/readme.md
new file mode 100644
index 0000000..ba7a16c
--- /dev/null
+++ b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/SendReceiveUsingMessageSenderReceiver/readme.md
@@ -0,0 +1,144 @@
+# Get started sending and receiving messages from Service Bus queues using MessageSender and MessageReceiver
+
+In order to run the sample in this directory, replace the following bracketed values in the `Program.cs` file.
+
+```csharp
+// Connection String for the namespace can be obtained from the Azure portal under the
+// `Shared Access policies` section.
+const string ServiceBusConnectionString = "{Service Bus connection string}";
+const string QueueName = "{Queue Name}";
+```
+
+Once you replace the above values run the following from a command prompt:
+
+```
+dotnet restore
+dotnet build
+dotnet run
+```
+
+## The Sample Program
+To keep things reasonably simple, the sample program keeps send and receive code within a single hosting application.
+Typically in real world applications these roles are often spread across applications, services, or at least across
+independently deployed and run tiers of applications or services. For clarity, the send and receive activities are kept as
+separate methods as if they were different apps.
+
+For further information on how to create this sample on your own, follow the rest of the tutorial.
+
+## What will be accomplished
+In this tutorial, we will write a console application to send and receive messages to a ServiceBus queue using MessageSender and MessageReceiver.
+MessageSender and MessageReceiver APIs offer a more richer API surface in terms of being able to Defer Messages, Receive Deferred Messages,
+Peek Messages etc. Thus it allows the User a more granular control on processing of messages than `QueueClient` but that also means the User has
+to write more code to renew message locks, complete messages and define how to achieve a basic degree of concurrency while processing messages.
+
+## Prerequisites
+1. [.NET Core](https://www.microsoft.com/net/core)
+2. An Azure subscription.
+3. [A ServiceBus namespace](https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-create-namespace-portal)
+4. [A ServiceBus queue](https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-dotnet-get-started-with-queues#2-create-a-queue-using-the-azure-portal)
+
+### Create a console application
+
+- Create a new .NET Core application. Check out [this link](https://docs.microsoft.com/en-us/dotnet/articles/core/getting-started) with help to create a new application on your operating system.
+
+### Add the ServiceBus client reference
+
+1. Add the following to your project.json, making sure that the solution references the `Microsoft.Azure.ServiceBus` project.
+
+ ```json
+ "Microsoft.Azure.ServiceBus": "1.0.0"
+ ```
+
+### Write some code to send and receive messages from the queue
+1. Add the following using statement to the top of the Program.cs file.
+
+ ```csharp
+ using Microsoft.Azure.ServiceBus;
+ ```
+
+1. Add the following variables to the `Program` class, and replace the placeholder values:
+
+ ```csharp
+ const string ServiceBusConnectionString = "{Service Bus connection string}";
+ const string QueueName = "{Queue Name}";
+ static IMessageSender messageSender;
+ static IMessageReceiver messageReceiver;
+ ```
+
+1. Create a new Task called `ReceiveMessagesAsync` that knows how to handle received messages with the following code:
+
+ ```csharp
+ static async Task ReceiveMessagesAsync(int numberOfMessagesToReceive)
+ {
+ while(numberOfMessagesToReceive-- > 0)
+ {
+ // Receive the message
+ Message message = await messageReceiver.ReceiveAsync();
+
+ // Process the message
+ Console.WriteLine($"Received message: SequenceNumber:{message.SystemProperties.SequenceNumber} Body:{Encoding.UTF8.GetString(message.Body)}");
+
+ // Complete the message so that it is not received again.
+ // This can be done only if the MessageReceiver is created in ReceiveMode.PeekLock mode (which is default).
+ await messageReceiver.CompleteAsync(message.SystemProperties.LockToken);
+ }
+ }
+ ```
+1. Create a new method called `SendMessagesToQueue` with the following code:
+
+ ```csharp
+ // Sends messages to the queue.
+ static async Task SendMessagesAsync(int numberOfMessagesToSend)
+ {
+ try
+ {
+ for (var i = 0; i < numberOfMessagesToSend; i++)
+ {
+ // Create a new message to send to the queue
+ string messageBody = $"Message {i}";
+ var message = new Message(Encoding.UTF8.GetBytes(messageBody));
+
+ // Write the body of the message to the console
+ Console.WriteLine($"Sending message: {messageBody}");
+
+ // Send the message to the queue
+ await messageSender.SendAsync(message);
+ }
+ }
+ catch (Exception exception)
+ {
+ Console.WriteLine($"{DateTime.Now} :: Exception: {exception.Message}");
+ }
+ }
+ ```
+
+1. Create a new method called `MainAsync` with the following code:
+
+ ```csharp
+ static async Task MainAsync(string[] args)
+ {
+ messageSender = new MessageSender(ServiceBusConnectionString, QueueName);
+ messageReceiver = new MessageReceiver(ServiceBusConnectionString, QueueName, ReceiveMode.PeekLock);
+
+ // Send Messages
+ await SendMessagesToQueue(numberOfMessages);
+
+ // Receive Messages
+ await ReceiveMessagesAsync(numberOfMessages);
+
+ Console.WriteLine("Completed Receiving all messages... Press any key to exit");
+ Console.ReadKey();
+
+ // Close the messageSender and messageReceiver after processing all needed messages.
+ await messageSender.CloseAsync();
+ await messageReceiver.CloseAsync();
+ }
+ ```
+
+1. Add the following code to the `Main` method:
+
+ ```csharp
+ MainAsync(args).GetAwaiter().GetResult();
+ ```
+
+Congratulations! You have now sent and received messages to a ServiceBus queue using MessageSender and MessageReceiver.
diff --git a/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/SessionSendReceiveUsingSessionClient/Program.cs b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/SessionSendReceiveUsingSessionClient/Program.cs
new file mode 100644
index 0000000..83d06c1
--- /dev/null
+++ b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/SessionSendReceiveUsingSessionClient/Program.cs
@@ -0,0 +1,125 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+namespace SessionSendReceiveUsingSessionClient
+{
+ using Microsoft.Azure.ServiceBus;
+ using Microsoft.Azure.ServiceBus.Core;
+ using System;
+ using System.Collections.Generic;
+ using System.Text;
+ using System.Threading.Tasks;
+
+ class Program
+ {
+ // Connection String for the namespace can be obtained from the Azure portal under the
+ // 'Shared Access policies' section.
+ const string ServiceBusConnectionString = "{ServiceBus connection string}";
+ const string QueueName = "{Queue Name of a Queue that supports sessions}";
+ static IMessageSender messageSender;
+ static ISessionClient sessionClient;
+ const string SessionPrefix = "session-prefix";
+
+ static void Main(string[] args)
+ {
+ MainAsync().GetAwaiter().GetResult();
+ }
+
+ static async Task MainAsync()
+ {
+ const int numberOfSessions = 5;
+ const int numberOfMessagesPerSession = 3;
+
+ messageSender = new MessageSender(ServiceBusConnectionString, QueueName);
+ sessionClient = new SessionClient(ServiceBusConnectionString, QueueName);
+
+ // Send messages with sessionId set
+ await SendSessionMessagesAsync(numberOfSessions, numberOfMessagesPerSession);
+
+ // Receive all Session based messages using SessionClient
+ await ReceiveSessionMessagesAsync(numberOfSessions, numberOfMessagesPerSession);
+
+ Console.WriteLine("=========================================================");
+ Console.WriteLine("Completed Receiving all messages... Press any key to exit");
+ Console.WriteLine("=========================================================");
+
+ Console.ReadKey();
+
+ await messageSender.CloseAsync();
+ await sessionClient.CloseAsync();
+ }
+
+ static async Task ReceiveSessionMessagesAsync(int numberOfSessions, int messagesPerSession)
+ {
+ Console.WriteLine("===================================================================");
+ Console.WriteLine("Accepting sessions in the reverse order of sends for demo purposes");
+ Console.WriteLine("===================================================================");
+
+ for (int i = 0; i < numberOfSessions; i++)
+ {
+ int messagesReceivedPerSession = 0;
+
+ // AcceptMessageSessionAsync(i.ToString()) as below with session id as parameter will try to get a session with that sessionId.
+ // AcceptMessageSessionAsync() without any messages will try to get any available session with messages associated with that session.
+ IMessageSession session = await sessionClient.AcceptMessageSessionAsync(SessionPrefix + i.ToString());
+
+ if(session != null)
+ {
+ // Messages within a session will always arrive in order.
+ Console.WriteLine("=====================================");
+ Console.WriteLine($"Received Session: {session.SessionId}");
+
+ while (messagesReceivedPerSession++ < messagesPerSession)
+ {
+ Message message = await session.ReceiveAsync();
+
+ Console.WriteLine($"Received message: SequenceNumber:{message.SystemProperties.SequenceNumber} Body:{Encoding.UTF8.GetString(message.Body)}");
+
+ // Complete the message so that it is not received again.
+ // This can be done only if the queueClient is created in ReceiveMode.PeekLock mode (which is default).
+ await session.CompleteAsync(message.SystemProperties.LockToken);
+ }
+
+ Console.WriteLine($"Received all messages for Session: {session.SessionId}");
+ Console.WriteLine("=====================================");
+
+ // Close the Session after receiving all messages from the session
+ await session.CloseAsync();
+ }
+ }
+ }
+
+ static async Task SendSessionMessagesAsync(int numberOfSessions, int messagesPerSession)
+ {
+ if (numberOfSessions == 0 || messagesPerSession == 0)
+ {
+ await Task.FromResult(false);
+ }
+
+ for (int i = numberOfSessions - 1; i >= 0; i--)
+ {
+ var messagesToSend = new List();
+ string sessionId = SessionPrefix + i;
+ for (int j = 0; j < messagesPerSession; j++)
+ {
+ // Create a new message to send to the queue
+ string messageBody = "test" + j;
+ var message = new Message(Encoding.UTF8.GetBytes(messageBody));
+ // Assign a SessionId for the message
+ message.SessionId = sessionId;
+ messagesToSend.Add(message);
+
+ // Write the sessionId, body of the message to the console
+ Console.WriteLine($"Sending SessionId: {message.SessionId}, message: {messageBody}");
+ }
+
+ // Send a batch of messages corresponding to this sessionId to the queue
+ await messageSender.SendAsync(messagesToSend);
+ }
+
+ Console.WriteLine("=====================================");
+ Console.WriteLine($"Sent {messagesPerSession} messages each for {numberOfSessions} sessions.");
+ Console.WriteLine("=====================================");
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/SessionSendReceiveUsingSessionClient/SessionSendReceiveUsingSessionClient.csproj b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/SessionSendReceiveUsingSessionClient/SessionSendReceiveUsingSessionClient.csproj
new file mode 100644
index 0000000..768aae7
--- /dev/null
+++ b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/SessionSendReceiveUsingSessionClient/SessionSendReceiveUsingSessionClient.csproj
@@ -0,0 +1,12 @@
+
+
+
+ Exe
+ netcoreapp2.0
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/SessionSendReceiveUsingSessionClient/readme.md b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/SessionSendReceiveUsingSessionClient/readme.md
new file mode 100644
index 0000000..0abc6e2
--- /dev/null
+++ b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/SessionSendReceiveUsingSessionClient/readme.md
@@ -0,0 +1,186 @@
+# Get started sending and receiving session based messages from Service Bus queues using SessionClient
+
+In order to run the sample in this directory, replace the following bracketed values in the `Program.cs` file.
+
+```csharp
+// Connection String for the namespace can be obtained from the Azure portal under the
+// `Shared Access policies` section.
+const string ServiceBusConnectionString = "{Service Bus connection string}";
+const string QueueName = "{Queue Name of a Queue that supports sessions}";
+```
+
+Once you replace the above values run the following from a command prompt:
+
+```
+dotnet restore
+dotnet build
+dotnet run
+```
+
+## The Sample Program
+To keep things reasonably simple, the sample program keeps send and receive code within a single hosting application.
+Typically in real world applications these roles are often spread across applications, services, or at least across
+independently deployed and run tiers of applications or services. For clarity, the send and receive activities are kept as
+separate methods as if they were different apps.
+
+For further information on how to create this sample on your own, follow the rest of the tutorial.
+
+## What will be accomplished
+In this tutorial, we will write a console application to send and receive sessionful messages to a ServiceBus queue using a SessionClient.
+Sending session based messages to a queue using MessageSender is same as sending other messages but the messages are stamped with an additional
+`SessionId` property. SessionClient offers a more granular control to the user for receiving Session based messages than `QueueClient`. The User
+can explicitly choose to accept sessions with a particular `SessionId`, defer messages received from a session and accept deffered messages on that session.
+But this also means the User has to write more code to accept MessageSessions, renew session locks, complete messages and
+define how to achieve a basic degree of concurrency while processing sessions.
+
+## Prerequisites
+1. [.NET Core](https://www.microsoft.com/net/core)
+2. An Azure subscription.
+3. [A ServiceBus namespace](https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-create-namespace-portal)
+4. [A ServiceBus queue](https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-dotnet-get-started-with-queues#2-create-a-queue-using-the-azure-portal)
+
+### Create a console application
+
+- Create a new .NET Core application. Check out [this link](https://docs.microsoft.com/en-us/dotnet/articles/core/getting-started) with help to create a new application on your operating system.
+
+### Add the ServiceBus client reference
+
+1. Add the following to your project.json, making sure that the solution references the `Microsoft.Azure.ServiceBus` project.
+
+ ```json
+ "Microsoft.Azure.ServiceBus": "1.0.0"
+ ```
+
+### Write some code to send and receive messages from the queue
+1. Add the following using statement to the top of the Program.cs file.
+
+ ```csharp
+ using Microsoft.Azure.ServiceBus;
+ ```
+
+1. Add the following variables to the `Program` class, and replace the placeholder values:
+
+ ```csharp
+ const string ServiceBusConnectionString = "{Service Bus connection string}";
+ const string QueueName = "{Queue Name of a Queue that supports sessions}";
+ static IMessageSender messageSender;
+ static ISessionClient sessionClient;
+ const string SessionPrefix = "session-prefix";
+ ```
+
+1. Create a new Task called `ReceiveSessionMessagesAsync` that knows how to receive messages from a session using SessionClient with the following code:
+
+ ```csharp
+ static async Task ReceiveSessionMessagesAsync(int numberOfSessions, int messagesPerSession)
+ {
+ Console.WriteLine("===================================================================");
+ Console.WriteLine("Accepting sessions in the reverse order of sends for demo purposes");
+ Console.WriteLine("===================================================================");
+
+ for (int i = 0; i < numberOfSessions; i++)
+ {
+ int messagesReceivedPerSession = 0;
+
+ // AcceptMessageSessionAsync(i.ToString()) as below with session id as parameter will try to get a session with that sessionId.
+ // AcceptMessageSessionAsync() without any messages will try to get any available session with messages associated with that session.
+ IMessageSession session = await sessionClient.AcceptMessageSessionAsync(SessionPrefix + i.ToString());
+
+ if(session != null)
+ {
+ // Messages within a session will always arrive in order.
+ Console.WriteLine("=====================================");
+ Console.WriteLine($"Received Session: {session.SessionId}");
+ Console.WriteLine($"Receiving all messages for this Session");
+
+ while(messagesReceivedPerSession++ < messagesPerSession)
+ {
+ Message message = await session.ReceiveAsync();
+ Console.WriteLine($"Received message: SequenceNumber:{message.SystemProperties.SequenceNumber} Body:{Encoding.UTF8.GetString(message.Body)}");
+
+ // Complete the message so that it is not received again.
+ // This can be done only if the queueClient is created in ReceiveMode.PeekLock mode (which is default).
+ await session.CompleteAsync(message.SystemProperties.LockToken);
+ }
+
+ Console.WriteLine($"Received all messages for Session: {session.SessionId}");
+ Console.WriteLine("=====================================");
+
+ // Close the Session after receiving all messages from the session
+ await session.CloseAsync();
+ }
+ }
+ }
+ ```
+
+1. Create a new method called `SendSessionMessagesAsync` that sends sessionful messages to the queue with the following code:
+
+ ```csharp
+ static async Task SendSessionMessagesAsync(int numberOfSessions, int messagesPerSession)
+ {
+ if (numberOfSessions == 0 || messagesPerSession == 0)
+ {
+ await Task.FromResult(false);
+ }
+
+ for (int i = numberOfSessions - 1; i >= 0; i--)
+ {
+ var messagesToSend = new List();
+ string sessionId = SessionPrefix + i;
+ for (int j = 0; j < messagesPerSession; j++)
+ {
+ // Create a new message to send to the queue
+ string messageBody = "test" + j;
+ var message = new Message(Encoding.UTF8.GetBytes(messageBody));
+ // Assign a SessionId for the message
+ message.SessionId = sessionId;
+ messagesToSend.Add(message);
+
+ // Write the sessionId, body of the message to the console
+ Console.WriteLine($"Sending SessionId: {message.SessionId}, message: {messageBody}");
+ }
+
+ // Send a batch of messages corresponding to this sessionId to the queue
+ await queueClient.SendAsync(messagesToSend);
+ }
+
+ Console.WriteLine("=====================================");
+ Console.WriteLine($"Sent {messagesPerSession} messages each for {numberOfSessions} sessions.");
+ Console.WriteLine("=====================================");
+ }
+ ```
+
+1. Create a new method called `MainAsync` with the following code:
+
+ ```csharp
+ static async Task MainAsync(string[] args)
+ {
+ const int numberOfSessions = 5;
+ const int numberOfMessagesPerSession = 3;
+
+ messageSender = new MessageSender(ServiceBusConnectionString, QueueName);
+ sessionClient = new SessionClient(ServiceBusConnectionString, QueueName);
+
+ Console.WriteLine("======================================================");
+ Console.WriteLine("Press any key to exit after receiving all the messages.");
+ Console.WriteLine("======================================================");
+
+ // Send messages with sessionId set
+ await SendSessionMessagesAsync(numberOfSessions, numberOfMessagesPerSession);
+
+ // Receive all Session based messages using SessionClient
+ await ReceiveSessionMessagesAsync(numberOfSessions, numberOfMessagesPerSession);
+
+ Console.ReadKey();
+
+ await messageSender.CloseAsync();
+ await sessionClient.CloseAsync();
+ }
+ ```
+
+1. Add the following code to the `Main` method:
+
+ ```csharp
+ MainAsync(args).GetAwaiter().GetResult();
+ ```
+
+Congratulations! You have now sent and received session based messages to a ServiceBus queue, using SessionClient.
diff --git a/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/TopicSubscriptionWithRuleOperationsSample/Program.cs b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/TopicSubscriptionWithRuleOperationsSample/Program.cs
new file mode 100644
index 0000000..83b8d63
--- /dev/null
+++ b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/TopicSubscriptionWithRuleOperationsSample/Program.cs
@@ -0,0 +1,183 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+namespace TopicSubscriptionWithRuleOperationsSample
+{
+ using Microsoft.Azure.ServiceBus;
+ using Microsoft.Azure.ServiceBus.Core;
+ using System;
+ using System.Linq;
+ using System.Threading.Tasks;
+
+ class Program
+ {
+ // Connection String for the namespace can be obtained from the Azure portal under the
+ // 'Shared Access policies' section.
+ const string ServiceBusConnectionString = "{ServiceBus connection string}";
+ const string TopicName = "{Topic Name}";
+
+ // Simply create 4 default subscriptions (no rules specified explicitly) and provide subscription names.
+ // The Rule addition will be done as part of the sample depending on the subscription behavior expected.
+ const string allMessagesSubscriptionName = "{Subscription 1 Name}";
+ const string sqlFilterOnlySubscriptionName = "{Subscription 2 Name}";
+ const string sqlFilterWithActionSubscriptionName = "{Subscription 3 Name}";
+ const string correlationFilterSubscriptionName = "{Subscription 4 Name}";
+
+ static ITopicClient topicClient;
+ static ISubscriptionClient allMessagessubscriptionClient, sqlFilterOnlySubscriptionClient, sqlFilterWithActionSubscriptionClient, correlationFilterSubscriptionClient;
+
+ static void Main(string[] args)
+ {
+ MainAsync().GetAwaiter().GetResult();
+ }
+
+ static async Task MainAsync()
+ {
+ topicClient = new TopicClient(ServiceBusConnectionString, TopicName);
+ allMessagessubscriptionClient = new SubscriptionClient(ServiceBusConnectionString, TopicName, allMessagesSubscriptionName);
+ sqlFilterOnlySubscriptionClient = new SubscriptionClient(ServiceBusConnectionString, TopicName, sqlFilterOnlySubscriptionName);
+ sqlFilterWithActionSubscriptionClient = new SubscriptionClient(ServiceBusConnectionString, TopicName, sqlFilterWithActionSubscriptionName);
+ correlationFilterSubscriptionClient = new SubscriptionClient(ServiceBusConnectionString, TopicName, correlationFilterSubscriptionName);
+
+ // First Subscription is already created with default rule. Leave as is.
+
+ // 2nd Subscription: Add SqlFilter on Subscription 2
+ // Delete Default Rule.
+ // Add the required SqlFilter Rule
+ // Note: Does not apply to this sample but if there are multiple rules configured for a
+ // single subscription, then one message is delivered to the subscription when any of the
+ // rule matches. If more than one rules match and if there is no `SqlRuleAction` set for the
+ // rule, then only one message will be delivered to the subscription. If more than one rules
+ // match and there is a `SqlRuleAction` specified for the rule, then one message per `SqlRuleAction`
+ // is delivered to the subscription.
+ Console.WriteLine($"SubscriptionName: {sqlFilterOnlySubscriptionName}, Removing Default Rule and Adding SqlFilter");
+ await sqlFilterOnlySubscriptionClient.RemoveRuleAsync(RuleDescription.DefaultRuleName);
+ await sqlFilterOnlySubscriptionClient.AddRuleAsync(new RuleDescription
+ {
+ Filter = new SqlFilter("Color = 'Red'"),
+ Name = "RedSqlRule"
+ });
+
+ // 3rd Subscription: Add SqlFilter and SqlRuleAction on Subscription 3
+ // Delete Default Rule
+ // Add the required SqlFilter Rule and Action
+ Console.WriteLine($"SubscriptionName: {sqlFilterWithActionSubscriptionName}, Removing Default Rule and Adding SqlFilter and SqlRuleAction");
+ await sqlFilterWithActionSubscriptionClient.RemoveRuleAsync(RuleDescription.DefaultRuleName);
+ await sqlFilterWithActionSubscriptionClient.AddRuleAsync(new RuleDescription
+ {
+ Filter = new SqlFilter("Color = 'Blue'"),
+ Action = new SqlRuleAction("SET Color = 'BlueProcessed'"),
+ Name = "BlueSqlRule"
+ });
+
+ // 4th Subscription: Add Correlation Filter on Subscription 4
+ Console.WriteLine($"SubscriptionName: {sqlFilterWithActionSubscriptionName}, Removing Default Rule and Adding CorrelationFilter");
+ await correlationFilterSubscriptionClient.RemoveRuleAsync(RuleDescription.DefaultRuleName);
+ await correlationFilterSubscriptionClient.AddRuleAsync(new RuleDescription
+ {
+ Filter = new CorrelationFilter() { Label = "Red", CorrelationId = "important" },
+ Name = "ImportantCorrelationRule"
+ });
+
+ // Get Rules on Subscription, called here only for one subscription as example
+ var rules = (await correlationFilterSubscriptionClient.GetRulesAsync()).ToList();
+ Console.WriteLine($"GetRules:: SubscriptionName: {correlationFilterSubscriptionName}, CorrelationFilter Name: {rules[0].Name}, Rule: {rules[0].Filter}");
+
+ // Send messages to Topic
+ await SendMessagesAsync();
+
+ // Receive messages from 'allMessagesSubscriptionName'. Should receive all 9 messages
+ await ReceiveMessagesAsync(allMessagesSubscriptionName);
+
+ // Receive messages from 'sqlFilterOnlySubscriptionName'. Should receive all messages with Color = 'Red' i.e 3 messages
+ await ReceiveMessagesAsync(sqlFilterOnlySubscriptionName);
+
+ // Receive messages from 'sqlFilterWithActionSubscriptionClient'. Should receive all messages with Color = 'Blue'
+ // i.e 3 messages AND all messages should have color set to 'BlueProcessed'
+ await ReceiveMessagesAsync(sqlFilterWithActionSubscriptionName);
+
+ // Receive messages from 'correlationFilterSubscriptionName'. Should receive all messages with Color = 'Red' and CorrelationId = "important"
+ // i.e 1 message
+ await ReceiveMessagesAsync(correlationFilterSubscriptionName);
+
+ Console.WriteLine("=========================================================");
+ Console.WriteLine("Completed Receiving all messages... Press any key to exit");
+ Console.WriteLine("=========================================================");
+
+ Console.ReadKey();
+
+ await allMessagessubscriptionClient.CloseAsync();
+ await sqlFilterOnlySubscriptionClient.CloseAsync();
+ await sqlFilterWithActionSubscriptionClient.CloseAsync();
+ await correlationFilterSubscriptionClient.CloseAsync();
+ await topicClient.CloseAsync();
+ }
+
+ static async Task SendMessagesAsync()
+ {
+ Console.WriteLine($"==========================================================================");
+ Console.WriteLine("Sending Messages to Topic");
+ try
+ {
+ await Task.WhenAll(
+ SendMessageAsync(label: "Red"),
+ SendMessageAsync(label: "Blue"),
+ SendMessageAsync(label: "Red", correlationId: "important"),
+ SendMessageAsync(label: "Blue", correlationId: "important"),
+ SendMessageAsync(label: "Red", correlationId: "notimportant"),
+ SendMessageAsync(label: "Blue", correlationId: "notimportant"),
+ SendMessageAsync(label: "Green"),
+ SendMessageAsync(label: "Green", correlationId: "important"),
+ SendMessageAsync(label: "Green", correlationId: "notimportant")
+ );
+ }
+ catch (Exception exception)
+ {
+ Console.WriteLine($"{DateTime.Now} :: Exception: {exception.Message}");
+ }
+ }
+
+ static async Task SendMessageAsync(string label, string correlationId = null)
+ {
+ Message message = new Message { Label = label };
+ message.UserProperties.Add("Color", label);
+
+ if (correlationId != null)
+ {
+ message.CorrelationId = correlationId;
+ }
+
+ await topicClient.SendAsync(message);
+ Console.WriteLine($"Sent Message:: Label: {message.Label}, CorrelationId: {message.CorrelationId ?? message.CorrelationId}");
+ }
+
+ static async Task ReceiveMessagesAsync(string subscriptionName)
+ {
+ string subscriptionPath = EntityNameHelper.FormatSubscriptionPath(TopicName, subscriptionName);
+ IMessageReceiver subscriptionReceiver = new MessageReceiver(ServiceBusConnectionString, subscriptionPath, ReceiveMode.ReceiveAndDelete);
+
+ Console.WriteLine($"==========================================================================");
+ Console.WriteLine($"{DateTime.Now} :: Receiving Messages From Subscription: {subscriptionName}");
+ int receivedMessageCount = 0;
+ while (true)
+ {
+ var receivedMessage = await subscriptionReceiver.ReceiveAsync(TimeSpan.Zero);
+ if (receivedMessage != null)
+ {
+ object colorProperty;
+ receivedMessage.UserProperties.TryGetValue("Color", out colorProperty);
+ Console.WriteLine($"Color Property = {colorProperty}, CorrelationId = {receivedMessage.CorrelationId ?? receivedMessage.CorrelationId}");
+ receivedMessageCount++;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ Console.WriteLine($"{DateTime.Now} :: Received '{receivedMessageCount}' Messages From Subscription: {subscriptionName}");
+ Console.WriteLine($"==========================================================================");
+ await subscriptionReceiver.CloseAsync();
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/TopicSubscriptionWithRuleOperationsSample/TopicSubscriptionWithRuleOperationsSample.csproj b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/TopicSubscriptionWithRuleOperationsSample/TopicSubscriptionWithRuleOperationsSample.csproj
new file mode 100644
index 0000000..768aae7
--- /dev/null
+++ b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/TopicSubscriptionWithRuleOperationsSample/TopicSubscriptionWithRuleOperationsSample.csproj
@@ -0,0 +1,12 @@
+
+
+
+ Exe
+ netcoreapp2.0
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/TopicSubscriptionWithRuleOperationsSample/readme.md b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/TopicSubscriptionWithRuleOperationsSample/readme.md
new file mode 100644
index 0000000..a876745
--- /dev/null
+++ b/samples/DotNet/GettingStarted/Microsoft.Azure.ServiceBus/TopicSubscriptionWithRuleOperationsSample/readme.md
@@ -0,0 +1,255 @@
+# Get started configuring and managing rules for Subscriptions
+
+In order to run the sample in this directory, replace the following bracketed values in the `Program.cs` file.
+
+```csharp
+// Connection String for the namespace can be obtained from the Azure portal under the
+// `Shared Access policies` section.
+const string ServiceBusConnectionString = "{Service Bus connection string}";
+const string TopicName = "{Topic Name}";
+
+// Simply create 4 default subscriptions (no rules specified explicitly) and provide subscription names.
+// The Rule addition will be done as part of the sample depending on the subscription behavior expected.
+const string allMessagesSubscriptionName = "{Subscription 1 Name}";
+const string sqlFilterOnlySubscriptionName = "{Subscription 2 Name}";
+const string sqlFilterWithActionSubscriptionName = "{Subscription 3 Name}";
+const string correlationFilterSubscriptionName = "{Subscription 4 Name}";
+```
+
+Once you replace the above values run the following from a command prompt:
+
+```
+dotnet restore
+dotnet build
+dotnet run
+```
+
+## The Sample Program
+To keep things reasonably simple, the sample program keeps send and receive code within a single hosting application.
+Typically in real world applications these roles are often spread across applications, services, or at least across
+independently deployed and run tiers of applications or services. For clarity, the send and receive activities are kept as
+separate methods as if they were different apps.
+
+For further information on how to create this sample on your own, follow the rest of the tutorial.
+
+## What will be accomplished
+Topics are similar to Queues for the send side of the application. However unlike Queues, Topic can have zero or more subscriptions,
+from which messages can be retrieved and each of subscription act like independent queues. Whether a message is selected into the
+subscription is determined by the Filter condition for the subscription. Filters can be one of the following:
+
+1. `TrueFilter` - Selects all messages to subscription,
+2. `FalseFilter` - Selects none of the messages to subscription,
+3. `SqlFilter` - Holds a SQL-like condition expression that is evaluated in the ServiceBus service against the arriving messages'
+user-defined properties and system properties and if matched the message is selected for subscription.
+4. `CorrelationFilter` - Holds a set of conditions that is evaluated in the ServiceBus service against the arriving messages'
+user-defined properties and system properties. A match exists when an arriving message's value for a property is equal to the
+value specified in the correlation filter.
+
+In this tutorial, we will write a console application to manage rules on Subscription (`AddRule`, `GetRules`, `RemoveRules`).
+We will also explore different forms of subscription filters. Refer to the
+link(https://github.com/Azure/azure-service-bus/tree/master/samples/DotNet/Microsoft.ServiceBus.Messaging/TopicFilters) for a more
+detailed explanation of filters.
+
+## Prerequisites
+1. [.NET Core](https://www.microsoft.com/net/core)
+2. An Azure subscription.
+3. [A ServiceBus namespace](https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-create-namespace-portal)
+4. [A ServiceBus Topic](https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-dotnet-how-to-use-topics-subscriptions#2-create-a-topic-using-the-azure-portal)
+5. [ServiceBus Subscriptions](https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-dotnet-how-to-use-topics-subscriptions)
+
+### Create a console application
+
+- Create a new .NET Core application. Check out [this link](https://docs.microsoft.com/en-us/dotnet/articles/core/getting-started) with help to create a new application on your operating system.
+
+### Add the ServiceBus client reference
+
+1. Add the following to your project.json, making sure that the solution references the `Microsoft.Azure.ServiceBus` project.
+
+ ```json
+ "Microsoft.Azure.ServiceBus": "1.0.0"
+ ```
+
+### Write some code to send messages to the topic, manage rules and receive messages from the subscription
+1. Add the following using statement to the top of the Program.cs file.
+
+ ```csharp
+ using Microsoft.Azure.ServiceBus;
+ ```
+
+1. Add the following variables to the `Program` class, and replace the placeholder values:
+
+ ```csharp
+ const string ServiceBusConnectionString = "{Service Bus connection string}";
+ const string TopicName = "{Topic Name}";
+ const string allMessagesSubscriptionName = "{Subscription 1 Name}";
+ const string sqlFilterOnlySubscriptionName = "{Subscription 2 Name}";
+ const string sqlFilterWithActionSubscriptionName = "{Subscription 3 Name}";
+ const string correlationFilterSubscriptionName = "{Subscription 4 Name}";
+ ```
+
+1. Create the following methods that will send messages with various combinations to the topic:
+
+ ```csharp
+ static async Task SendMessagesAsync()
+ {
+ Console.WriteLine($"==========================================================================");
+ Console.WriteLine("Sending Messages to Topic");
+ try
+ {
+ await Task.WhenAll(
+ SendMessageAsync(label: "Red"),
+ SendMessageAsync(label: "Blue"),
+ SendMessageAsync(label: "Red", correlationId: "important"),
+ SendMessageAsync(label: "Blue", correlationId: "important"),
+ SendMessageAsync(label: "Red", correlationId: "notimportant"),
+ SendMessageAsync(label: "Blue", correlationId: "notimportant"),
+ SendMessageAsync(label: "Green"),
+ SendMessageAsync(label: "Green", correlationId: "important"),
+ SendMessageAsync(label: "Green", correlationId: "notimportant")
+ );
+ }
+ catch (Exception exception)
+ {
+ Console.WriteLine($"{DateTime.Now} :: Exception: {exception.Message}");
+ }
+ }
+
+ static async Task SendMessageAsync(string label, string correlationId = null)
+ {
+ Message message = new Message { Label = label };
+ message.UserProperties.Add("Color", label);
+
+ if (correlationId != null)
+ {
+ message.CorrelationId = correlationId;
+ }
+
+ await topicClient.SendAsync(message);
+ Console.WriteLine($"Sent Message:: Label: {message.Label}, CorrelationId: {message.CorrelationId ?? message.CorrelationId}");
+ }
+ ```
+
+1. Create a new method Task `ReceiveMessagesAsync` with the following code to process messages from a given subscription:
+ ```csharp
+ static async Task ReceiveMessagesAsync(string subscriptionName)
+ {
+ string subscriptionPath = EntityNameHelper.FormatSubscriptionPath(TopicName, subscriptionName);
+ IMessageReceiver subscriptionReceiver = new MessageReceiver(ServiceBusConnectionString, subscriptionPath, ReceiveMode.ReceiveAndDelete);
+
+ Console.WriteLine($"==========================================================================");
+ Console.WriteLine($"{DateTime.Now} :: Receiving Messages From Subscription: {subscriptionName}");
+ int receivedMessageCount = 0;
+ while (true)
+ {
+ var receivedMessage = await subscriptionReceiver.ReceiveAsync(TimeSpan.Zero);
+ if (receivedMessage != null)
+ {
+ object colorProperty;
+ receivedMessage.UserProperties.TryGetValue("Color", out colorProperty);
+ Console.WriteLine($"Color Property = {colorProperty}, CorrelationId = {receivedMessage.CorrelationId ?? receivedMessage.CorrelationId}");
+ receivedMessageCount++;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ Console.WriteLine($"{DateTime.Now} :: Received '{receivedMessageCount}' Messages From Subscription: {subscriptionName}");
+ Console.WriteLine($"==========================================================================");
+ }
+ ```
+
+1. Create a new method called `MainAsync` with the following code:
+
+ ```csharp
+ static async Task MainAsync()
+ {
+ topicClient = new TopicClient(ServiceBusConnectionString, TopicName);
+ allMessagessubscriptionClient = new SubscriptionClient(ServiceBusConnectionString, TopicName, allMessagesSubscriptionName);
+ sqlFilterOnlySubscriptionClient = new SubscriptionClient(ServiceBusConnectionString, TopicName, sqlFilterOnlySubscriptionName);
+ sqlFilterWithActionSubscriptionClient = new SubscriptionClient(ServiceBusConnectionString, TopicName, sqlFilterWithActionSubscriptionName);
+ correlationFilterSubscriptionClient = new SubscriptionClient(ServiceBusConnectionString, TopicName, correlationFilterSubscriptionName);
+
+ // First Subscription is already created with default rule. Leave as is.
+
+ // 2nd Subscription: Add SqlFilter on Subscription 2
+ // Delete Default Rule.
+ // Add the required SqlFilter Rule
+ // Note: Does not apply to this sample but if there are multiple rules configured for a
+ // single subscription, then one message is delivered to the subscription when any of the
+ // rule matches. If more than one rules match and if there is no `SqlRuleAction` set for the
+ // rule, then only one message will be delivered to the subscription. If more than one rules
+ // match and there is a `SqlRuleAction` specified for the rule, then one message per `SqlRuleAction`
+ // is delivered to the subscription.
+ Console.WriteLine($"SubscriptionName: {sqlFilterOnlySubscriptionName}, Removing Default Rule and Adding SqlFilter");
+ await sqlFilterOnlySubscriptionClient.RemoveRuleAsync(RuleDescription.DefaultRuleName);
+ await sqlFilterOnlySubscriptionClient.AddRuleAsync(new RuleDescription
+ {
+ Filter = new SqlFilter("Color = 'Red'"),
+ Name = "RedSqlRule"
+ });
+
+ // 3rd Subscription: Add SqlFilter and SqlRuleAction on Subscription 3
+ // Delete Default Rule
+ // Add the required SqlFilter Rule and Action
+ Console.WriteLine($"SubscriptionName: {sqlFilterWithActionSubscriptionName}, Removing Default Rule and Adding SqlFilter and SqlRuleAction");
+ await sqlFilterWithActionSubscriptionClient.RemoveRuleAsync(RuleDescription.DefaultRuleName);
+ await sqlFilterWithActionSubscriptionClient.AddRuleAsync(new RuleDescription
+ {
+ Filter = new SqlFilter("Color = 'Blue'"),
+ Action = new SqlRuleAction("SET Color = 'BlueProcessed'"),
+ Name = "BlueSqlRule"
+ });
+
+ // 4th Subscription: Add Correlation Filter on Subscription 4
+ Console.WriteLine($"SubscriptionName: {sqlFilterWithActionSubscriptionName}, Removing Default Rule and Adding CorrelationFilter");
+ await correlationFilterSubscriptionClient.RemoveRuleAsync(RuleDescription.DefaultRuleName);
+ await correlationFilterSubscriptionClient.AddRuleAsync(new RuleDescription
+ {
+ Filter = new CorrelationFilter() { Label = "Red", CorrelationId = "important" },
+ Name = "ImportantCorrelationRule"
+ });
+
+ // Get Rules on Subscription, called here only for one subscription as example
+ var rules = (await correlationFilterSubscriptionClient.GetRulesAsync()).ToList();
+ Console.WriteLine($"GetRules:: SubscriptionName: {correlationFilterSubscriptionName}, CorrelationFilter Name: {rules[0].Name}, Rule: {rules[0].Filter}");
+
+ // Send messages to Topic
+ await SendMessagesAsync();
+
+ // Receive messages from 'allMessagesSubscriptionName'. Should receive all 9 messages
+ await ReceiveMessagesAsync(allMessagesSubscriptionName);
+
+ // Receive messages from 'sqlFilterOnlySubscriptionName'. Should receive all messages with Color = 'Red' i.e 3 messages
+ await ReceiveMessagesAsync(sqlFilterOnlySubscriptionName);
+
+ // Receive messages from 'sqlFilterWithActionSubscriptionClient'. Should receive all messages with Color = 'Blue'
+ // i.e 3 messages AND all messages should have color set to 'BlueProcessed'
+ await ReceiveMessagesAsync(sqlFilterWithActionSubscriptionName);
+
+ // Receive messages from 'correlationFilterSubscriptionName'. Should receive all messages with Color = 'Red' and CorrelationId = "important"
+ // i.e 1 message
+ await ReceiveMessagesAsync(correlationFilterSubscriptionName);
+
+ Console.WriteLine("=========================================================");
+ Console.WriteLine("Completed Receiving all messages... Press any key to exit");
+ Console.WriteLine("=========================================================");
+
+ Console.ReadKey();
+
+ await allMessagessubscriptionClient.CloseAsync();
+ await sqlFilterOnlySubscriptionClient.CloseAsync();
+ await sqlFilterWithActionSubscriptionClient.CloseAsync();
+ await correlationFilterSubscriptionClient.CloseAsync();
+ await topicClient.CloseAsync();
+ }
+ ```
+
+1. Add the following code to the `Main` method:
+
+ ```csharp
+ MainAsync(args).GetAwaiter().GetResult();
+ ```
+
+Congratulations! You have now learnt to configure and manage rules for a ServiceBus Topic Subscription.