Creating a simple Data Entry Application Part 2 of 2

In this two part post we will create a simple data entry application that will provide the following functionality.

  • A page that will allow the user to enter the information regarding the recruiter and whether a call back or email is required
  • A validation page which will validate the information entered.
  • A page that will confirm whether you need to call back the recruiter or not and the details for this recruiter
  • A page that list all the recruiters that have called and whether I needed to call them back or send them a email or not

See Creating a simple Data Entry Application Part 1 of 2 for information on the first page of this tutorial.

The second part of this tutorial will deal with creating a summary page, dynamic html, calling a code behind method from the page and model validation.

Summary Page

The purpose of the summary page is to see all the recruiters who have contacted me and whether a call back is required or not. So lets create a summary page showing this information.

Continue reading

Creating a simple Data Entry Application Part 1 of 2

In this two part post we will create a simple data entry application that will provide the following functionality.

  • A page that will allow the user to enter the information regarding the recruiter and whether a call back or email is required
  • A validation page which will validate the information entered.
  • A page that will confirm whether you need to call back the recruiter or not and the details for this recruiter
  • A page that list all the recruiters that have called and whether I needed to call them back or send them a email or not

The first part of this tutorial will deal with creating the data model and repository and creating the page to enter the user information and creating the validation page.

Creating the application

So as before go to Add New Project and select ASP.NET Empty Web Application. and give it the name RecruiterContacts

Creating the Data Model and Repository

In this example we will create the Data model that will store the recruiter information and a repository that will store all the recruiters that have contacted me. Since this is a simple example, we will not store the repository in a Database it will just stay in memory and will be discarded once the application is ended or timed out.

Recruiter.cs

Before creating this class, firstly create a new folder and call it Model. Next add a new class in there called Recruiter and add the following code to it.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace RecruiterContacts.Model
{
public class Recruiter
{
public string Company { get; set; }
public string Name {get;set;}
public string URL { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
public bool? ContactThem { get; set; }
}
}

This is the model that will be used, next lets create the Repository where we will store the recruiters added.

RecruiterRepository.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace RecruiterContacts.Model
{
public class RecruiterRepository
{
private static RecruiterRepository repository = new RecruiterRepository();
private List Recruiters = new List();

public static RecruiterRepository GetRepository()
{
return repository;
}

public IEnumerable GetAllRecruiters()
{
return Recruiters;
}

public void AddRecruiter(Recruiter recruit)
{
Recruiters.Add(recruit);
}
}
}

Now that the repository is done the next thing to do is to create the web form where we will enter the recruiter details.

Default.aspx

Create a new web form called Default.aspx and add the following code to it.

<%@ Page Language=”C#” AutoEventWireup=”true” CodeBehind=”Default.aspx.cs” Inherits=”RecruiterContacts.Default” %>

<!DOCTYPE html>

<html xmlns=”http://www.w3.org/1999/xhtml”&gt;
<head runat=”server”>
<title></title>
</head>
<body>
<form id=”recruiterform” runat=”server”>
<div>
<h1>Recruiter Information</h1>
</div>
<div>
<label>Company:</label>
<input type=”text” id=”company” />
</div>
<div>
<label>Name:</label>
<input type=”text” id=”name” />
</div>
<div>
<label>URL:</label>
<input type=”text” id=”URL” />
</div>
<div>
<label>Phone Number:</label>
<input type=”text” id=”phone” />
</div>
<div>
<label>Email:</label>
<input type=”text” id=”email” />
</div>
<div>
<label>Contact Them?</label>
<select id=”contactedthem”>
<option value=””>Choose an Option</option>
<option value=”true”>Yes</option>
<option value=”false”>No</option>
</select>
</div>
<div>
<button type=”submit”>Submit Recruiter</button>
</div>
</form>
</body>
</html>

Lets just go over a few things with this page.

Firstly the very first line is used to specify the language to use, i.e. C#, whether the auto event is turned on and the code behind class to use.

Next the form declaration has been given the id recruiterform, which we will use later for the CSS and as usual we have runat=”server”, if this was not there then the form would not work.

Then for each of the member variables in the recruiter class, there is a corresponding label and input html tag allowing the user to enter these values.

The select tag is used as a drop down to allow the user to select either true or false for whether the user has contacted them or not.

Finally we have a submit button, which will post the page back to the server passing the results back as viewstate.

So build the application and run. As you can see there is nothing special in how the app looks and if you click the button nothing is currently happening it is just posting back to the same page.

Also it looks crappy, its like a classic html page that was created long back, so lets add a bit of CSS to make it better

Styles.css

Add a new style sheet called Styles.css and add the following to it


#recruiterform label {
width: 120px;
display: inline-block;
}

#recruiterform input {
margin: 2px;
margin-left: 4px;
width: 150px;
}

#recruiterform select {
margin: 2px;
margin-left: 4px;
width: 154px;
}

button[type=submit] {
margin-top: 5px;
}

What this does is to format the labels, input, select and button to use these styles when rendering the HTML to the page.

Now to make this work we have to tell the page to use this new style sheet.

Default.aspx

Update the page as follows

<%@ Page Language=”C#” AutoEventWireup=”true” CodeBehind=”Default.aspx.cs” Inherits=”RecruiterContacts.Default” %>

<!DOCTYPE html>

<html xmlns=”http://www.w3.org/1999/xhtml”&gt;
<head runat=”server”>
<title></title>
<link rel=”stylesheet” href=”Styles.css” />
</head>

As you can see we have told the page to use the stylesheet Styles.css. So if you run the application again you will see that the inputs, drop down and button are all lined up correctly.

Model Binding

I will get into model binding in another tutorial, lets just say the point of it is to allow the binding of html tags with actual model data. This is similar in a Winform when you can bind a collection to the datasource of the datagridview, which then enumerates through this collection and displays the collections data.

The advantage of this is obvious, if this was not possible the only way to figure out what was in the Html tag would be to interrogate them one by one and extract the data required.

Postback to the Page

So to demonstrate this we will show how Postback works. Postback is when the user wants to postback to the server a change that requires some kind of validation or response. In most cases this is when a button is pressed. So usually when a button is pressed a postback is generated and posted back to the server, when this happens the code behind file Load method is called, there are other functions called as well, but for now I am keeping this simple, Within the Load method we have to decide whether the call is a postback or just the start of the page being processed by the server, this is done using the IsPostback property that is supported by the Page class. So lets have a quick look at the code that will handle the postback and will perform the model binding.

Default.aspx.cs


