Exposing WCF REST Service over HTTPS

In this post, I will explain; how could we expose a WCF REST Service over secure HTPP (HTTPS)? Essentially there are three steps involved

1. Create a certificate or use a third party provided certificate

2. Configure HTTPS in IIS

3. Configure webHttpBinding to use transport level security

Create Certificate

To expose a service over HTTPS, we need to have a certificate in store. Either you can create your own X.509 certificate or use certificate provided by 3rd parties.

I am going to create my own certificate. To create X.509 certificate Open Inetmgr

clip_image001

In center you will get an option of Server Certificates. Double click on that.

clip_image003

At left pane you will get option to create a server certificate. Select Create Self-Signed Certificate

clip_image004

Just follow the wizard to create the self-signed certificate

clip_image006

Configure HTTPS in IIS

Next step we need to do is to configure SSL in IIS. Follow below steps for the same.

1. Open IIS

2. Select Default Web Site

clip_image007

3. Select SSL setting

clip_image009

4. Select Binding option of Edit Site tab from left panel

clip_image010

5. Add a Binding for HTTPS.

clip_image011

6. Select HTTPS from dropdown

clip_image012

7. Now we need to choose a certificate for secure communication over HTTP. We can choose a certificate provided by third party or self-created certificate from personal store. In beginning of this post we created a certificate called DEBUGMODE. CER. I am going to use that certificate.

clip_image013

8. HTTPS is being configured at port 443.

clip_image014

Create WCF REST Service

Since purpose of this post is to demonstrate REST over HTTPS so basic assumption I do have is you know how to create REST service and hosting.

I am creating a simple resource like below,

clip_image015

Implement service as below,

clip_image016

HOST WCF REST Service

I am going to host service in a console application. Right click on WCF Service Application project and a console application project. Change the target framework from to .Net framework 4.0. Add required references.

Add reference of,

a. System.ServiceModel

b. System.ServiceModel.Web

c. Add project reference of WCF Service project

1. We are going to use WebServiceHost to host REST service in managed [Console] application.

clip_image018

2. We need to construct URI for base address of service

clip_image020

In base address URI construction, you need to make sure below points

a. Address scheme is HTTPS not HTTP.

b. Since HTTPS is configured on port 443 so base address is constructed with port 443.

3. Obviously we need to choose binding as WebHttpBinding.

clip_image022

Point to take care is that we are setting security mode for WebHttpBinding as Transport.

4. Adding EndPoint to the instance of WebServiceHost

clip_image024

Iservice1 is the service contract and Service1 is the service implementation file.

Host program will be as below,

Program.cs


using System;
using System.ServiceModel;
using System.ServiceModel.Web;
using WcfService13;
using System.Diagnostics;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
WebServiceHost host = new WebServiceHost(typeof(Service1));
string uri = "<a href="https://localhost:443/Service1.svc/">https://localhost:443/Service1.svc/</a>";
WebHttpBinding binding = new WebHttpBinding();
binding.Security.Mode = WebHttpSecurityMode.Transport;
host.AddServiceEndpoint(typeof(IService1), binding, uri);
host.Open();
Console.WriteLine("REST Service with HTTPS is running ");
Process.Start(uri);
Console.ReadKey(true);

}
}
}

Running Service

Now when we run console application browser will automatically get started

clip_image026

If you notice URL, you can see that service is running on SSL over HTTP. URL is starting with HTTPS.

In next post, I will show you calling WCF REST Service over HTTPS from a client. Thanks for reading.

Getting current Authentication information on WCF REST Service

Sometime you may have a requirement to tell your client what type of authentication scheme you are applying on your WCF REST service. In this post I will show you, “How could you expose authentication scheme information as part of your service? “

To start with let us create Self Hosted WCF REST Service. Besides other resources [OperationContracts] of your REST Service add a function to return Authentication type as string in Service Contract.

clip_image001

We are returning authentication scheme as string.

If you don’t have any other functions than GetAuthenticationType() then your service contract would look like below,

IService1.cs


using System.ServiceModel;
using System.ServiceModel.Web;
namespace WcfService13
{
    
    [ServiceContract]
    public interface IService1
    {             

        [OperationContract]
        [WebGet(UriTemplate = "/GetAuthenticationType")]
        string GetAuthenticationType();       
       
       
    }

   
}


Now we need to implement the service to return the authentication scheme.

clip_image003

In implementation

1. We are creating instance of current operation context.

