I've been working for a while on an application, too long to explain what it actually does, but the bottom line is that it requires, or at least it could benefit from having, a RESTful WCF service hosted on both http and https endpoints.
I toyed with the idea of doing the application in Python as it uses some Python code but I decided to stick with what I knew as I wanted to finish it quickly. At any rate, here is the code:
This is simply shown as an example of how it could be done, if you follow it, your end point will be listening on
http://<hostname>/store/ and can be invoked by simply navigating to it like this:
http://<hostname>/store?page=url
In order for the application to listen on https you will need to have a valid certificate on your certificate store. The subject name should match the hostname of the machine running this application and then this should work:
https://<hostname>/store?page=url
First the interface:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace WcfJsonRestService
{
[ServiceContract]
public interface IStore
{
[OperationContract]
bool Store(string item);
}
}
Then the class implementing the interface:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Configuration;
namespace WcfJsonRestService
{
public class Store : IStore
{
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "store?page={item}")]
public bool Store(string item)
{
//do stuff here
return true;
}
}
}
And finally a Console application that hosts the service.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
namespace WcfJsonRestService
{
class Program
{
static void Main(string[] args)
{
try
{
using (ServiceHost host = new ServiceHost(typeof(RESTful)))
{
AddServiceEndPoint(host, "https://{0}/store", true, "change me");
AddServiceEndPoint(host, "http://{0}/store", false);
host.Open();
Console.WriteLine("Service host running......");
Console.WriteLine("Press Any key at any time to exit...");
Console.Read();
host.Close();
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
Console.Read();
}
}
private static void AddServiceEndPoint(ServiceHost host, string url, bool useSSLTLS, string certSubjectName="")
{
string addressHttp = String.Format(url,
System.Net.Dns.GetHostEntry("").HostName);
WebHttpBinding binding;
if (useSSLTLS)
{
binding = new WebHttpBinding(WebHttpSecurityMode.Transport);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
binding.HostNameComparisonMode = HostNameComparisonMode.WeakWildcard;
binding.CrossDomainScriptAccessEnabled = true;
}
else
{
binding = new WebHttpBinding(WebHttpSecurityMode.None);
binding.CrossDomainScriptAccessEnabled = true;
}
// You must create an array of URI objects to have a base address.
Uri uri = new Uri(addressHttp);
Uri[] baseAddresses = new Uri[] { uri };
WebHttpBehavior behaviour = new WebHttpBehavior();
// Add an endpoint to the service. Insert the thumbprint of an X.509
// certificate found on your computer.
host.AddServiceEndpoint(typeof(IRESTful), binding, uri).EndpointBehaviors.Add(behaviour);
if (useSSLTLS)
{
host.Credentials.ServiceCertificate.SetCertificate(
StoreLocation.LocalMachine,
StoreName.My,
X509FindType.FindBySubjectName,
certSubjectName);
}
}
}
}
Alternatively, the WCF service can be hosted by a Windows service. Code behind for windows service here:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
using StoreAndConvert.WCFService;
using System.Security.Cryptography.X509Certificates;
using System.Configuration;
namespace StoreAndConvert.WindowsService
{
public partial class Store : ServiceBase
{
string certSubjectName = string.Empty;
ServiceHost host;
public Store()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
try
{
//Debugger.Launch();
certSubjectName = ConfigurationManager.AppSettings["CertificateSubjectName"];
host = new ServiceHost(typeof(StoreUrls));
AddServiceEndPoint(host, "https://{0}/storeurl", true, certSubjectName);
AddServiceEndPoint(host, "http://{0}/storeurl", false);
host.Open();
Trace.WriteLine("Service host running......");
Trace.WriteLine("Listening on");
foreach (ServiceEndpoint sep in host.Description.Endpoints)
{
Trace.WriteLine(string.Format("endpoint: {0} - BindingType: {1}",
sep.Address, sep.Binding.Name));
}
}
catch (Exception ex)
{
Trace.WriteLine(ex);
}
}
protected override void OnStop()
{
try
{
if (host != null)
{
host.Close();
}
}
catch (Exception ex)
{
Trace.WriteLine(ex);
}
}
private void AddServiceEndPoint(ServiceHost host, string url, bool useSSLTLS, string certSubjectName = "")
{
string addressHttp = String.Format(url,
System.Net.Dns.GetHostEntry("").HostName);
WebHttpBinding binding;
if (useSSLTLS)
{
binding = new WebHttpBinding(WebHttpSecurityMode.Transport);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
binding.HostNameComparisonMode = HostNameComparisonMode.WeakWildcard;
binding.CrossDomainScriptAccessEnabled = true;
}
else
{
binding = new WebHttpBinding(WebHttpSecurityMode.None);
binding.CrossDomainScriptAccessEnabled = true;
}
// You must create an array of URI objects to have a base address.
Uri uri = new Uri(addressHttp);
Uri[] baseAddresses = new Uri[] { uri };
WebHttpBehavior behaviour = new WebHttpBehavior();
// Add an endpoint to the service. Insert the thumbprint of an X.509
// certificate found on your computer.
host.AddServiceEndpoint(typeof(IStoreUrls), binding, uri).EndpointBehaviors.Add(behaviour);
if (useSSLTLS)
{
host.Credentials.ServiceCertificate.SetCertificate(
StoreLocation.LocalMachine,
StoreName.My,
X509FindType.FindBySubjectName,
certSubjectName);
}
}
}
}