using RecruiterContacts.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.ModelBinding;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace RecruiterContacts
{
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
Recruiter recruit = new Recruiter();
if (TryUpdateModel(recruit,
new FormValueProvider(ModelBindingExecutionContext)))

{
RecruiterRepository.GetRepository().AddRecruiter(recruit);
if (recruit.ContactedThem.HasValue && recruit.ContactedThem.Value)
{
Response.Redirect(“youhavecontactedthem.html”);
}
else
{
Response.Redirect(“youneedtocallthem.html”);
}

}
}
}
}
}

So you can see in the page there are few things to discuss

The first is the IsPostback member variable, this is used to discover whether this is a postback or not and from this will handle the postback rather than the startup of the page.

The next thing to look at is TryUpdateModel, the purpose of this method is to allow the binding of the form data into the model data directly without having to do this yourself. The secret to how this works is that the names of the input and selects are the same as the Recruiter model class meaning this method would use some kind of reflection to figure out which property matches to which html tab and then set the model data with the html tag data.

The final thing to look at is the checking of the ContactedThem property. In that if the value is set to yes or no then a page will be displayed to the user informing them of the decision, if it is not set then no page is displayed.

So lets run the app, enter the company, name, url, etc and choose whether you contacted them or not and click the submit button. Right now when you click the submit button you will see that an error is thrown because we did not create the html pages yet, however if you look at the page that it tried to display it is youneedtocallthem.html. Why is this page being called since it should have some values, well lets check it out.

Put a breakpoint on the line highlighted below


if (IsPostBack)
{
Recruiter recruit = new Recruiter();
if (TryUpdateModel(recruit,
new FormValueProvider(ModelBindingExecutionContext)))

{
RecruiterRepository.GetRepository().AddRecruiter(recruit);
if (recruit.ContactedThem.HasValue && recruit.ContactedThem.Value)
{
Response.Redirect("youhavecontactedthem.html");
}
else
{
Response.Redirect("youneedtocallthem.html");
}
}
}

Run the app again, enter the values and then when it hits the breakpoint press F10 to step over the line. If you look at the recruit class it shows that all the values in there are null, why is that. Well the problem is that if you look at the Default.aspx page and all the input html tags they are missing something vital the runat=”server’ attribute. Without this the tag is not processed on the server and ignored meaning it display correctly on the client. but the server does not care about it, hence the model binding will fail.

To overcome this issue lets alter the Default.aspx page as follows.

Default.aspx

<%@ Page Language=”C#” AutoEventWireup=”true” CodeBehind=”Default.aspx.cs” Inherits=”RecruiterContacts.Default” %>

<!DOCTYPE html>

<html xmlns=”http://www.w3.org/1999/xhtml”&gt;
<head runat=”server”>
<title></title>
<link rel=”stylesheet” href=”Styles.css” />
</head>
<body>
<form id=”recruiterform” runat=”server”>
<div>
<h1>Recruiter Information</h1>
</div>
<div>
<label>Company:</label>
<input type=”text” id=”company” runat=”server” />
</div>
<div>
<label>Name:</label>
<input type=”text” id=”name” runat=”server” />
</div>
<div>
<label>URL:</label>
<input type=”text” id=”URL” runat=”server” />
</div>
<div>
<label>Phone Number:</label>
<input type=”text” id=”phone” runat=”server” />
</div>
<div>
<label>Email:</label>
<input type=”text” id=”email” runat=”server” />
</div>
<div>
<label>Contacted Them?</label>
<select id=”contactedthem” runat=”server”>
<option value=””>Choose an Option</option>
<option value=”true”>Yes</option>
<option value=”false”>No</option>
</select>
</div>
<div>
<button type=”submit”>Submit Recruiter</button>
</div>
</form>
</body>
</html>

Now run the application and enter the same values, this time we still get the error, but now we see that the other page is being requested.

Lets fix the error add the following 2 html pages

youhavecontactedthem.html

<!DOCTYPE html>
<html xmlns=”http://www.w3.org/1999/xhtml”&gt;
<head>
<title>Contacted Them</title>
</head>
<body>
<p>You have already contacted them</p>
</body>
</html>

youneedtocallthem.html

<!DOCTYPE html>
<html xmlns=”http://www.w3.org/1999/xhtml”&gt;
<head>
<title>Call Them</title>
</head>
<body>
<p>You need to call them back</p>
</body>
</html>

If you run the app now and select Yes then you will see that the you need to call them page will appear otherwise the other one will.

Conclusion

This concludes the first part of this tutorial on creating a simple data entry application, in the 2nd part of this tutorial we will create a summary page, validation, dynamic HTML, calling code behind members from the page and creating model validation.

Creating a hello World ASP.NET application

In the following example we will create a very basic ASP.NET application that will present to the user a Hello World web page when it is run.

This blog will assume that the user has installed the Visual Studio 2012 Express Edition for the Web.

Creating the project

Once the VS2012 application is open the first decision is which project to use when creating the application. There are a number of choices as shown below.

New Project ASP.NET

To make our lives easy choose the top one, which is ASP.NET Empty Web Application. As the name suggests this will have no web pages within it. Give it the Name HelloWorld

Once you click OK the project will be created and you will see the only thing in there would be a Web.config file

Creating the Default.aspx page

Since there is no webpage within it, if you tried to run the application you would get nothing, well that is not technically true, if you try it you would get an error saying that you cannot list out the files in the application.

So to show the Hello World lets create a aspx page, so Right mouse click the project and add new Web Form and call it Default and click OK. Once you have done this the Default.aspx page will open allowing you to modify anything within it.

Now run the application again, the error that we got before has gone and we have a blank page. If you look at the address bar you can see that it is using the Default.aspx as the page to go to, how did it know to go to this page?

Well lets do a little experiment change the name of the file from Default.aspx to Test.aspx and make sure to close the aspx page so no pages are displayed in the VS2012 IDE and run the application again. Now when you run you will see the same error message as before that it cannot list the files.
NOTE: If you leave the Test.aspx page open and run VS2012 will use this page as its default page and will work as expected

So whats going on, by default a ASP.NET application will always default to the default.aspx page, big shock there right 🙂 So if you do not name any aspx file Default.aspx then you will get this error regarding the listing. One way round this would be to do the following.

Right mouse click the Test.aspx file and select the menu option Set as Start Page soon as you do this when you run the app it defaults to the Test web page. What it actually does is in the project settings there is a Start Action settings, in there you can specify the default page that can be launched. So in this case Specific Page is checked and the name Test.aspx is set, so now when it runs it will launch that page.

Web Project Settings