2. If context is null means there is no authentication.

3. If it is not null then we are checking whether is anonymous.

4. If it is not anonymous then simply we are assigning Primary identity name.

For your reference your service would like below,

Service1.svc.cs


using System.ServiceModel;

namespace WcfService13
{
    public class Service1 : IService1
    {      
       public string GetAuthenticationType()
        {
            ServiceSecurityContext context = OperationContext.Current.ServiceSecurityContext;
            string authenticationType = "Oh!There is no Authentication on my REST Service";
            if (context != null)
            {
                if (context.IsAnonymous)
                {
                    authenticationType = "Anonymous Authentication";
                }
                else
                {
                    authenticationType = context.PrimaryIdentity.Name;
                }
            }

            return authenticationType;

        }   
       
    }
}


Since we have created a self-hosted WCF REST Service, press F5 to call the webGet method from browser.

clip_image005

Uploading File to server from ASP.Net client using WCF REST Service

Very often I see one question flooding in all forums, “How to upload a File using WCF REST Service? “, so I thought let me write a post on the same.

Essentially, there is nothing specific to do to upload file, but the below steps

1. Create a service with Post operation

2. Pass file data as Input Stream

3. Pass name of the File

4. Host the service in console application [Note : You can host wherever you want though]

Let us first create Service Contract.

clip_image002

If you notice above Service contract is creating a REST resource with POST method. One of the input parameter is Stream.

For your reference, contract interface would look like as below, [You can copyJ]

IService1.cs


using System.ServiceModel;
using System.ServiceModel.Web;
using System.IO;
namespace RESTImageUpload
{
[ServiceContract]
public interface IImageUpload
{
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "FileUpload/{fileName}")]
void FileUpload(string fileName, Stream fileStream);

}
}

Once Contract is defined we need to implement service to save a file on sever location.

clip_image004

You need to make sure you have a folder FileUpload created on D drive of your server else you would get “Device not ready “exception.

Since Write () method takes byte array as input to write data in a file and input parameter of our service is Stream , so we need to do a conversion between Stream to Bye Array

clip_image006

Final Service implementation would look like below [You can CopyJ]

Service1.svc.cs


using System.IO;
namespace RESTImageUpload
{

public class ImageUploadService : IImageUpload
{

public void FileUpload(string fileName, Stream fileStream)
{

FileStream fileToupload = new FileStream("D:\\FileUpload\\" + fileName, FileMode.Create);

byte[] bytearray = new byte[10000];
int bytesRead, totalBytesRead = 0;
do
{
bytesRead = fileStream.Read(bytearray, 0, bytearray.Length);
totalBytesRead += bytesRead;
} while (bytesRead > 0);

fileToupload.Write(bytearray, 0, bytearray.Length);
fileToupload.Close();
fileToupload.Dispose();

}

}
}

So far we are done with Service definition and implementation and now we need to host the service. I am going to host service in a console application. Host program would have reference of System.ServiceModel and System.ServiceModel.Web. If you are not able to find System.ServiceModel.Web reference to add in your console application then change the target framework to .Net Framework 4.0 from .Net Framework 4.0 client profile.

Program.cs


using System;
using System.ServiceModel;
using RESTImageUpload;
using System.ServiceModel.Description;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
ServiceHost host = new ServiceHost(typeof(ImageUploadService), new Uri(baseAddress));
host.AddServiceEndpoint(typeof(IImageUpload), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior());
host.Open();
Console.WriteLine("Host opened");
Console.ReadKey(true);
}
}
}

Press F5 to run the service hosted in console application.

clip_image008

Service is up and running so let us call this service to upload the file.

I am creating a simple ASP.Net Web Application with File Upload control and a button. ASPX page looks like below

Default.aspx


u<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %>

<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
</asp:Content>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<h2>
Welcome to ASP.NET!
</h2>
<p>
To learn more about ASP.NET visit <a href="<a href="http://www.asp.net">http://www.asp.net</a>" title="ASP.NET Website">www.asp.net</a>.
</p>
<p>
You can also find <a href="<a href="http://go.microsoft.com/fwlink/?LinkID=152368&amp;clcid=0x409">http://go.microsoft.com/fwlink/?LinkID=152368&amp;clcid=0x409</a>"
title="MSDN ASP.NET Docs">documentation on ASP.NET at MSDN</a>.
</p>
<asp:FileUpload ID="FileUpload1" runat="server" />
<asp:Button ID="Button1" runat="server"
Text="Upload File" />
</asp:Content>

