Something as simple as ad-hoc selfhosting a WCF service can be fairly difficult if you need to use https. This is because of all the underlying pieces than need to be configured to properly host on a secure transport. In this fairly lengthy posting, I will go through a walkthrough of creating a simple selfhosted HelloWorld WCF service, entirely by hand, and modify it to listen over https. Along the way, I will run into several common errors and give the solutions to these.
Disclaimer: By no means is this intended for production. The purpose of this is to give an example of test code which self-hosts a WCF service using https.
using System;
using System.ServiceModel;
namespace HttpsSelfhost
{
class Program
static void Main(string[] args)
string address = "http://localhost/HelloWorldService";
BasicHttpBinding binding = new BasicHttpBinding();
ServiceHost host = new ServiceHost(typeof(HelloWorldService));
host.AddServiceEndpoint(typeof(IHelloWorld), binding, address);
host.Open();
Console.WriteLine("Host is {0}. Press enter to close.", host.State);
Console.ReadLine();
host.Close();
}
[ServiceContract]
public interface IHelloWorld
[OperationContract]
void HelloWorld();
public class HelloWorldService : IHelloWorld
public void HelloWorld()
Console.WriteLine("Hello World!");
namespace HelloWorldClient
Console.WriteLine("Press enter when the service is opened.");
ChannelFactory<IHelloWorld> factory = new ChannelFactory<IHelloWorld>(binding, address);
IHelloWorld client = factory.CreateChannel();
Console.WriteLine("Invoking HelloWorld on the service.");
client.HelloWorld();
Console.WriteLine("Press enter to quit.");
string address = "http://localhost:1234/HelloWorldService";
Then restart VS as an admin. When I hit F5, I can start the client once the service indicates it's open.
string address = "https://localhost:1234/HelloWorldService";
This yields the following exception:
Parameter name: context.ListenUriBaseAddress
binding.Security.Mode = BasicHttpSecurityMode.Transport;
netsh http add urlacl url=https://+:1234/ user=EVERYONE
makecert.exe -sk RootCA -sky signature -pe -n CN=<machineName> -r -sr LocalMachine -ss Root MyCA.cer
makecert.exe -sk server -sky exchange -pe -n CN=<machineName> -ir LocalMachine -is Root -ic MyCA.cer -sr LocalMachine -ss My <certificate path>
using System.Diagnostics;
using System.IO;
using System.Security.Cryptography.X509Certificates;
namespace BindCertToPort
int port = 1234;
string certPath = "MyAdHocTestCert.cer";
X509Certificate2 certificate = new X509Certificate2(certPath);
// netsh http add sslcert ipport=0.0.0.0:<port> certhash={<thumbprint>} appid={<some GUID>}
Process bindPortToCertificate = new Process();
bindPortToCertificate.StartInfo.FileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.SystemX86), "netsh.exe");
bindPortToCertificate.StartInfo.Arguments = string.Format("http add sslcert ipport=0.0.0.0:{0} certhash={1} appid={{{2}}}", port, certificate.Thumbprint, Guid.NewGuid());
bindPortToCertificate.Start();
bindPortToCertificate.WaitForExit();
Note: If the certificate is still bound to the port, you still should be able to invoke the service over https.
X509Certificate2 cert = new X509Certificate2(certificatePath);
X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadWrite);
store.Remove(cert);
store.Close();
I want to reiterate that none of the above examples are intended for production; I'm only presenting them to provide one example of how to manually set up a self-hosted WCF service which uses https.