Returning Hello World to the Web Page

The final part of this example is to return Hello World to the user. If you open up the Test.aspx you can see the following HTML

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Test.aspx.cs" Inherits="HelloWorld.Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml"&gt;
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>

</div>
</form>
</body>
</html>

Within the <div> tags add the following

Hello World

Now run the application again, you should see the Hello World displayed in the page.

Conclusion

This concludes the example of creating a basic ASP.NET application, in the next example we will create a simple Data Entry application that will store a list of recruiters that are calling the recruitee and whether the recruitee actually followed up with the recruiter or not or whether the job offer was not the right fit.

Host a WCF Service with multiple endpoints Part 7 of 7

In this 7 part example I will detail how to create, host and communicate with a WCF service that has multiple endpoints.

  • In this first example I will show how to create and host a WCF service with multiple endpoints
  • In the second example I will show how to create and host a WCF service with multiple endpoints using code rather than a config file
  • In the third example I will show how to enable the Metadata Exchange also called MEXGET
  • In the fouth example I will show how to enable the Metadata Exchange also called MEXGET using code rather than a config file
  • In the fifth example I will show how to enable metadata exchange using a dedicated endpoint also called MEX
  • In the sixth example I will show how to enable metadata exchange using a dedicated endpoint also called MEX using code rather than a config file
  • In the seventh example I will show how to create a client to connect to all these endpoints.

Finally we get to the final example in this seven part series. I know you are exhausted from reading through the examples and I am sure you have much better things to do than read my blog, but hey I did spend my precious time writing this so at least you could read it, sorry off on a tangent there.

Anyway where was I, yes we are at the final part of this example the client. Obviously there is no point creating a WCF service without actually using it. So we will create a client to talk to this service.

However before we start we have an issue, it seems that we have two services that we created throughout these examples, so how are we going to be able to add both of them and talk to both of them at the same time.

Well the easy way and the way I would do it because I am lazy would be to create two console applications that each hosted one of the services. As well as being the lazy way it is the better way because if one of the services fails for any reason the other one will not be affected since they are in different processes.

So to make this work we have to tweak the current code we have in the service and add a key in the config file.

WCFExampleService

So open up the app.config file and add an appsettings section and add the following key.

app.config

<?xml version=”1.0″ encoding=”utf-8″ ?>
<configuration>
<appSettings>
<add key=”service” value=”ExampleService”/>
</appSettings>

<startup>

We will use this configuration value to decide which service to run.

Now open up the Program.cs and make the following changes

Program.cs

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
using WCFExampleService;

namespace WcfHostMultiEndpoints
{
class Program
{
static void Main(string[] args)
{
string serviceName = ConfigurationManager.AppSettings[“service”] as string;

if (string.IsNullOrEmpty(serviceName) || serviceName == “ExampleService”)
{
try
{
using (ServiceHost host = new ServiceHost(typeof(ExampleService)))
{
host.Open();
Console.WriteLine(“Press to terminate the Host application.”);
Console.ReadLine();
}
}
catch (CommunicationException ce)
{
Console.WriteLine(“An exception occurred: {0}”, ce.Message);
}
}
else
{
try
{
using (ServiceHost host = new ServiceHost(typeof(ExampleService2)))
{
host.Open();
Console.WriteLine(“Press to terminate the Host application.”);
Console.ReadLine();
}
}
catch (CommunicationException ce)
{
Console.WriteLine(“An exception occurred: {0}”, ce.Message);
}
}

}
}
}

Yes I know, this code is horribly an abomination, you should be ashamed of yourself for writing it, yes I know all these things, but hey this is my blog you don’t like it go write your own blog :). The only reason for writing the code like this is so that we can run the same EXE twice and then just tweak the config file so that the other service would load. So lets do that.

Build the application and then run the EXE, then change the config value ExampleService to ExampleService2 and run the EXE again. You should now have two exe’s running hosting two different services.

So we have our services ready, the next thing to do is to create our client to talk to these services.

MultiServiceClientApp

So lets create the client app, firstly create a new console app calling it MultiServiceClientApp.

No we get to the fun part lets add the Service References. Errr, which ones. Well if we look at the app.config we can see there are lots of endpoints we can connect to, so what we can do is start the add them one by one.

Lets start with the Example Service, it has 4 endpoints, 2 are http and 2 are tcp. Since both the http ones are using the base address then lets start with those.

Right mouse click the project and select the Add Service reference and put the address

http://localhost:3000/

After it spins its wheels for a few minutes it finally finds the service and displays the interfaces that we have implemented IExampleService and IExampleService2. So add this service and in the namespace edit box set the name as ClientServiceReference.

So now the next thing we will do is also add the TCP versions of these for ExampleService service, so we again add the Add Service Reference and add the following address

net.tcp://localhost:3001/ExampleService

Hmmm, it did not work, says it cannot find the service, why is this. Well if you look in the ServiceBehavior tags in the config file for the MEXGET behavior you will notice that the httpGetEnabled tag is set to true. From the name you can realize that it only supports Http and not Tcp. So that means we cannot add the Tcp services using Add Service Reference or for that matter using SvcUtil since they are not exposing their metadata. So why did you make us write them if we can’t even use them. :(. Calm down you can still use them, its just that to use them you can’t get Visual Studio to do all the work for you, you have to figure it out yourself. I know that sucks right having to do the work yourself. Anyway I will show you how to do it since I am such a nice guy later in the post.

Next we will move to the other service ExampleService2. Again select Add Service Reference and add the following address.

http://localhost:4000

Again it spins its wheels and adds the service, this time give the namespace name of ClientServiceReferenceExample2Http. Sorry for the long name, just wanted to make sure that we could distinguish which one is which.

Now lets try and add the next address

net.tcp://localhost:5000

Wait a minute, I am not falling for that again, we tried that last time and it did not work, what you think I am stupid or something :). No not at all, 😉 The difference this time is that for this service we have set up a specific endpoint to handle this, so give it a try.

It worked it is showing the service. Use the namespace of ClientServiceReferenceEndpoint2NetTcp. I know the name is too long, just wanted to distinguish which is which.

So now we have our three endpoints available to use, cool 🙂

So lets be daring and try and connect to them.