On click event of button we need to make a call to the service to upload the file.

clip_image010

In above code, I am making a HTTP Web Request and explicitly specifying method is POST and content type is text/plain. We need to get the Request Stream and write the byte array in that. As HTTP response you can get the status code.

For your reference client code would look like as below,

Default.aspx.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.IO;
using System.Web.UI.WebControls;
using System.Net;

namespace WebApplication1
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Button1.Click += new EventHandler(Button1_Click);
}

void Button1_Click(object sender, EventArgs e)
{
byte[] bytearray=null ;
string name = "";
//throw new NotImplementedException();
if (FileUpload1.HasFile)
{
name = FileUpload1.FileName;
Stream stream = FileUpload1.FileContent;
stream.Seek(0, SeekOrigin.Begin);
bytearray = new byte[stream.Length];
int count = 0;
while (count < stream.Length)
{
bytearray[count++] = Convert.ToByte(stream.ReadByte());
}

}

string baseAddress = "http://" + Environment.MachineName + ":8000/Service/FileUpload/";
HttpWebRequest request = (HttpWebRequest) HttpWebRequest.Create(baseAddress+name);
request.Method = "POST";
request.ContentType = "text/plain";
Stream serverStream  = request.GetRequestStream();
serverStream.Write(bytearray, 0, bytearray.Length);
serverStream.Close();
using ( HttpWebResponse response = request.GetResponse() as HttpWebResponse )
{
int statusCode =(int) response.StatusCode;
StreamReader reader = new StreamReader( response.GetResponseStream() );

}

}
}
}

I hope this post was useful and saved your time to upload a file. In next post I will show you how to upload an image from Silverlight client.

WCF 4.0 Features: Part #1

WCF 4 comes with many of new features for better developer experience. There is high integration with workflow service. Making WCF REST service more developer friendly and Configuration less WCF service. In short WCF 4 tries to address common scenario easily and at the same time gives us more options to communicate in between service and client.

Below are the few of new features of WCF 4.0

1. Dynamic Service and End Point discovery

2. Intermediate Routing Pattern ( Generic Routing Services)

3. Discovery announcement

4. Simplified Configuration

5. Protocol bridging and Fault tolerance

6. Default End Points.

7. .svc-less activation of REST services or making REST URI nice.

8. Default Protocol Mapping

9. Help page enabled for WCF Rest service and many more.

In this article we will see in detail three exciting features of WCF 4.0. and in further articles we will see the other features

In this article we are going to see

1. EndPoint Discovery

2. Default EndPoints

3. Help page enabled for WCF REST Service

Problem

People say; you need to know only ABC of a service to expose End Point of that service. And client or service consumer needs to know only End Point to consume the service. But wait for a while here, and think; what if? Binding need to change at the service side from basic to WS over HTTP, This is very basic change but to accommodate this client has to update the service again. And this is very much error prone. It is very tedious task to update client about all the basic frequent change at the service side. To solve this issue, there should be some mechanism and that is called End Point Discovery or Dynamic Service.

In absolute technical words

WCF 4.0 supports WS –Discovery standard or protocol.

WS-Discovery Standard

1. This is a multicast protocol that issues SOAP message over UDP,

2. WS-Discovery is a Standard that defines a lightweight discovery mechanism for discovering services based on multicast messages. It enables a service to send a Hello announcement message when it is initialized and a Bye message when is removed from the network.

3. Client or consumer can discover services by multicasting a Probe message to which a service can reply with a ProbeMatch message containing the information necessary to contact the service.

4. Client or consumer can find services that have changed endpoint by issuing a Resolve message to which respond with a ResolveMatchmessage.

So, we can say WS –Discovery is a UDP based multicast message exchange. This message receives End Point information from Service and uses this as discovery information. Client uses discovery information to discover the available service on the network.

WCF Service Discovery API

WCF provides, WCF Discovery API for dynamic publish and discovery of web service using WS –Discovery protocol. This API helps service to publish them and helps client to find service on the network.

Modes

clip_image002

Managed Mode

1. In managed mode there is a centralized server called a discovery proxy that services use to publish themselves and clients use to retrieve information about available services.

2. When a new service starts up it sends an announcement message to the discovery proxy.

3. The discovery proxy saves information about each available service to storage.

