Introduction
This article provides an example of a self hosted WCF service over HTTPS with transaction. The article describes how to create a self-signed certificate, how to bind it to a port, how to edit the config files, and how to run the service and the client. The WCF service and some configuration is from the blog post Self hosted WCF https works only when IIS has a site w https binding of Bill at Cape Cod.
Background
For a WCF Service to use SSL, a certificate must be binded to the port where the WCF Service runs. In production environments, a valid certificate must be installed. In development environments, a self-signed certificate may be created. Three ways are presented to create and bind a self-signed certificate:
- With IIS Manager
- With the command-line tools makecert and netsh http. However,
makecert
is deprecated - With the provided
CreateCert.bat
which uses makecert, certutil and netsh http.
Certificate with IIS
- Start IIS Manager for example through Start/Run/inetmgr.exe.
- Select the top node (computer name).
- Double-click on icon Server Certificates.
- Click on the link Create Self-Signed Certificate.
- Specify a friendly name for the certificate, for example IIS self-signed.
- The certificate is added to the list of certificates.
- Select the Default Web Site node and click on Bindings link.
- Set
Port
to 44400
, choose SSL certificate
IIS self-signed, and click on OK.
- You can check that the certificate is binded to port
44400
with the following command:
netsh http show sslcert ipport=0.0.0.0:44400
Certificate with makecert
and netsh http
- Check if certificate already registered for port
44400
:
netsh http show sslcert ipport=0.0.0.0:44400
- If certificate already exists, delete it with:
netsh http delete sslcert ipport=0.0.0.0:44400
- Create certificate for
localhost
:
"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\x64\makecert" -ss My -sr LocalMachine -n CN=localhost -r
This will create the certificate localhost which you can see in Certificates Snap-in/Certificates (Local Computer)/Personal/Certificates. - The Certificates Snap-in can be viewed with: Start/Run/mmc/File/Add/Remove Snap-in.../Certificates/Add/Computer account/Next/Local computer/Finish
- Make certificate trusted. In Certificates Snap-in copy-paste: from Personal/Certificates/localhost to Trusted People/Certificates
- Copy thumbprint of certificate to clipboard: Double click on Personal/Certificates/localhost, then select tab page Details, click on Field Thumbprint and select text in textbox and Ctrl-C.
- Add certificate to port:
netsh http add sslcert ipport=0.0.0.0:44400 certhash=[certificate thumbprint] appid={12345678-1234-1234-1234-123456789012}
appid
seems not to play a role. - You can check that the certificate is binded to port
44400
with the following command:
netsh http show sslcert ipport=0.0.0.0:44400
Certificate with CreateCert.bat
The provided CreateCert.bat creates a self-signed certificate in store Personal and file c:\localhost.cer
, imports c:\localhost.cer
into store Trusted People, finds the thumbprint with certutil
and registers that certificate with port 44400
.
- Run as administrator CreateCert.bat. The output will be similar to the following:
C:\Windows\system32>"C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\makecert" -r -sk COMPUTER1 -sr LocalMachine -ss My -n CN=COMPUTER1,CN=localhost,CN=COMPUTER1 c:\localhost.cer
Succeeded
C:\Windows\system32>certutil -addstore TrustedPeople c:\localhost.cer
TrustedPeople "Trusted People"
Signature matches Public Key
Certificate "COMPUTER1" added to store.
CertUtil: -addstore command completed successfully.
C:\Windows\system32>del c:\localhost.cer
Created certificate with thumbprint=fa5ee6c56c066a5349ba64245e09580996ec5d56
C:\Windows\system32>netsh http delete sslcert ipport=0.0.0.0:44400
SSL Certificate deletion failed, Error: 2
The system cannot find the file specified.
C:\Windows\system32>netsh http add sslcert ipport=0.0.0.0:44400 certhash=fa5ee6c56c066a5349ba64245e09580996ec5d56 appid={12345678-1234-1234-1234-123456789012}
SSL Certificate successfully added
C:\Windows\system32>pause
Press any key to continue . . .
- Do not mind about the error
SSL Certificate deletion failed, Error: 2
This command deletes any certificate from port 44400, and fails, if no certificate is binded to that port. - You may check that port 44400 is binded to a certificate with the following command:
netsh http show sslcert ipport=0.0.0.0:44400
This should produce an output similar to the following:
SSL Certificate bindings:
-------------------------
IP:port : 0.0.0.0:44400
Certificate Hash : 022d408a952cbdd44ad0668f85254001510f4ee8
Application ID : {12345678-1234-1234-1234-123456789012}
Certificate Store Name : (null)
Verify Client Certificate Revocation : Enabled
Verify Revocation Using Cached Client Certificate Only : Disabled
Usage Check : Enabled
Revocation Freshness Time : 0
URL Retrieval Timeout : 0
Ctl Identifier : (null)
Ctl Store Name : (null)
DS Mapper Usage : Disabled
Negotiate Client Certificate : Disabled
Reject Connections : Disabled
Using the Code
The solution contains two projects:
WCFService
: Console application hosting a WCF Service WCFClient
: Console application calling the WCF Service
The service implements only one method:
<ServiceContract()>
Interface ITestService
<OperationContract()>
<TransactionFlow(TransactionFlowOption.Mandatory)>
Function GetResult() As String
End Interface
<ServiceBehavior(TransactionIsolationLevel:=
System.Transactions.IsolationLevel.Serializable,
TransactionTimeout:="00:00:30",
ReleaseServiceInstanceOnTransactionComplete:=False,
TransactionAutoCompleteOnSessionClose:=False,
IncludeExceptionDetailInFaults:=True)>
Public Class TestService
Implements ITestService
<OperationBehavior(TransactionScopeRequired:=True, TransactionAutoComplete:=True)>
Public Function GetResult() As String Implements ITestService.GetResult
Return String.Format("Hello, busy World. {0}", DateTime.Now.ToShortTimeString())
End Function
End Class
The client just calls the service once:
Sub Main()
Try
Using tx As New TransactionScope()
Dim client = New ServiceReference1.TestServiceClient
Dim result = client.GetResult
client.Close()
Console.WriteLine(result)
tx.Complete()
End Using
Catch ex As Exception
Console.WriteLine(ex.ToString)
End Try
Console.ReadKey()
End Sub
The address of the WCFService
is https://computer1.domain1.com:44400
and is registered in the app.config files of WCFClient
and WCFService
. You have to change this address to the one shown in the Certificates Snap-in:
Now, everything should be configured. To test:
- Build solution.
- Start WCFService\bin\Debug\WCFService.exe. You probably have to run it as administrator.
- Start WCFClient\bin\Debug\WCFClient.exe. You probably have to run it as administrator. If everything went OK, the following will be displayed:
History
- WCF Service with transaction and SSL
- Added CreateCert.bat, which creates and registers the certificate with
makecert
, certutil
, and netsh http sslcert
.