Open the Program.cs file and add the following code.

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MultiServiceClientApp
{
class Program
{
static void Main(string[] args)
{
// Connect to the ExampleService HTTP service
ClientServiceReference.ExampleService2Client client2 = new ClientServiceReference.ExampleService2Client();
bool result = client2.ExampleMethod2();

ClientServiceReference.ExampleServiceClient client1 = new ClientServiceReference.ExampleServiceClient();
bool result2 = client1.ExampleMethod();

// Connect to the Example2 HTTP Service
ClientServiceReferenceExample2Http.ExampleService2Client client2Http = new ClientServiceReferenceExample2Http.ExampleService2Client();
bool result3 = client2Http.ExampleMethod2();

ClientServiceReferenceExample2Http.ExampleServiceClient client1Http = new ClientServiceReferenceExample2Http.ExampleServiceClient();
bool result4 = client1Http.ExampleMethod();

// Connect to the Example2 TCP Service
ClientServiceReferenceEndpoint2NetTcp.ExampleService2Client client2Tcp = new ClientServiceReferenceEndpoint2NetTcp.ExampleService2Client();
bool result5 = client2Tcp.ExampleMethod2();

ClientServiceReferenceEndpoint2NetTcp.ExampleServiceClient client1Tcp = new ClientServiceReferenceEndpoint2NetTcp.ExampleServiceClient();
bool result6 = client1Tcp.ExampleMethod();
}
}
}

Run it and, err well it does not work. It is complaining that the there is more than one endpoint configuration with that name. Hmmm, how are we going to get round this, well the thing with the Add Service Reference way of doing things is that it does just that it adds a service reference and also updates the app.config. The problem is since we are using the same interface for multiple endpoints then it does not know which is which, the good thing is that the client class that is generated has a constructor where you can pass the endpoint configuration name. So where do we get this amazing name and where did we create it, well if you look at your app.config now you should see this.

app.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="NetTcpBinding_IExampleService2" />
<binding name="NetTcpBinding_IExampleService" />
<binding name="NetTcpBinding_IExampleService21" />
<binding name="NetTcpBinding_IExampleService22" />
</netTcpBinding>
<wsHttpBinding>
<binding name="WSHttpBinding_IExampleService" />
<binding name="WSHttpBinding_IExampleService2" />
<binding name="WSHttpBinding_IExampleService1" />
<binding name="WSHttpBinding_IExampleService3" />
</wsHttpBinding>

</bindings>
<client>
<endpoint address="http://localhost:3000/&quot; binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IExampleService" contract="ClientServiceReference.IExampleService"
name="WSHttpBinding_IExampleService">
<identity>
<userPrincipalName value="Windows7PC\robert" />
</identity>
</endpoint>
<endpoint address="http://localhost:3000/&quot; binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IExampleService2" contract="ClientServiceReference.IExampleService2"
name="WSHttpBinding_IExampleService2">
<identity>
<userPrincipalName value="Windows7PC\robert" />
</identity>
</endpoint>
<endpoint address="net.tcp://localhost:3001/ExampleService" binding="netTcpBinding"
bindingConfiguration="NetTcpBinding_IExampleService2" contract="ClientServiceReference.IExampleService2"
name="NetTcpBinding_IExampleService2">
<identity>
<userPrincipalName value="Windows7PC\robert" />
</identity>
</endpoint>
<endpoint address="net.tcp://localhost:3002/ExampleService" binding="netTcpBinding"
bindingConfiguration="NetTcpBinding_IExampleService" contract="ClientServiceReference.IExampleService"
name="NetTcpBinding_IExampleService">
<identity>
<userPrincipalName value="Windows7PC\robert" />
</identity>
</endpoint>
<endpoint address="http://localhost:4000/ExampleService&quot; binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IExampleService1" contract="ClientServiceReferenceExample2Http.IExampleService"
name="WSHttpBinding_IExampleService1">
<identity>
<userPrincipalName value="Windows7PC\robert" />
</identity>
</endpoint>
<endpoint address="net.tcp://localhost:5000/ExampleService" binding="netTcpBinding"
bindingConfiguration="NetTcpBinding_IExampleService21" contract="ClientServiceReferenceExample2Http.IExampleService2"
name="NetTcpBinding_IExampleService21">
<identity>
<userPrincipalName value="Windows7PC\robert" />
</identity>
</endpoint>
<endpoint address="http://localhost:4000/ExampleService&quot; binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IExampleService3" contract="ClientServiceReferenceEndpoint2NetTcp.IExampleService"
name="WSHttpBinding_IExampleService3">
<identity>
<userPrincipalName value="Windows7PC\robert" />
</identity>
</endpoint>
<endpoint address="net.tcp://localhost:5000/ExampleService" binding="netTcpBinding"
bindingConfiguration="NetTcpBinding_IExampleService22" contract="ClientServiceReferenceEndpoint2NetTcp.IExampleService2"
name="NetTcpBinding_IExampleService22">
<identity>
<userPrincipalName value="Windows7PC\robert" />
</identity>
</endpoint>
</client>
</system.serviceModel>
</configuration>

As you can see Visual Studio was very nice and create a name for each of the endpoints, this allows us to tell the constructor the one we actually want. So change the code as follows.

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MultiServiceClientApp
{
class Program
{
static void Main(string[] args)
{
// Connect to the ExampleService HTTP service
ClientServiceReference.ExampleService2Client client2 = new ClientServiceReference.ExampleService2Client(“WSHttpBinding_IExampleService2”);
bool result = client2.ExampleMethod2();

ClientServiceReference.ExampleServiceClient client1 = new ClientServiceReference.ExampleServiceClient(“WSHttpBinding_IExampleService”);
bool result2 = client1.ExampleMethod();

// Connect to the Example2 HTTP Service
ClientServiceReferenceExample2Http.ExampleService2Client client2Http = new ClientServiceReferenceExample2Http.ExampleService2Client();
bool result3 = client2Http.ExampleMethod2();

ClientServiceReferenceExample2Http.ExampleServiceClient client1Http = new ClientServiceReferenceExample2Http.ExampleServiceClient();
bool result4 = client1Http.ExampleMethod();

// Connect to the Example2 TCP Service
ClientServiceReferenceEndpoint2NetTcp.ExampleService2Client client2Tcp = new ClientServiceReferenceEndpoint2NetTcp.ExampleService2Client();
bool result5 = client2Tcp.ExampleMethod2();

ClientServiceReferenceEndpoint2NetTcp.ExampleServiceClient client1Tcp = new ClientServiceReferenceEndpoint2NetTcp.ExampleServiceClient();
bool result6 = client1Tcp.ExampleMethod();
}
}
}