4. When a client must search for a service it sends a Probe request to the discovery proxy and it determines whether any of the services that have been published match the request.

5. If there are matches the discovery proxy sends a ProbeMatch response back to the client.

6. The client can then contact the service directly using the service information returned from the proxy.

Ad-Hoc Mode

1. There is no centralized server.

2. Service announcements and client requests are sent in a multicast fashion.

3. If a service is configured to send out a Hello announcement on start up, it sends it out over a well-known, multicast address using the UDP protocol.

4. Therefore, clients have to actively listen for these announcements and process them accordingly.

5. When a client issues a Probe request for a service it is also sent over the network using a multicast protocol.

6. Each service that receives the request determines whether it matches the criteria in the Probe request and responds directly to the client with a ProbeMatch message if the service matches the criteria specified in the Probe request.

Sample

In this sample, we will create a very basic service and at the client side, first client will discover the service in Ad-Hoc mode and then consume that.

To run and go through this sample, you need Visual Studio 2010 Beta.

To make a service discoverable, a ServiceDiscoveryBehavior must be added to the service host and a discovery endpoint must be added to specify where to listen for and send discovery message

Step1

Open VS2010. Create a new project by choosing WCF Service Application Project template.

Step 2

Delete all the code which is generated by Visual studio. After deleting Contract and Service Implantation is as follows.

IService1.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace WcfService1
{
[ServiceContract]
public interface IService1
{
[OperationContract]
string GetMessage(string  msg);
}
}

Service1.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace WcfService1
{
public class Service1 : IService1
{
public string GetMessage(string msg)
{
return msg;
}

}
}

The above is simple Service Contract and implantation of that.

Step3

Open Web.Config file. And modify the System.ServiceModel. Add the code which in red rectangle below.

Web.Config


<system.serviceModel>
<services>
<service name="WcfService1.Service1" behaviorConfiguration="WcfService1.Service1Behavior">
<endpoint address="" binding="wsHttpBinding" contract="WcfService1.IService1">

<identity>
<dns value="localhost"/>
</identity>
</endpoint>

<endpoint name ="udpDiscovery" kind ="udpDiscoveryEndpoint" />

<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WcfService1.Service1Behavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>

<serviceDiscovery />

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

Explanation of Config file

1. One new End Point is being added.

2. Kind of newly added End Point is udpDiscoveryEndpoint.

3. This End Point will be used to discover the service.

4. ServiceDiscovery behavior is also get added.

Step 4

Press F5 to run the service. Service will get hosted in ASP.Net web server.

clip_image006

Step 5

Add a new console project in solution.

Step 6

Add Reference of System.ServiceModel.Discovery.dll in console project.

clip_image007

Step 7

Add namespace using System.ServiceModel.Discovery;

Program.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ConsoleApplication1.ServiceReference1;
using System.ServiceModel;
using System.ServiceModel.Discovery;

namespace ConsoleApplication1

{
class Program

{

static void Main(string[] args)

{

DiscoveryClient discoverclient = new DiscoveryClient(new UdpDiscoveryEndpoint());

FindResponse response = discoverclient.Find(new FindCriteria(typeof(IService1)));

EndpointAddress address = response.Endpoints[0].Address;

Service1Client client = new Service1Client(new  WSHttpBinding(), address);

string str= client.GetMessage("Hello WCF 4 ");

Console.WriteLine(str);

Console.ReadKey(true);

}

}
}

Explanation of the code

1. We are making object of DiscoveryClient class. This class is user to discover available service.

2. In constructor of this class, we are passing UdpDiscoveryEndPoint of the service.

3. Then we are calling Find method with contract name as argument to get FindResponse.

4. Now FindResponse variable having all the available address for contract passed in Find method.

5. We are creating the client proxy and passing discovered address as argument.

6. Calling the service operation on the client proxy.

Output

clip_image009

Default End Points and Protocol mapping

For a normal developer like me, had a great challenge working with WCF 3.x was configuration of End Points in config file. Developer had to add endpoints to setup a WCF service. In WCF 4, Defualt End Point is associated with the service, if we don’t configure any WCF endpoint.

Walkthrough

To see how Default EndPoint works follow the steps below,

Step1

Create a WCF service application.

Let us create two service contracts

IService1.cs


[ServiceContract]
public interface IService1
{

[OperationContract]
string GetData();
}

IService2.cs


[ServiceContract]
public interface IService2
{
[OperationContract]
string GetMessage();
}

