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

AutoCompleteBox in Silverlight 4.0 with DataSource from SQL Server

In my last article AutoCompleteBox in Silverlight 4.0 , Data Source for Autocomplete Box was an IEnumerable list. In this post we will work with a column value of table from SQL Server as Data Source for Autocomplete Box.

Our approach would be

1. Create WCF Service

2. Exposed data

3. Consume in Silverlight

4. Put data exposed by service as data source of Autocomplete Box.

I have a table called Course in School database. I am going to bind value of the Title column of Course table as source for AutoCompletebox.

Create WCF Service

Right click on web project hosting Silverlight application and add a new item by selecting WCF Service application from Web tab.

1. Very first let us create a Service Contract returning titles as list of string.

clip_image001

Create Data Access layer

Now let us create a Data Access layer using LINQ to SQL class.

a. Right click on web application project and add a new item. Select LINQ to SQL class from Data tab.

clip_image003

Note: I have written many posts on LINQ. You can refer them for better and detail understanding of LINQ. In this post I am going bit faster J

b. Select server explorer option.

c. Either create a new data connection or choose [if listed for your Database server] from server explorer.

clip_image004

d. Drag and drop Course table on dbml file.

Now our Data access layer is in place.

Implement Service

Service contract and Data access layer is in place. Now let us implement the service.

clip_image006

I have done a very simple stuff in above code. I created instance of Data class context and fetching all the titles from courses table.

Test WCF Service

Right click on .SVC class and select show in browser.

Consume WCF Service in Silverlight

Right click on Silverlight application and add service reference. Since WCF Service is in same solution with Silverlight click on Discover to select service.

clip_image007

Now Service is added. We need to make a client side class to bind as data source of Autocomplete box. Add below class in Silverlight project.

clip_image009

Call WCF Service

We know we need to make asynchronous call to WCF from Silverlight. In completed event we can bind Autocompletebox as below.

clip_image011

In above snippet atcTextBox is name of the Autocompletebox.

Drag and Drop AutoCompleteBox on XAML

1. From the tool box select AutoCompleteBox and drop on the XAML page

clip_image012

2. Set the Binding, ValueMemberPath and FilterMode.

clip_image014

3. Set the DataTemplate and bind the TextBlock where user will type the text.

clip_image015

For reference,

MainPage.Xaml


<Grid x:Name="LayoutRoot" Background="White">
<sdk:AutoCompleteBox x:Name="atcTextBox" ItemsSource="{Binding}"
ValueMemberPath="CourseName"
FilterMode="Contains"
IsTextCompletionEnabled="True"
Height="30" Margin="62,22,54,248">
<sdk:AutoCompleteBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding CourseName}" />
</DataTemplate>
</sdk:AutoCompleteBox.ItemTemplate>

</sdk:AutoCompleteBox>

</Grid>

MainPage.Xaml.cs


using System;
using System.Collections.Generic;
using System.Windows.Controls;
using SilverlightApplication4.ServiceReference1;

namespace SilverlightApplication4
{
public partial class MainPage : UserControl
{
List<Courses> lstCourses = null;
public MainPage()
{
InitializeComponent();
Service1Client proxy = new Service1Client();
proxy.GetTitleToBindCompleted += 
new EventHandler<GetTitleToBindCompletedEventArgs>(proxy_GetTitleToBindCompleted);
proxy.GetTitleToBindAsync();

}

void proxy_GetTitleToBindCompleted(object sender, GetTitleToBindCompletedEventArgs e)
{

lstCourses = new List<Courses>();
var res = e.Result;
foreach (var r in res)
{
lstCourses.Add(new Courses { CourseName = r.ToString() });

}

atcTextBox.DataContext = lstCourses;
}
}
}

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.

System.ServiceModel.Web is missing in Visual Studio 2010 Console Application ?

I was creating a managed host application for WCF Service. Although it was just to write few lines of codes in console application, it took 1 hrs. for me to figure out a strange problem.

I followed steps as below,

1. Created a console application

2. I had to add reference of System.ServiceModel and System.ServiceModel.Web

And to my surprise System.ServiceModel.Web reference was missing,

clip_image001

When I started looking for a solution on missing System.ServiceModel.Web, I found it was designed not have it in console application. Because by default, Console Application targets to .Net Framework 4 client profile and client profile does not have System.ServiceModel.Web dll

clip_image003

So if you want to add System.ServiceModel.Web in console application, essentially you will have to change Target Framewrok of the console application.

To change target framework, right click and select Properties. On the Application tab you will get option to change

clip_image005

After changing target framework you will get System.ServiceModel.Web to add as reference in your console application project.

clip_image007