Run the application… it works, cool we are done…. O I better explain why it is working and why you only have to specify two endpoints names. Well the problem was that the app could not distinguish which interface was going where so by specifically telling it what to look for that solved the issue, however we have 4 other endpoints where we did not have to do this, well the other ones are on a different address, meaning that you do not need to worry about there being a conflict and so it will run without any issue.
Obviously this example only returns true or false depending on what you are calling, but it is doing it using multiple endpoints, bindings and services.

Conclusion

This concludes the 7 part series on hosting a WCF with multiple endpoints, if you made it to the end congratulations, you must like pain. Hopefully you gained an understanding on how to host a service with multiple endpoints and how you can access it from a client.

Host a WCF Service with multiple endpoints Part 6 of 7

In this 7 part example I will detail how to create, host and communicate with a WCF service that has multiple endpoints.

  • In this first example I will show how to create and host a WCF service with multiple endpoints
  • In the second example I will show how to create and host a WCF service with multiple endpoints using code rather than a config file
  • In the third example I will show how to enable the Metadata Exchange also called MEXGET
  • In the fouth example I will show how to enable the Metadata Exchange also called MEXGET using code rather than a config file
  • In the fifth example I will show how to enable metadata exchange using a dedicated endpoint also called MEX
  • In the sixth example I will show how to enable metadata exchange using a dedicated endpoint also called MEX using code rather than a config file
  • In the seventh example I will show how to create a client to connect to all these endpoints.

In the sixth part of this series I will do the same thing as the fifth example did, but this time use code rather than a configuration file.

WcfMultiEndpointsProgrammatically

We will change the Program.cs file to create a series of metadata endpoints that match what was created in the 5th example of this series.

Program.cs

Replace the current code with the following

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.Text;
using System.Threading.Tasks;
using WCFExampleService;

namespace WcfMultiEndpointsProgrammatically
{
class Program
{
static Uri[] baseAddresses = new Uri[2]
{new Uri(“http://localhost:4000/&#8221;),new Uri(“net.tcp://localhost:5000/”)};

static void Main(string[] args)
{
try
{
using (ServiceHost host = new ServiceHost(typeof(ExampleService2), baseAddresses))
{
SetUpBindingsAndEndPoints(host);
SetupMetadata(host);

host.Open();
Console.WriteLine(“Press to terminate the Host application.”);
Console.ReadLine();
}
}
catch (CommunicationException ce)
{
Console.WriteLine(“An exception occurred: {0}”, ce.Message);
}
}

static void SetUpBindingsAndEndPoints(ServiceHost host)
{
Binding wsBinding = new WSHttpBinding();
Binding tcpBinding = new NetTcpBinding();

//
host.AddServiceEndpoint(typeof(IExampleService), wsBinding, “ExampleService”);
//
host.AddServiceEndpoint(typeof(IExampleService2), tcpBinding, “ExampleService”);
}

static void SetupMetadata(ServiceHost host)
{
BindingElement bindingElementHttp = new HttpTransportBindingElement();
CustomBinding custBindHttp = new CustomBinding(bindingElementHttp);

BindingElement bindingElementTcp = new TcpTransportBindingElement();
CustomBinding custBindTcp = new CustomBinding(bindingElementTcp);

ServiceMetadataBehavior metadataBehavior;
metadataBehavior = host.Description.Behaviors.Find();
if (metadataBehavior == null)
{
metadataBehavior = new ServiceMetadataBehavior();
host.Description.Behaviors.Add(metadataBehavior);
}
host.AddServiceEndpoint(typeof(IMetadataExchange), custBindHttp, “MEX”);
host.AddServiceEndpoint(typeof(IMetadataExchange), custBindTcp, “MEX”);
}

}
}

The changes that are made are highlighted.

Firstly I have created an array of base addresses since in the app.config we had two base addresses one for the HTTP and one for the TCP.

Next in the SetUpBindingsAndEndPoints function I have removed two of the endpoints we are not going to use in this example.

Finally the biggest change is in the SetupMetadata function.

BindingElement bindingElementHttp = new HttpTransportBindingElement();
CustomBinding custBindHttp = new CustomBinding(bindingElementHttp);

BindingElement bindingElementTcp = new TcpTransportBindingElement();
CustomBinding custBindTcp = new CustomBinding(bindingElementTcp);

The purpose of these lines is to setup the binding needed to add with the metadata service points that’s why there is one for Http and one for Tcp

ServiceMetadataBehavior metadataBehavior;
metadataBehavior = host.Description.Behaviors.Find();
if (metadataBehavior == null)
{
metadataBehavior = new ServiceMetadataBehavior();
host.Description.Behaviors.Add(metadataBehavior);
}

These lines are as before the only difference is that we no longer need to enable the metedataBehavior so that line has been removed.

host.AddServiceEndpoint(typeof(IMetadataExchange), custBindHttp, “MEX”);
host.AddServiceEndpoint(typeof(IMetadataExchange), custBindTcp, “MEX”);

Finally we add the MEX endpoints for both the Http and Tcp using the custom binding we created above.

So now if you run the WcfTestClient and enter the following Uris

http://localhost:4000/
net.tcp://localhost:5000/

You will see the interfaces implemented using both TCP and Http

This will allow you to choose which binding method you would like to implement and adds more flexibility to the service.

Conclusion

This concludes this example regarding setting up metadata endpoints using code. In the final example we see how to create a client to connect to this service and make calls to their methods.

Host a WCF Service with multiple endpoints part 5 of 7

In this 7 part example I will detail how to create, host and communicate with a WCF service that has multiple endpoints.