Now let us implement the service as below,


public class Service1 : IService1, IService2
{
public string GetData()
{
return "Hello From Iservice1 ";

}

public string GetMessage()
{
return " Hello From Iservice2";
}

Step 2

Now we will host this service in a console application, Create a new console application project.

Add reference of WCF service application project and also add reference of System.serviceModel in the console application project.

Note: There is no App.Config associated with console application.

clip_image011

Here, we are registering two base addresses with the servicehost. One for http binding and other for nettcp binding.

Now we don’t have any configuration for the service EndPoint . ServiceHost will create default EndPoints .

Now ServiceHost will configure EndPoints for two base addresses


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;
using WcfService1;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{

ServiceHost host = new ServiceHost(typeof(WcfService1.Service1),
new Uri("<a href="http://localhost:8080/service">http://localhost:8080/service</a>"),
new Uri("net.tcp://localhost:8081/service"));

host.Open();
foreach (ServiceEndpoint se in host.Description.Endpoints)
{
Console.WriteLine("Address: " +  se.Address.ToString() +
"  Binding: " + se.Binding.Name +
" Contract :"+ se.Contract.Name);
}

Console.ReadKey(true);

}
}
}

Output would be

clip_image013

The default protocol mapping for default EndPoints are mapped as below,

clip_image015

Since HTTP is mapped with basicHttpBinding , so we got the default EndPoint with basicHttpBinding.

Default EndPoint will only get created if there is not a single Endpoint configured. If we add any single EndPoint then all then there won’t be any default EndPoint get configured.

If we add one EndPoint as below,

clip_image017

We added one service EndPoint and now the output we would get for below code ad below,


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;
using WcfService1;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{

ServiceHost host = new ServiceHost(typeof(WcfService1.Service1),
new Uri("<a href="http://localhost:8080/service">http://localhost:8080/service</a>"),
new Uri("net.tcp://localhost:8081/service"));

host.AddServiceEndpoint(typeof(IService1),
new WSHttpBinding(),
"myBinding");

host.Open();
foreach (ServiceEndpoint se in host.Description.Endpoints)
{
Console.WriteLine("Address: " +  se.Address.ToString() +
"  Binding: " + se.Binding.Name +
" Contract :"+ se.Contract.Name);
}

Console.ReadKey(true);

}
}
}

Output

clip_image019

Now we see that if we configure EndPoint then WCF does not support default Endpoints.

If we closely look at the output that by default WCF maps protocol to binding as below.

clip_image020

So if we are not configuring any EndPoint , then for http type base address in default EndPoint created by WCF will have basicHttpBinding.

If we see the above mapping , by default http type is mapped to basicHttpBinding , net.tcp type is mapped to netTcpBinding and so on.

If we want to change this, we can change this default mapping

clip_image022

Now when we do the above change in the Web.Config file then when we do not define any EndPoint then for HTTP type base address, WCF will create the EndPoint with wsHttpBinding.

So to understand more, what I am talking about

1. Create a WCF Service application

2. Create a Service contract as below


[ServiceContract]
public interface IService1
{

[OperationContract]
string GetData();
}

3. Implement the Service as below


using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace WcfService1
{

public class Service1 : IService1
{
public string GetData()
{
return "Hello From Iservice1 ";

}

}
}

4. Now we will host this service in a console application, Create a new console application project. Add reference of WCF service application project and also add reference of System.serviceModel in the console application project.

5. Right click on the console project and add app.config file to console project. Right the below configuration in App.Config


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<protocolMapping >
<add  scheme ="http" binding ="wsHttpBinding" bindingConfiguration ="" />
</protocolMapping>
</system.serviceModel>
</configuration>

6. Now write the below code to fetch the default Endpoint created by WCF


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;
using WcfService1;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{

ServiceHost host = new ServiceHost(typeof(WcfService1.Service1),
new Uri("<a href="http://localhost:8080/service">http://localhost:8080/service</a>"));

host.Open();
foreach (ServiceEndpoint se in host.Description.Endpoints)
{
Console.WriteLine("Address: " +  se.Address.ToString() +
"  Binding: " + se.Binding.Name +
" Contract :"+ se.Contract.Name);
}

Console.ReadKey(true);

}
}
}

And output we would get is

clip_image024

So we can see that how we modified the default mapping using Protocol mapping in System.ServiceModel

Enabling Help page for REST Service in WCF 4.0

