Raw New Markdown
Generating updated version of doc...
Rendered New Markdown
Generating updated version of doc...
---
title: Expose on-premises WCF REST service to clients
description: This tutorial describes how to expose an on-premises WCF REST service to an external client by using Azure WCF Relay.
ms.topic: tutorial
ms.date: 12/11/2024
# Customer intent: I want to know how to expose an on-premises WCF REST service to external clients using WCF Relay.
---
# Tutorial: Expose an on-premises Windows Communication Foundation (WCF) REST service to external client by using Azure WCF Relay
This tutorial describes how to build a WCF Relay client application and a service using Azure Relay. Like their original WCF counterparts, a service is a construct that exposes one or more endpoints. Each **endpoint** exposes one or more service operations. The endpoint of a service specifies an **address** where the service can be found, a **binding** that contains the information that a client must communicate with the service, and a **contract** that defines the functionality provided by the service to its clients. The main difference between WCF and WCF Relay is that the endpoint is exposed in the cloud instead of locally on your computer.
After you work through the sequence of sections in this tutorial, you'll have a running service. You'll also have a client that can invoke the operations of the service.
You do the following tasks in this tutorial:
> [!div class="checklist"]
>
> * Install prerequisites for this tutorial.
> * Create a Relay namespace.
> * Create a WCF service contract.
> * Implement the WCF contract.
> * Host and run the WCF service to register with the Relay service.
> * Create a WCF client for the service contract.
> * Configure the WCF client.
> * Implement the WCF client.
> * Run the applications.
## Prerequisites
To complete this tutorial, you need the following prerequisites:
* An Azure subscription. If you don't have one, [create a free account](https://azure.microsoft.com/pricing/purchase-options/azure-account?cid=msft_learn) before you begin.
* [Visual Studio 2015 or later](https://www.visualstudio.com). The examples in this tutorial use Visual Studio 2019.
* Azure SDK for .NET. Install it from the [SDK downloads page](https://azure.microsoft.com/downloads/).
## Create a Relay namespace
The first step is to create a namespace, and to obtain a [Shared Access Signature (SAS)](../service-bus-messaging/service-bus-sas.md) key. A namespace provides an application boundary for each application exposed through the relay service. An SAS key is automatically generated by the system when a service namespace is created. The combination of service namespace and SAS key provides the credentials for Azure to authenticate access to an application.
[!INCLUDE [relay-create-namespace-portal](./includes/relay-create-namespace-portal.md)]
## Define a WCF service contract
The service contract specifies what operations the service supports. Operations are web service methods or functions. Contracts are created by defining a C++, C#, or Visual Basic interface. Each method in the interface corresponds to a specific service operation. Each interface must have the [ServiceContractAttribute](/dotnet/api/system.servicemodel.servicecontractattribute) attribute applied to it, and each operation must have the [OperationContractAttribute](/dotnet/api/system.servicemodel.operationcontractattribute) attribute applied to it. If a method in an interface that has the [ServiceContractAttribute](/dotnet/api/system.servicemodel.servicecontractattribute) attribute doesn't have the [OperationContractAttribute](/dotnet/api/system.servicemodel.operationcontractattribute) attribute, that method isn't exposed. The code for these tasks is provided in the example following the procedure. For a larger discussion of contracts and services, see [Designing and Implementing Services](/dotnet/framework/wcf/designing-and-implementing-services).
### Create a relay contract with an interface
1. Start Microsoft Visual Studio as an administrator. To do so, right-click the Visual Studio program icon, and select **Run as administrator**.
1. In Visual Studio, select **Create a new project**.
1. In **Create a new project**, choose **Console App (.NET Framework)** for C# and select **Next**.
1. Name the project *EchoService* and select **Create**.
![Create a console app][2]
1. In **Solution Explorer**, right-click the project and select **Manage NuGet Packages**. In the **NuGet Package Manager**, select **Browse**, then search for and choose **WindowsAzure.ServiceBus**. Select **Install**, and accept the terms of use.
![Service Bus package][3]
This package automatically adds references to the Service Bus libraries and the WCF `System.ServiceModel`. [System.ServiceModel](/dotnet/api/system.servicemodel) is the namespace that enables you to programmatically access the basic features of WCF. Service Bus uses many of the objects and attributes of WCF to define service contracts.
1. Add the following `using` statements at the top of *Program.cs*:
```csharp
using System.ServiceModel;
using Microsoft.ServiceBus;
```
1. Change the namespace name from its default name of `EchoService` to `Microsoft.ServiceBus.Samples`.
> [!IMPORTANT]
> This tutorial uses the C# namespace `Microsoft.ServiceBus.Samples` which is the namespace of the contract-based managed type that is used in the configuration file in the [Configure the WCF client](#configure-the-wcf-client) section. You can specify any namespace you want when you build this sample. However, the tutorial will not work unless you then modify the namespaces of the contract and service accordingly, in the application configuration file. The namespace specified in the *App.config* file must be the same as the namespace specified in your C# files.
>
1. Directly after the `Microsoft.ServiceBus.Samples` namespace declaration, but within the namespace, define a new interface named `IEchoContract` and apply the `ServiceContractAttribute` attribute to the interface with a namespace value of `https://samples.microsoft.com/ServiceModel/Relay/`. Paste the following code after the namespace declaration:
```csharp
[ServiceContract(Name = "IEchoContract", Namespace = "https://samples.microsoft.com/ServiceModel/Relay/")]
public interface IEchoContract
{
}
```
The namespace value differs from the namespace that you use throughout the scope of your code. Instead, the namespace value is used as a unique identifier for this contract. Specifying the namespace explicitly prevents the default namespace value from being added to the contract name.
> [!NOTE]
> Typically, the service contract namespace contains a naming scheme that includes version information. Including version information in the service contract namespace enables services to isolate major changes by defining a new service contract with a new namespace and exposing it on a new endpoint. In this manner, clients can continue to use the old service contract without having to be updated. Version information can consist of a date or a build number. For more information, see [Service Versioning](/dotnet/framework/wcf/service-versioning). For this tutorial, the naming scheme of the service contract namespace does not contain version information.
>
1. Within the `IEchoContract` interface, declare a method for the single operation the `IEchoContract` contract exposes in the interface and apply the `OperationContractAttribute` attribute to the method that you want to expose as part of the public WCF Relay contract, as follows:
```csharp
[OperationContract]
string Echo(string text);
```
1. Directly after the `IEchoContract` interface definition, declare a channel that inherits from both `IEchoContract` and also to the `IClientChannel` interface, as shown here:
```csharp
public interface IEchoChannel : IEchoContract, IClientChannel { }
```
A channel is the WCF object through which the host and client pass information to each other. Later, you'll write code against the channel to echo information between the two applications.
1. Select **Build** > **Build Solution** or select Ctrl+Shift+B to confirm the accuracy of your work so far.
### Example of a WCF contract
The following code shows a basic interface that defines a WCF Relay contract.
```csharp
using System;
using System.ServiceModel;
namespace Microsoft.ServiceBus.Samples
{
[ServiceContract(Name = "IEchoContract", Namespace = "https://samples.microsoft.com/ServiceModel/Relay/")]
public interface IEchoContract
{
[OperationContract]
String Echo(string text);
}
public interface IEchoChannel : IEchoContract, IClientChannel { }
class Program
{
static void Main(string[] args)
{
}
}
}
```
Now that the interface is created, you can implement the interface.
## Implement the WCF contract
Creating an Azure relay requires that you first create the contract by using an interface. For more information about creating the interface, see the previous section. The next procedure implements the interface. This task involves creating a class named `EchoService` that implements the user-defined `IEchoContract` interface. After you implement the interface, you then configure the interface using an *App.config* configuration file. The configuration file contains necessary information for the application. This information includes the name of the service, the name of the contract, and the type of protocol that is used to communicate with the relay service. The code used for these tasks is provided in the example that follows the procedure. For a more general discussion about how to implement a service contract, see [Implementing Service Contracts](/dotnet/framework/wcf/implementing-service-contracts).
1. Create a new class named `EchoService` directly after the definition of the `IEchoContract` interface. The `EchoService` class implements the `IEchoContract` interface.
```csharp
class EchoService : IEchoContract
{
}
```
Similar to other interface implementations, you can implement the definition in a different file. However, for this tutorial, the implementation is located in the same file as the interface definition and the `Main()` method.
1. Apply the [ServiceBehaviorAttribute](/dotnet/api/system.servicemodel.servicebehaviorattribute) attribute to the `IEchoContract` interface. The attribute specifies the service name and namespace. After doing so, the `EchoService` class appears as follows:
```csharp
[ServiceBehavior(Name = "EchoService", Namespace = "https://samples.microsoft.com/ServiceModel/Relay/")]
class EchoService : IEchoContract
{
}
```
1. Implement the `Echo` method defined in the `IEchoContract` interface in the `EchoService` class.
```csharp
public string Echo(string text)
{
Console.WriteLine("Echoing: {0}", text);
return text;
}
```
1. Select **Build** > **Build Solution** or select Ctrl+Shift+B.
### Define the configuration for the service host
The configuration file is similar to a WCF configuration file. It includes the service name, endpoint, and binding. The endpoint is the location Azure Relay exposes for clients and hosts to communicate with each other. The binding is the type of protocol that is used to communicate. The main difference is that this configured service endpoint refers to a [NetTcpRelayBinding](/dotnet/api/microsoft.servicebus.nettcprelaybinding) binding, which isn't part of the .NET Framework. [NetTcpRelayBinding](/dotnet/api/microsoft.servicebus.nettcprelaybinding) is one of the bindings defined by the service.
1. In **Solution Explorer**, double-click **App.config** to open the file in the Visual Studio editor.
1. In the `<appSettings>` element, replace the placeholders with the name of your Azure Relay namespace, and the SAS key that you copied in an earlier step.
1. Within the `<system.serviceModel>` tags, add a `<services>` element. You can define multiple relay applications in a single configuration file. However, this tutorial defines only one.
```xml
<?xmlversion="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<services>
</services>
</system.serviceModel>
</configuration>
```
1. Within the `<services>` element, add a `<service>` element to define the name of the service.
```xml
<service name="Microsoft.ServiceBus.Samples.EchoService">
</service>
```
1. Within the `<service>` element, define the location of the endpoint contract, and also the type of binding for the endpoint.
```xml
<endpoint contract="Microsoft.ServiceBus.Samples.IEchoContract" binding="netTcpRelayBinding"/>
```
The endpoint defines where the client will look for the host application. Later, the tutorial uses this step to create a URI that fully exposes the host through Azure Relay. The binding declares that we're using TCP as the protocol to communicate with the relay service.
1. Select **Build** > **Build Solution** or select Ctrl+Shift+B to confirm the accuracy of your work so far.
### Example of implementation of a service contract
The following code shows the implementation of the service contract.
```csharp
[ServiceBehavior(Name = "EchoService", Namespace = "https://samples.microsoft.com/ServiceModel/Relay/")]
class EchoService : IEchoContract
{
public string Echo(string text)
{
Console.WriteLine("Echoing: {0}", text);
return text;
}
}
```
The following code shows the basic format of the *App.config* file associated with the service host.
```xml
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="Microsoft.ServiceBus.Samples.EchoService">
<endpoint contract="Microsoft.ServiceBus.Samples.IEchoContract" binding="netTcpRelayBinding" />
</service>
</services>
<extensions>
<bindingExtensions>
<add name="netTcpRelayBinding"
type="Microsoft.ServiceBus.Configuration.NetTcpRelayBindingCollectionElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</bindingExtensions>
</extensions>
</system.serviceModel>
</configuration>
```
## Host and run the WCF service to register with the relay service
This step describes how to run an Azure Relay service.
### Create the relay credentials
1. In `Main()`, create two variables in which to store the namespace and the SAS key that are read from the console window.
```csharp
Console.Write("Your Service Namespace: ");
string serviceNamespace = Console.ReadLine();
Console.Write("Your SAS key: ");
string sasKey = Console.ReadLine();
```
The SAS key will be used later to access your project. The namespace is passed as a parameter to `CreateServiceUri` to create a service URI.
1. Using a [TransportClientEndpointBehavior](/dotnet/api/microsoft.servicebus.transportclientendpointbehavior) object, declare that you'll be using an SAS key as the credential type. Add the following code directly after the code added in the last step.
```csharp
TransportClientEndpointBehavior sasCredential = new TransportClientEndpointBehavior();
sasCredential.TokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider("RootManageSharedAccessKey", sasKey);
```
### Create a base address for the service
After the code you added in the previous section, create a `Uri` instance for the base address of the service. This URI specifies the Service Bus scheme, the namespace, and the path of the service interface.
```csharp
Uri address = ServiceBusEnvironment.CreateServiceUri("sb", serviceNamespace, "EchoService");
```
The value "sb" is an abbreviation for the Service Bus scheme. It indicates that we're using TCP as the protocol. This scheme was also previously indicated in the configuration file, when [NetTcpRelayBinding](/dotnet/api/microsoft.servicebus.nettcprelaybinding) was specified as the binding.
For this tutorial, the URI is `sb://putServiceNamespaceHere.windows.net/EchoService`.
### Create and configure the service host
1. Still working in `Main()`, set the connectivity mode to `AutoDetect`.
```csharp
ServiceBusEnvironment.SystemConnectivity.Mode = ConnectivityMode.AutoDetect;
```
The connectivity mode describes the protocol the service uses to communicate with the relay service; either HTTP or TCP. Using the default setting `AutoDetect`, the service attempts to connect to Azure Relay over TCP if it's available, and HTTP if TCP isn't available. This result differs from the protocol the service specifies for client communication. That protocol is determined by the binding used. For example, a service can use the [BasicHttpRelayBinding](/dotnet/api/microsoft.servicebus.basichttprelaybinding) binding, which specifies that its endpoint communicates with clients over HTTP. That same service could specify `ConnectivityMode.AutoDetect` so that the service communicates with Azure Relay over TCP.
1. Create the service host, using the URI created earlier in this section.
```csharp
ServiceHost host = new ServiceHost(typeof(EchoService), address);
```
The service host is the WCF object that instantiates the service. Here, you pass it the type of service you want to create, an `EchoService` type, and also to the address at which you want to expose the service.
1. At the top of the *Program.cs* file, add references to [System.ServiceModel.Description](/dotnet/api/system.servicemodel.description) and [Microsoft.ServiceBus.Description](/dotnet/api/microsoft.servicebus.description).
```csharp
using System.ServiceModel.Description;
using Microsoft.ServiceBus.Description;
```
1. Back in `Main()`, configure the endpoint to enable public access.
```csharp
IEndpointBehavior serviceRegistrySettings = new ServiceRegistrySettings(DiscoveryType.Public);
```
This step informs the relay service that your application can be found publicly by examining the Atom feed for your project. If you set `DiscoveryType` to `private`, a client could still access the service. However, the service wouldn't appear when it searches the `Relay` namespace. Instead, the client would have to know the endpoint path beforehand.
1. Apply the service credentials to the service endpoints defined in the *App.config* file:
```csharp
foreach (ServiceEndpoint endpoint in host.Description.Endpoints)
{
endpoint.Behaviors.Add(serviceRegistrySettings);
endpoint.Behaviors.Add(sasCredential);
}
```
As stated previously, you could have declared multiple services and endpoints in the configuration file. If you had, this code would traverse the configuration file and search for every endpoint to which it should apply your credentials. For this tutorial, the configuration file has only one endpoint.
### Open the service host
1. Still in `Main()`, add the following line to open the service.
```csharp
host.Open();
```
1. Inform the user that the service is running, and explain how to shut down the service.
```csharp
Console.WriteLine("Service address: " + address);
Console.WriteLine("Press [Enter] to exit");
Console.ReadLine();
```
1. When finished, close the service host.
```csharp
host.Close();
```
1. Select Ctrl+Shift+B to build the project.
### Example that hosts a service in a console application
Your completed service code should appear as follows. The code includes the service contract and implementation from previous steps in the tutorial, and hosts the service in a console application.
```csharp
using System;
using System.ServiceModel;
using System.ServiceModel.Description;
using Microsoft.ServiceBus;
using Microsoft.ServiceBus.Description;
namespace Microsoft.ServiceBus.Samples
{
[ServiceContract(Name = "IEchoContract", Namespace = "https://samples.microsoft.com/ServiceModel/Relay/")]
public interface IEchoContract
{
[OperationContract]
String Echo(string text);
}
public interface IEchoChannel : IEchoContract, IClientChannel { };
[ServiceBehavior(Name = "EchoService", Namespace = "https://samples.microsoft.com/ServiceModel/Relay/")]
class EchoService : IEchoContract
{
public string Echo(string text)
{
Console.WriteLine("Echoing: {0}", text);
return text;
}
}
class Program
{
static void Main(string[] args)
{
ServiceBusEnvironment.SystemConnectivity.Mode = ConnectivityMode.AutoDetect;
Console.Write("Your Service Namespace: ");
string serviceNamespace = Console.ReadLine();
Console.Write("Your SAS key: ");
string sasKey = Console.ReadLine();
// Create the credentials object for the endpoint.
TransportClientEndpointBehavior sasCredential = new TransportClientEndpointBehavior();
sasCredential.TokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider("RootManageSharedAccessKey", sasKey);
// Create the service URI based on the service namespace.
Uri address = ServiceBusEnvironment.CreateServiceUri("sb", serviceNamespace, "EchoService");
// Create the service host reading the configuration.
ServiceHost host = new ServiceHost(typeof(EchoService), address);
// Create the ServiceRegistrySettings behavior for the endpoint.
IEndpointBehavior serviceRegistrySettings = new ServiceRegistrySettings(DiscoveryType.Public);
// Add the Relay credentials to all endpoints specified in configuration.
foreach (ServiceEndpoint endpoint in host.Description.Endpoints)
{
endpoint.Behaviors.Add(serviceRegistrySettings);
endpoint.Behaviors.Add(sasCredential);
}
// Open the service.
host.Open();
Console.WriteLine("Service address: " + address);
Console.WriteLine("Press [Enter] to exit");
Console.ReadLine();
// Close the service.
host.Close();
}
}
}
```
## Create a WCF client for the service contract
The next task is to create a client application and define the service contract you'll implement later. These steps resemble the steps used to create a service: defining a contract, editing an *App.config* file, using credentials to connect to the relay service, and so on. The code used for these tasks is provided in the example following the procedure.
1. Create a new project in the current Visual Studio solution for the client:
1. In **Solution Explorer**, right-click the current solution (not the project), and select **Add** > **New Project**.
1. In **Add a new project**, select **Console App (.NET Framework)** for C#, and select **Next**.
1. Specify *EchoClient* as the name of the project and select **Create**.
1. In **Solution Explorer**, in the **EchoClient** project, double-click **Program.cs** to open the file in the editor, if it isn't already open.
1. Change the namespace name from its default name of `EchoClient` to `Microsoft.ServiceBus.Samples`.
1. Install the [Service Bus NuGet package](https://www.nuget.org/packages/WindowsAzure.ServiceBus):
1. In **Solution Explorer**, right-click **EchoClient** and then select **Manage NuGet Packages**.
1. Select **Browse**, then search for and select **WindowsAzure.ServiceBus**. Select **Install**, and accept the terms of use.
![Install service bus package][4]
1. Add a `using` statement for the [System.ServiceModel](/dotnet/api/system.servicemodel) namespace in the *Program.cs* file.
```csharp
using System.ServiceModel;
```
1. Add the service contract definition to the namespace, as shown in the following example. This definition is identical to the definition used in the **Service** project. Add this code at the top of the `Microsoft.ServiceBus.Samples` namespace.
```csharp
[ServiceContract(Name = "IEchoContract", Namespace = "https://samples.microsoft.com/ServiceModel/Relay/")]
public interface IEchoContract
{
[OperationContract]
string Echo(string text);
}
public interface IEchoChannel : IEchoContract, IClientChannel { }
```
1. Select Ctrl+Shift+B to build the client.
### Example of the EchoClient project
The following code shows the current status of the *Program.cs* file in the **EchoClient** project.
```csharp
using System;
using Microsoft.ServiceBus;
using System.ServiceModel;
namespace Microsoft.ServiceBus.Samples
{
[ServiceContract(Name = "IEchoContract", Namespace = "https://samples.microsoft.com/ServiceModel/Relay/")]
public interface IEchoContract
{
[OperationContract]
string Echo(string text);
}
public interface IEchoChannel : IEchoContract, IClientChannel { }
class Program
{
static void Main(string[] args)
{
}
}
}
```
## Configure the WCF client
In this step, you create an *App.config* file for a basic client application that accesses the service created previously in this tutorial. This *App.config* file defines the contract, binding, and name of the endpoint. The code used for these tasks is provided in the example following the procedure.
1. In **Solution Explorer**, in the **EchoClient** project, double-click **App.config** to open the file in the Visual Studio editor.
1. In the `<appSettings>` element, replace the placeholders with the name of your service namespace, and the SAS key that you copied in an earlier step.
1. Within the `system.serviceModel` element, add a `<client>` element.
```xml
<?xmlversion="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<client>
</client>
</system.serviceModel>
</configuration>
```
This code declares that you're defining a WCF-style client application.
1. Within the `client` element, define the name, contract, and binding type for the endpoint.
```xml
<endpoint name="RelayEndpoint"
contract="Microsoft.ServiceBus.Samples.IEchoContract"
binding="netTcpRelayBinding"/>
```
This code defines the name of the endpoint. It also defines the contract defined in the service and the fact that the client application uses TCP to communicate with Azure Relay. The endpoint name is used in the next step to link this endpoint configuration with the service URI.
1. Select **File** > **Save All**.
### Example of the App.config file
The following code shows the *App.config* file for the Echo client.
```xml
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<client>
<endpoint name="RelayEndpoint"
contract="Microsoft.ServiceBus.Samples.IEchoContract"
binding="netTcpRelayBinding"/>
</client>
<extensions>
<bindingExtensions>
<add name="netTcpRelayBinding"
type="Microsoft.ServiceBus.Configuration.NetTcpRelayBindingCollectionElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</bindingExtensions>
</extensions>
</system.serviceModel>
</configuration>
```
## Implement the WCF client
In this section, you implement a basic client application that accesses the service you created previously in this tutorial. Similar to the service, the client does many of the same operations to access Azure Relay:
* Sets the connectivity mode.
* Creates the URI that locates the host service.
* Defines the security credentials.
* Applies the credentials to the connection.
* Opens the connection.
* Performs the application-specific tasks.
* Closes the connection.
However, one of the main differences is that the client application uses a channel to connect to the relay service. The service uses a call to **ServiceHost**. The code used for these tasks is provided in the example following the procedure.
### Implement a client application
1. Set the connectivity mode to `AutoDetect`. Add the following code inside the `Main()` method of the **EchoClient** application.
```csharp
ServiceBusEnvironment.SystemConnectivity.Mode = ConnectivityMode.AutoDetect;
```
1. Define variables to hold the values for the service namespace, and SAS key that are read from the console.
```csharp
Console.Write("Your Service Namespace: ");
string serviceNamespace = Console.ReadLine();
Console.Write("Your SAS Key: ");
string sasKey = Console.ReadLine();
```
1. Create the URI that defines the location of the host in your Relay project.
```csharp
Uri serviceUri = ServiceBusEnvironment.CreateServiceUri("sb", serviceNamespace, "EchoService");
```
1. Create the credential object for your service namespace endpoint.
```csharp
TransportClientEndpointBehavior sasCredential = new TransportClientEndpointBehavior();
sasCredential.TokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider("RootManageSharedAccessKey", sasKey);
```
1. Create the channel factory that loads the configuration described in the *App.config* file.
```csharp
ChannelFactory<IEchoChannel> channelFactory = new ChannelFactory<IEchoChannel>("RelayEndpoint", new EndpointAddress(serviceUri));
```
A channel factory is a WCF object that creates a channel through which the service and client applications communicate.
1. Apply the credentials.
```csharp
channelFactory.Endpoint.Behaviors.Add(sasCredential);
```
1. Create and open the channel to the service.
```csharp
IEchoChannel channel = channelFactory.CreateChannel();
channel.Open();
```
1. Write the basic user interface and functionality for the echo.
```csharp
Console.WriteLine("Enter text to echo (or [Enter] to exit):");
string input = Console.ReadLine();
while (input != String.Empty)
{
try
{
Console.WriteLine("Server echoed: {0}", channel.Echo(input));
}
catch (Exception e)
{
Console.WriteLine("Error: " + e.Message);
}
input = Console.ReadLine();
}
```
The code uses the instance of the channel object as a proxy for the service.
1. Close the channel, and close the factory.
```csharp
channel.Close();
channelFactory.Close();
```
### Example code for this tutorial
Your completed code should appear as follows. This code shows how to create a client application, how to call the operations of the service, and how to close the client after the operation call is finished.
```csharp
using System;
using Microsoft.ServiceBus;
using System.ServiceModel;
namespace Microsoft.ServiceBus.Samples
{
[ServiceContract(Name = "IEchoContract", Namespace = "https://samples.microsoft.com/ServiceModel/Relay/")]
public interface IEchoContract
{
[OperationContract]
String Echo(string text);
}
public interface IEchoChannel : IEchoContract, IClientChannel { }
class Program
{
static void Main(string[] args)
{
ServiceBusEnvironment.SystemConnectivity.Mode = ConnectivityMode.AutoDetect;
Console.Write("Your Service Namespace: ");
string serviceNamespace = Console.ReadLine();
Console.Write("Your SAS Key: ");
string sasKey = Console.ReadLine();
Uri serviceUri = ServiceBusEnvironment.CreateServiceUri("sb", serviceNamespace, "EchoService");
TransportClientEndpointBehavior sasCredential = new TransportClientEndpointBehavior();
sasCredential.TokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider("RootManageSharedAccessKey", sasKey);
ChannelFactory<IEchoChannel> channelFactory = new ChannelFactory<IEchoChannel>("RelayEndpoint", new EndpointAddress(serviceUri));
channelFactory.Endpoint.Behaviors.Add(sasCredential);
IEchoChannel channel = channelFactory.CreateChannel();
channel.Open();
Console.WriteLine("Enter text to echo (or [Enter] to exit):");
string input = Console.ReadLine();
while (input != String.Empty)
{
try
{
Console.WriteLine("Server echoed: {0}", channel.Echo(input));
}
catch (Exception e)
{
Console.WriteLine("Error: " + e.Message);
}
input = Console.ReadLine();
}
channel.Close();
channelFactory.Close();
}
}
}
```
## Run the applications
1. Select Ctrl+Shift+B to build the solution. This action builds both the client project and the service project that you created in the previous steps.
1. Before running the client application, you must make sure that the service application is running. In **Solution Explorer**, right-click the **EchoService** solution, then select **Properties**.
1. In **Property Pages**, **Common Properties** > **Startup Project**, then choose **Multiple startup projects**. Make sure **EchoService** appears first in the list.
1. Set the **Action** box for both the **EchoService** and **EchoClient** projects to **Start**.
![Project property pages][5]
1. Select **Project Dependencies**. In **Projects**, select **EchoClient**. For **Depends on**, make sure **EchoService** is selected.
![Project dependencies][6]
1. Select **OK** to close **Property Pages**.
1. Select F5 to run both projects.
1. Both console windows open and prompt you for the namespace name. The service must run first, so in the **EchoService** console window, enter the namespace and then select Enter.
1. Next, the console prompts you for your SAS key. Enter the SAS key and select Enter.
Here's example output from the console window. The values here are just examples.
`Your Service Namespace: myNamespace`
`Your SAS Key: <SAS key value>`
The service application prints to the console window the address on which it's listening, as seen in the following example.
`Service address: sb://mynamespace.servicebus.windows.net/EchoService/`
`Press [Enter] to exit`
1. In the **EchoClient** console window, enter the same information that you entered previously for the service application. Enter the same service namespace and SAS key values for the client application.
1. After you enter these values, the client opens a channel to the service and prompts you to enter some text as seen in the following console output example.
`Enter text to echo (or [Enter] to exit):`
Enter some text to send to the service application and select Enter. This text is sent to the service through the Echo service operation and appears in the service console window as in the following example output.
`Echoing: My sample text`
The client application receives the return value of the `Echo` operation, which is the original text, and prints it to its console window. The following text is example output from the client console window.
`Server echoed: My sample text`
1. You can continue sending text messages from the client to the service in this manner. When you're finished, select Enter in the client and service console windows to end both applications.
## Next step
Advance to the following tutorial:
> [!div class="nextstepaction"]
>[Expose an on-premises WCF REST service to a client outside your network](service-bus-relay-rest-tutorial.md)
[2]: ./media/service-bus-relay-tutorial/configure-echoservice-console-app.png
[3]: ./media/service-bus-relay-tutorial/install-nuget-service-bus.png
[4]: ./media/service-bus-relay-tutorial/install-nuget-service-bus-client.png
[5]: ./media/service-bus-relay-tutorial/set-projects.png
[6]: ./media/service-bus-relay-tutorial/set-depend.png