  • In this first example I will show how to create and host a WCF service with multiple endpoints
  • In the second example I will show how to create and host a WCF service with multiple endpoints using code rather than a config file
  • In the third example I will show how to enable the Metadata Exchange also called MEXGET
  • In the fouth example I will show how to enable the Metadata Exchange also called MEXGET using code rather than a config file
  • In the fifth example I will show how to enable metadata exchange using a dedicated endpoint also called MEX
  • In the sixth example I will show how to enable metadata exchange using a dedicated endpoint also called MEX using code rather than a config file
  • In the seventh example I will show how to create a client to connect to all these endpoints.

This is part 5 of the series and deals with creating a dedicated endpoint to handle the metadata exchange.

I won’t go into too much details on what the metadata endpoint is doing, you can look to Microsoft to give you a much better explanation than me, the only thing I will say is that the service contract is called IMetadataExchange and it is an industry standard.

Anyway enough talk lets start coding.

Since I do not want to mess up the already created service we have in the previous example, we will create a brand new service to allow us to demonstrate how the metadata exchange works.

WCFExampleService

Update the app.config of the WCFExampleService as follows.

app.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.web>
<compilation debug="true"/>
</system.web>
<system.serviceModel>
<services>
<service name="WCFExampleService.ExampleService" behaviorConfiguration="MEXGET">
<endpoint
address=""
binding="wsHttpBinding"
contract="WCFExampleService.IExampleService" />
<endpoint
address=""
binding="wsHttpBinding"
contract="WCFExampleService.IExampleService2" />
<endpoint
address="net.tcp://localhost:3001/ExampleService"
binding="netTcpBinding"
contract="WCFExampleService.IExampleService2" />
<endpoint
address="net.tcp://localhost:3002/ExampleService"
binding="netTcpBinding"
bindingConfiguration="TransactionalTCP"
contract="WCFExampleService.IExampleService" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:3000/"/&gt;
</baseAddresses>
</host>
</service>
<service name="WCFExampleService.ExampleService2" behaviorConfiguration="MEX">
<endpoint
address="ExampleService"
binding="wsHttpBinding"
contract="WCFExampleService.IExampleService" />
<endpoint
address="ExampleService"
binding="netTcpBinding"
contract="WCFExampleService.IExampleService2" />
<endpoint
address="MEX"
binding="mexTcpBinding"
contract="IMetadataExchange" />
<endpoint
address="MEX"
binding="mexHttpBinding"
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:4000/"/&gt;
<add baseAddress="net.tcp://localhost:5000/"/>
</baseAddresses>
</host>
</service>

</services>
<bindings>
<netTcpBinding>
<binding name="TransactionalTCP" transactionFlow="true" />
</netTcpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="MEXGET">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
<behavior name="MEX">
<serviceMetadata />
</behavior>

</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>

As you can see the new service is pretty much like the other service, the only difference is that we have added two metadata exchange endpoints that you can use to get the metadata for both HTTP and TCP calls.

Since this is a new service name when we are hosting it, we have to change the code in the Program.cs file in the WcfHostMultiEndpoints project.

WcfHostMultiEndPoints Project

Program.cs

Alter the code as follows, see highlighted.

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
using WCFExampleService;

namespace WcfHostMultiEndpoints
{
class Program
{
static void Main(string[] args)
{
try
{
using (ServiceHost host = new ServiceHost(typeof(ExampleService2)))
{
host.Open();
Console.WriteLine(“Press to terminate the Host application.”);
Console.ReadLine();
}
}
catch (CommunicationException ce)
{
Console.WriteLine(“An exception occurred: {0}”, ce.Message);
}
}
}
}

Run the application.

Then open up the WcfTestClient and add the following services

http://localhost:4000
net.tcp://localhost:5000

When you add them, you will see the interfaces that the service implements, thus allowing you to call the service using Net TCP or Http.

Conclusion

This concludes the example of creating metadata endpoints using a configuration file, in the next example we will do the same thing, but this time use code.

Host a WCF service with multiple endpoints Part 4 of 7

In this 7 part example I will detail how to create, host and communicate with a WCF service that has multiple endpoints.