WCF 4.0 provides us feature to eanable Help page on WCF REST Service.

Walkthrough

In this walkthrough we will see,

1. How to create a REST based service?

2. How to host a REST based service in Console application?

3. How to enable Help page for REST Service?

Follow the steps as below,

Step1

Create a New project. Select Console application as project type.

clip_image026

Step 2

Add a new project to same solution. Choose the project type as class library.

clip_image028

Step 3

Add below references in both projects console and service library

System.ServiceModel;

System.ServiceModel.Description;

System.ServiceModel.Web;

clip_image029

If you are not able to get System.ServiceModel.Web dll by default , when you are adding as Add Reference in your console application project and class library project , then follow the below steps

1. Right click on your console application project or class library project

2. Select properties from context menu

3. From Application tab, if you see by default .NET Framework 4 Client profile is selected. Change that to .NET Framework 4.0. So your target framework should be .NET Framework 4.0.

clip_image030

Now you should able to see all the dll when you add service reference in project.

Step 4

In this step, I will create contract of service

1. Open the Contract (Class Library project).

2. Delete Class1.

3. Right click and add a new item then select Interface from Code tab.

clip_image032

4. Make Interface as public and put ServiceContract attribute.

5. Declare two operation contracts. Make one attributed with WebGet and another attributed with Web Invoke.

IService.cs


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

namespace Contracts
{
[ServiceContract]
public  interface IService
{
[OperationContract]
[WebGet]
string GetMessage(string inputMessage);

[OperationContract]
[WebInvoke]
string PostMessage(string inputMessage);
}
}

Step 5

In this step, I will implement the contract in Service file. To do so,

1. Right click and add a class in Console application.

clip_image034

2. Give any name; I am giving name here Service of the class.

3. Implement the interface (Contract IService) in this class.

Service.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Contracts;

namespace SelfHostedRESTService
{
public  class Service :IService
{
public string GetMessage(string inputMessage)
{
return "Calling Get for you " + inputMessage;
}

public string PostMessage(string inputMessage)
{
return "Calling Post for you " + inputMessage;
}
}
}

Step 6

In this step, I will host the service in a console application. So to do so

1. Open Program.cs

2. Create instanced of WebServieceHostFactory

clip_image036

3. Add a service end point

clip_image038

4. Add service host behavior with help page enabled

clip_image040

As we know, REST service used webHttpBindding. And we are enabling Help page here.

Program.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Web;
using Contracts;