  • In this first example I will show how to create and host a WCF service with multiple endpoints
  • In the second example I will show how to create and host a WCF service with multiple endpoints using code rather than a config file
  • In the third example I will show how to enable the Metadata Exchange also called MEXGET
  • In the fourth example I will show how to enable the Metadata Exchange also called MEXGET using code rather than a config file
  • In the fifth example I will show how to enable metadata exchange using a dedicated endpoint also called MEX
  • In the sixth example I will show how to enable metadata exchange using a dedicated endpoint also called MEX using code rather than a config file
  • In the seventh example I will show how to create a client to connect to all these endpoints.

In part 4 of this series we will show how to enable metadata on a service pro-grammatically. You can look at Host a WCF service with multiple endpoints Part 3 of 7 for a discussion on how to do the same thing using the config file and a discussion on metadata.

So lets get to it.

MultipleEndPointsOnSameServiceSolution Solution

Open the solution and select the project WcfMultiEndpointsProgrammatically and change the code as follows

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.Text;
using System.Threading.Tasks;
using WCFExampleService;

namespace WcfMultiEndpointsProgrammatically
{
class Program
{
static Uri baseAddress = new Uri(“http://localhost:3000/&#8221;);

static void Main(string[] args)
{
try
{
using (ServiceHost host = new ServiceHost(typeof(ExampleService), baseAddress))
{
SetUpBindingsAndEndPoints(host);
SetupMetadata(host);

host.Open();
Console.WriteLine(“Press to terminate the Host application.”);
Console.ReadLine();
}
}
catch (CommunicationException ce)
{
Console.WriteLine(“An exception occurred: {0}”, ce.Message);
}
}

static void SetUpBindingsAndEndPoints(ServiceHost host)
{
Binding wsBinding = new WSHttpBinding();
Binding tcpBinding = new NetTcpBinding();
NetTcpBinding netTcpBinding = new NetTcpBinding();

//
host.AddServiceEndpoint(typeof(IExampleService), wsBinding, “ExampleService”);
//
host.AddServiceEndpoint(typeof(IExampleService2), wsBinding, “ExampleService”);
//
host.AddServiceEndpoint(typeof(IExampleService2), tcpBinding, “net.tcp://localhost:3001/ExampleService”);
//
netTcpBinding.TransactionFlow = true;
host.AddServiceEndpoint(typeof(IExampleService), netTcpBinding, “net.tcp://localhost:3002/ExampleService”);
}

static void SetupMetadata(ServiceHost host)
{
ServiceMetadataBehavior metadataBehavior;
metadataBehavior = host.Description.Behaviors.Find();
if (metadataBehavior == null)
{
metadataBehavior = new ServiceMetadataBehavior();
metadataBehavior.HttpGetEnabled = true;
host.Description.Behaviors.Add(metadataBehavior);
}
}

}
}

As you can see I added a new method to add the metadata, first I checked to make sure it did not already exist in the config file and then I created a new service metadata class and specified the HttpGetEnabled to true, which enables the metadata.

Now if you try and connect using the WcfTestClient and enter the address

http://localhost:3000

You will see that all the endpoints that were added show up.

Conclusion

This concludes this example of how to enable metadata pro-grammatically, in the next example I will show a way to do the same thing, but using a dedicated endpoint.

Host a WCF service with multiple endpoints Part 3 of 7

In this 7 part example I will detail how to create, host and communicate with a WCF service that has multiple endpoints.

  • In this first example I will show how to create and host a WCF service with multiple endpoints
  • In the second example I will show how to create and host a WCF service with multiple endpoints using code rather than a config file
  • In the third example I will show how to enable the Metadata Exchange also called MEXGET
  • In the fouth example I will show how to enable the Metadata Exchange also called MEXGET using code rather than a config file
  • In the fifth example I will show how to enable metadata exchange using a dedicated endpoint also called MEX
  • In the sixth example I will show how to enable metadata exchange using a dedicated endpoint also called MEX using code rather than a config file
  • In the seventh example I will show how to create a client to connect to all these endpoints.

This is part three of this series, we will enable metadata exchange on to the service that we created in the 1st and 2nd example.

Metadata Exchange

Before we dive into the code a quick discussion on the metadata exchange and what it means. Metadata as the name implies tells you what the service provides, i.e. its contract. Whether it be its class, methods and data that it needs to allow a client to communicate with it. In WCF there are two ways to do this one is provided free of charge by Microsoft. It uses a HTTP-GET mechanism and the only thing you need to do is enable it, yeh for Microsoft, they are so generous. The 2nd way to do this is to create your own endpoint to provide the metadata, this one we will look at in the fifth and sixth part of this series.

So without further ado lets gets coding.

MultipleEndPointsOnSameServiceSolution Solution

Open the same solution you have been working with and go to the WcfHostMultiEndpoints and open the app.config file.

Change the config file as follows.

app.config

<?xml version=”1.0″ encoding=”utf-8″ ?>
<configuration>
<startup>
<supportedRuntime version=”v4.0″ sku=”.NETFramework,Version=v4.5″ />
</startup>
<system.web>
<compilation debug=”true”/>
</system.web>
<system.serviceModel>
<services>
<service name=”WCFExampleService.ExampleService” behaviorConfiguration=”MEXGET”>
<endpoint
address=”ExampleService”
binding=”wsHttpBinding”
contract=”WCFExampleService.IExampleService” />
<endpoint
address=”ExampleService”
binding=”wsHttpBinding”
contract=”WCFExampleService.IExampleService2″ />
<endpoint
address=”net.tcp://localhost:3001/ExampleService”
binding=”netTcpBinding”
contract=”WCFExampleService.IExampleService2″ />
<endpoint
address=”net.tcp://localhost:3002/ExampleService”
binding=”netTcpBinding”
bindingConfiguration=”TransactionalTCP”
contract=”WCFExampleService.IExampleService” />
<host>
<baseAddresses>
<add baseAddress=”http://localhost:3000″/&gt;
</baseAddresses>
</host>
</service>
</services>
<bindings>
<netTcpBinding>
<binding name=”TransactionalTCP” transactionFlow=”true” />
</netTcpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name=”MEXGET”>
<serviceMetadata httpGetEnabled=”true”/>
</behavior>
</serviceBehaviors>
</behaviors>

</system.serviceModel>
</configuration>

The changes that have been made have been highlighted.

As you can see the first change is to add something called behaviorConfiguration=”MEXGET” what this means is that for this service we are going to provide a behavior configuration and not use the default one.

So then we look at the defined behaviorConfiguration. As you can see it matches the name you gave, which is MEXGET. Just as an aside you can call it anything you like. The important piece is the definition of the ServiceMetadata and the HttpGetEnabled being set to true. By doing this it enables the metadata for the service.

Just to prove this run the WcfTestClient.exe and select File Add Service and enter the following address

http://localhost:3000

After spinning its wheels for a few seconds you will see the following.

WcfTestClientMultiEndpoint
WCFTestClient showing multiple endpoints

As you can see in the picture it is showing all the endpoints that we have added including the ones for Net Tcp as well. You can try and execute some of the methods to see how they work.

Conclusion

This concludes this example on how to enable metadata in a WCF service using the configuration file and the built in feature provided by WCF. In the next example we will see the same thing, but this time using code rather than a config file.

Host a WCF service with multiple endpoints Part 2 of 7

In this 7 part example I will detail how to create, host and communicate with a WCF service that has multiple endpoints.

  • In this first example I will show how to create and host a WCF service with multiple endpoints
  • In the second example I will show how to create and host a WCF service with multiple endpoints using code rather than a config file
  • In the third example I will show how to enable the Metadata Exchange also called MEXGET
  • In the fouth example I will show how to enable the Metadata Exchange also called MEXGET using code rather than a config file
  • In the fifth example I will show how to enable metadata exchange using a dedicated endpoint also called MEX
  • In the sixth example I will show how to enable metadata exchange using a dedicated endpoint also called MEX using code rather than a config file
  • In the seventh example I will show how to create a client to connect to all these endpoints.

This is part 2 of this series and focuses on how to create and host a WCF service with multiple endpoints pro-grammatically rather than using a config file.

Endpoint Configuration using Code

In the previous example Host a WCF service with multiple endpoints Part 1 of 7 we created a WCF service and hosted it by specifying the endpoints, binding and address directly within a config file. The config file should be the primary way you manage a service since this is easiest way to set it up and also allows for modifications without having to change code.

However since there might be times when you would want to do the same thing in code, I thought I would show you how to do this.

MultipleEndPointsOnSameServiceSolution solution

So open the MultipleEndPointsOnSameServiceSolution solution that you created in the first part of this series and do the following.

Add a new Console Project and call it WcfMultiEndpointsProgrammatically

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Text;
using System.Threading.Tasks;
using WCFExampleService;

namespace WcfMultiEndpointsProgrammatically
{
class Program
{
static Uri baseAddress = new Uri(“http://localhost:3000/&#8221;);

static void Main(string[] args)
{
try
{
using (ServiceHost host = new ServiceHost(typeof(ExampleService), baseAddress))
{
SetUpBindingsAndEndPoints(host);

host.Open();
Console.WriteLine(“Press to terminate the Host application.”);
Console.ReadLine();
}
}
catch (CommunicationException ce)
{
Console.WriteLine(“An exception occurred: {0}”, ce.Message);
}
}

static void SetUpBindingsAndEndPoints(ServiceHost host)
{
Binding wsBinding = new WSHttpBinding();
Binding tcpBinding = new NetTcpBinding();
NetTcpBinding netTcpBinding = new NetTcpBinding();

//
host.AddServiceEndpoint(typeof(IExampleService), wsBinding, “ExampleService”);
//
host.AddServiceEndpoint(typeof(IExampleService2), wsBinding, “ExampleService”);
//
host.AddServiceEndpoint(typeof(IExampleService2), tcpBinding, “net.tcp://localhost:3001/ExampleService”);
//
netTcpBinding.TransactionFlow = true;
host.AddServiceEndpoint(typeof(IExampleService), netTcpBinding, “net.tcp://localhost:3002/ExampleService”);
}
}
}

Add the following references

  • System.ServiceModel
  • WCFExampleService

As an explanation the main method to be interested in is <strong>SetUpBindingsAndEndPoints</strong>. This is where the endpoints and the bindings are set up. These exactly match what is done with the configuration file to show how you can do both things.

Again if you try and add service reference or generate the proxy classes using SvcUtil then again it would fail as I have not specified any metadata yet.

Conclusion

So in this example you could see how it is very easy to do the same thing in either code or a config file. In the next example we will enable the metadata exchange allowing us to be able to generate the proxy classes for the connecting client.

Host a WCF service with multiple endpoints Part 1 of 7

In this 7 part example I will detail how to create, host and communicate with a WCF service that has multiple endpoints.

  • In this first example I will show how to create and host a WCF service with multiple endpoints
  • In the second example I will show how to create and host a WCF service with multiple endpoints using code rather than a config file
  • In the third example I will show how to enable the Metadata Exchange also called MEXGET
  • In the fouth example I will show how to enable the Metadata Exchange also called MEXGET using code rather than a config file
  • In the fifth example I will show how to enable metadata exchange using a dedicated endpoint also called MEX
  • In the sixth example I will show how to enable metadata exchange using a dedicated endpoint also called MEX using code rather than a config file
  • In the seventh example I will show how to create a client to connect to all these endpoints.

EndPoints

Before I start diving into the code, that is what you really want to see not be babbling on about what an Endpoint it, just have to provide some context to a Endpoint. An Endpoint is as its name sounds a location where a client can connect with a WCF service. Each Endpoint will have 3 parts to it

  • Address
  • Binding
  • Contract

Now I don’t know if Microsoft got lucky and that the 3 parts happened to be A, B, C, but if definitely makes it easier in a interview when the interviewer asks what an Endpoint is and what are its three parts.

In the previous example we have created, we have used all three parts of the endpoint, with Address being the URI where you can communicate with the service, Binding, the protocol used to communicate, i.e. Http, Tcp, Pipes, etc, and finally Contract, which is what the service has to offer a user.

Sounds simple enough right, well it is, it only gets difficult once you start digging into the thousands of settings in the app.config and the multitude of bindings and custom bindings, but we will get to that eventually.

I have bored you enough, lets get to writing some code.

Creating the Solution

As usual the first thing I always do is to create a blank solution.

Open Visual Studio and click File New and select Blank Solution and give it the name MultipleEndPointsOnSameServiceSolution

Next add a mew Class Library project and call it WCFExampleService
Finally add a new Console App project and call it WCFHostMultiEndpoints

WCFExampleService

Since you have create a WCF service in previous examples I will just go over the steps that you need to do.

  • Create a new interface and call it IExampleService.cs and add the following code

IExampleService.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;

namespace WCFExampleService
{
[ServiceContract]
public interface IExampleService
{
[OperationContract]
bool ExampleMethod();
}

[ServiceContract]
public interface IExampleService2
{
[OperationContract]
bool ExampleMethod2();
}
}

Note: One thing to notice here is that both interfaces are decorated with the [ServiceContract] attribute. You are probably wondering why we could not just inherit from the IExampleService and extend and then that interface would also be WCF service ready. Well it does not work like that, for each interface you have to decorate it with the attribute.

ExampleService.cs

Rename the created class1.cs file to ExampleService.cs and add the following code.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WCFExampleService
{
public class ExampleService : IExampleService, IExampleService2
{
public bool ExampleMethod()
{
return false;
}

public bool ExampleMethod2()
{
return true;
}
}
}

As you can see in this code the difference from the previous services you have created is the fact that the class is inheriting from two different interfaces, meaning the service is handling multiple implementations.

Now that the code is done, we just have to do the normal adding of the following reference.

  • System.ServiceModel

This completes the WCF service.

WcfHostMultiEndpoints

Since we have hosted a WCF before, using many different forms, I will not go into that much detail, except to say that I will be using a console application to host the service.

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
using WCFExampleService;

namespace WcfHostMultiEndpoints
{
class Program
{
static void Main(string[] args)
{
try
{
using (ServiceHost host = new ServiceHost(typeof(ExampleService)))
{
host.Open();
Console.WriteLine(“Press to terminate the Host application.”);
Console.ReadLine();
}
}
catch (CommunicationException ce)
{
Console.WriteLine(“An exception occurred: {0}”, ce.Message);
}
}
}
}

App.config

<?xml version=”1.0″ encoding=”utf-8″ ?>
<configuration>
<startup>
<supportedRuntime version=”v4.0″ sku=”.NETFramework,Version=v4.5″ />
</startup>
<system.web>
<compilation debug=”true”/>
</system.web>
<system.serviceModel>
<services>
<service name=”WCFExampleService.ExampleService”>
<endpoint
address=”ExampleService”
binding=”wsHttpBinding”
contract=”WCFExampleService.IExampleService” />
<endpoint
address=”ExampleService”
binding=”wsHttpBinding”
contract=”WCFExampleService.IExampleService2″ />
<endpoint
address=”net.tcp://localhost:3001/ExampleService”
binding=”netTcpBinding”
contract=”WCFExampleService.IExampleService2″ />
<endpoint
address=”net.tcp://localhost:3002/ExampleService”
binding=”netTcpBinding”
bindingConfiguration=”TransactionalTCP”
contract=”WCFExampleService.IExampleService” />
<host>
<baseAddresses>
<add baseAddress=”http://localhost:3000/”/&gt;
</baseAddresses>
</host>
</service>
</services>
<bindings>
<netTcpBinding>
<binding name=”TransactionalTCP” transactionFlow=”true” />
</netTcpBinding>
</bindings>
</system.serviceModel>
</configuration>

Then add the following references

  • System.ServiceModel
  • WCFExampleService

Now build the application.

Right now we have 4 endpoints defined, two of them supporting http binding and two supporting tcp.

However as they are currently written we cannot generate a proxy class or add a service reference, the reason is that we have not yet added any metadata support to them. This means if you try and do Add service reference or generate the proxy classes it will fail and complain that no metadata has been specified.

This does not mean that the WCF will not work, if you crafted the classes yourself you can still connect to the WCF service with no problem. You can think of this WCF service as a private service that is not visible to the user.

Once we get to step 3 of this series we will see how to enable the metadata and see that once we do the WCF page will be visible showing that are service is ready for use and that a WSDL dump is available.

Conclusion

This concludes the first part of the multi endpoint series, the next part we will use the same service, but instead of using a configuration file we will use code.