namespace SelfHostedRESTService
{
class Program
{
static void Main(string[] args)
{

WebServiceHost host = new WebServiceHost(typeof(Service), new Uri("<a href="http://localhost:8000">http://localhost:8000</a>"));
ServiceEndpoint ep = host.AddServiceEndpoint(typeof(IService), new WebHttpBinding(), "");

host.Description.Endpoints[0].Behaviors.Add(new WebHttpBehavior { HelpEnabled = true });
host.Open();
Console.WriteLine("Service is up and running");
Console.WriteLine("Press enter to quit ");
Console.ReadLine();
host.Close();
}
}
}

Step 7

Just press F5 to run the service.

clip_image042

Now once service is up and running, I can test,

To test the Help page, just type

http://localhost:8000/help

clip_image044

When you click on Get or Post link you will get below detail help.

clip_image046

In next article we will see some other features of WCF 4.0

Walkthrough creating REST Service in WCF 4.0

Objective

This article will explain step to step explanation of, how to create a REST based service and how to consume that in a managed client.

Step 1`

Create a new project as WCF Service application type.

clip_image002

Step 2

Delete all the default code from IService.cs and Service.svc.cs

Now open Web.Config file and delete <system.serviceModel>

If you are using VS2010 then delete below code from Web.Config

clip_image004

Step 3

Right click on Service.svc and open View markup.

clip_image005

In Markup of RestService.cs , add below code there

Factory=”System.ServiceModel.Activation.WebServiceHostFactory”

So after adding code the markup would look like

Markup of RestService.cs

clip_image007

Step 4

Add following references to the WCF Service Application project, if you are using VS2010

Microsoft.Http.dll

Microsoft.Http.Extension.dll

System.ServiceModel.Web.dll

Step 5

Add a new project as of type class library and give it name UtilityClasses.

clip_image009

Add a class Number to this class library.

Number.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UtilityClasses
{
 [Serializable]
 public class NumberService
 {
 public int Number1 { get; set; }
 public int Number2 { get; set; }
 }
}

 

Step 6

Define the Service Contract as below,

IService1.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Web;
using UtilityClasses;

namespace WcfService3
{

 [ServiceContract]
 public interface IService1
 {
 [OperationContract(Name="AddParameter")]
 [WebInvoke(UriTemplate = "/Add/MyAdd",Method="POST")]
 int  Add(NumberService n1);
 [OperationContract(Name = "Add")]
 [WebGet(UriTemplate = "/")]
 int Add();

}

}

 

This code is used to construct URI for REST service.

clip_image010

Method parameter says what type of HTTP request; this URI is going to entertain. In this case it is Http POST.

UriTemplate parameter says, what would be URI for this particular method. In this case it is one back slash means; it is root URI of this service.

So, to invoke this method add (), the URI address would be

http://localhost:3602/RestService.svc/

Where 3602 is port number of web server, where this service is running.

Let, if the above code is modified as

clip_image012

Then it would be invoked as

http://localhost:3602/RestService.svc/ADD/MyAdd

Step 7

Now we need to implement the service

Service1.svc.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using UtilityClasses;

namespace WcfService3
{

 public class Service1 : IService1
 {
 public int res = 100;

public int Add(NumberService n1)
 {

res = Convert.ToInt32(n1.Number1) + Convert.ToInt32(n1.Number2);
 return res;
 }
 public int Add()
 {
 return res;
 }
 }
}

&nbsp;

 

Step 8

Test the Service in Browser

1. Build the Service

2. Right click on Service1.svc and select view in browser.

clip_image014

Output 100 is returned in the browser by the service. It is because, below service method. URI of below GET method is mapped to root of the URI. And this method is returning 100.

clip_image015

Step 9

Consume the service

Add new console project in solution and give it name as ConsoleTestProject.

clip_image017

Add reference of project UtilityClasses Add following references to the console project.

Microsoft.Http.dll

Microsoft.Http.Extension.dll

System.ServiceModel.Web.dll

Step 10

Program.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using Microsoft.Http;
using Microsoft.ServiceModel.Web;
using Microsoft.ServiceModel.Web.SpecializedServices;
using System.Runtime.Serialization;
using UtilityClasses;

namespace ConsoleTestProject
{
 class Program
 {
 static void Main(string[] args)
 {

uri = "<a href="http://localhost:3602/RestService.svc/">http://localhost:3602/RestService.svc/</a>";
 // Calling without parameter
 Console.WriteLine(AddWithoutParameter());
 Console.Read();
 //Calling with parameter
 NumberService obj = new NumberService() { Number1 = 7, Number2 = 2 };
 Console.WriteLine(AddWithParameter(obj));
 Console.Read();

}
 public static string  AddWithoutParameter()
 {
 using (HttpResponseMessage response = new HttpClient().Get(uri))
 {

 int res = response.Content.ReadAsDataContract<int>();
 return res.ToString();
 }
 }
 public static string  AddWithParameter(NumberService obj)
 {
 using (HttpResponseMessage  response = new HttpClient().Post(uri,HttpContentExtensions.CreateDataContract(obj)))
 {

 int res = response.Content.ReadAsDataContract<int>();
 return res.ToString();

}

}

}
 }
}

&nbsp;

 

There are two static methods

AddWithoutParameter() -> To Invoke HTTP Get on Service URI. {In Green}

AddWithParameter() -> To Invoke HTTP POST on Service URI. {In Yellow}

Output

clip_image019

Removing .SVC from WCF REST Service

I got a mail asking question, “How could we remove .SVC from a WCF REST Service?

For example, instead of

clip_image001

We need to remove, .svc extension from address of the WCF service.

Let us say, you have a WCF REST Service up and running

http://localhost:58230/Service1.svc/GetMessage

With output

clip_image003

Read here: How to create a WCF REST Service

To remove service extension, we will write a HTTP Module and remove the extension and rewrite the path.

Now to remove .svc follows below steps

1. Add a class in WCF Application project.

2. Add the namespace System.Web

3. Implement the class from IHttpModule

clip_image004

4. Before starting of current context take the context path and rewrite the URL.

clip_image006

Full source code for

RemoveSvc.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace WcfService7
{
    public class Removesvc : IHttpModule
    {
        public void Dispose()
        {
        }
        public void Init(HttpApplication context)
        {
            context.BeginRequest += delegate
            {
                HttpContext cxt = HttpContext.Current;
                string path = cxt.Request.AppRelativeCurrentExecutionFilePath;
                int i = path.IndexOf('/', 2);
                if (i > 0)
                {
                    string a = path.Substring(0, i) + ".svc";
                    string b = path.Substring(i, path.Length - i);
                    string c = cxt.Request.QueryString.ToString();
                    cxt.RewritePath(a, b, c, false);
                }
            };
        }
    }
}

5. Now we need to add the HTTP Module in configuration file of WCF Service.

clip_image008

Where, RemoveSvc is name of the class implementing IHttpModule and WcfService7 is the project name (namespace)

Web.Config


<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="true"/>
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
 <system.webServer>
    <modules>
      <add name ="removesvc" type ="WcfService7.Removesvc,WcfService7"/>
   </modules>      
  </system.webServer
</configuration>


6. Now host the service in IIS. [Read here : Hosting WCF Service in IIS ]

Now when you open WCF REST Service in browser, you can see you are able to call the service without extension ,

http://localhost:4567/Service1/GetMessage

clip_image010

Consuming WCF REST Service in ASP.Net Web Site

Objective

This article will give a quick walkthrough on how to consume a WCF REST Service in ASP.Net Web site.

1. Create a WCF REST Service.

2. Consume the Service in ASP.Net Web Site

Create a WCF REST Service

Step 1

Create a WCF application. To create a new application File -> New -> Web-> WCF Service Application.

clip_image002

Step 2

Remove all the default code created by WCF. Remove code from IService 1 interface and Service1 class. Remove the code from Web.Config also. Open Web.Config and remove System.Servicemodel codes.

Step 3

Right click on Service1.svc select View markup and add below code

clip_image003

<%@ ServiceHost Language=”C#” Debug=”true” Service=”FetchingImageinBrowser.Service1″ CodeBehind=”Service1.svc.cs” Factory=”System.ServiceModel.Activation.WebServiceHostFactory” %>

Step 4

Create contract. Operation contract will return Stream. Stream is in the namespace System.IO. By putting WebGet attribute make operation contract

IService1.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.ServiceModel.Web;
namespace WcfService6
{
    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        [WebGet(UriTemplate="/GetData")]
        string GetData();
    }
}

Step 5

Implement the service

Service1.svc.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace WcfService6
{
    public class Service1 : IService1
    {
        public string GetData()
        {
            return "hello From REST ";
        }
    }
}

Press F5 to run the service

Consume the Service in ASP.Net Web Site

Step 1

Create an ASP.Net Web Site. Navigate to File -> New -> Web Site

clip_image005

Step 2

Drag and drop one button and text box on the page.

Step 3

Add the namespace of

System.RunTIme.Serilization

System.Net

System.IO

Step 4

On the click event of the button,

clip_image007

In above code,

1. Create instance of WebClient class.

2. Down load the data in byte array form.

3. Create the stream from byte array

4. Using Data Contract Serializer deserialize the stream.

5. Get the result in string

Default.aspx.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Runtime.Serialization;
using System.Net;
using System.IO;
public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
    }
    protected void Button1_Click(object sender, EventArgs e)
    {
        WebClient proxy = new WebClient();
        byte[] abc = proxy.DownloadData((new Uri("http://localhost:4567/Service1.svc/GetData")));
        Stream strm = new MemoryStream(abc);
        DataContractSerializer obj = new DataContractSerializer(typeof(string));
        string result = obj.ReadObject(strm).ToString();
        TextBox1.Text = result;
    }
}

Run to get the output.

WebServiceHost : Hosting a WCF REST Service

Objective

In this article, I will explain

1. What is WebServiceHost Factory class?

2. What is its function?

3. Where to use it?

4. One sample on hosting WCF REST Service using WebServiceHost.

What is WebServiceHost factory?

1. This is useful to host WCF REST End points.

2. This is derived from ServiceHost.

3. WebServiceHost has some extra functionality.

4. WebServiceHost works exactly the same way ServiceHost works.

WebServiceHost factory perform following special task

image

Where to use it?

image

How to choose between ServiceHost and WebServiceHost?

image

Example

In this example, I will show you step by step, how we can create a REST Service and host it in a console application using WebServiceHost factory.

To see the complete step by step walkthrough , follow my below article.

Hosting WCF REST Service in Console Application.

I hope this post was useful. Thanks for reading. Happy coding.