How to programatically create a WCF service and its metadata on the same URL

10,291

Turns out the solution is simple. The documentation for HttpGetUrl is slightly obtuse, basically in order to get all three to work off the same URL you need to create the ServiceHost with the full URL of the service and then only set ServiceMetaBaseBehaviour.HttpGetEnable to true.

Relevant code is below.

var baseUri = new Uri("http://ws.test.com");
var serviceUri = new Uri(baseUri, serviceUrl);
BasicHttpBinding binding = new BasicHttpBinding();
using (var host = new ServiceHost(typeof(Fibonacci), serviceUri /*Specify full URL here*/))
{
    host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true /*Do not specify URL at all*/});
    host.Description.Behaviors.Find<ServiceDebugBehavior>().IncludeExceptionDetailInFaults = true;
    host.Description.Behaviors.Find<ServiceDebugBehavior>().HttpHelpPageUrl = serviceUri;

    host.AddServiceEndpoint(typeof(IFibonacci), binding, string.Empty /*Url here can either be empty or the same one as serviceUri*/);

    Console.WriteLine("Started service on cotnract {0}, ready for anything", typeof(IFibonacci).FullName);

    host.Open();
    _ResetEvent.WaitOne();
}
Share:
10,291
Igor Zevaka
Author by

Igor Zevaka

I am a software engineer in Sydney Australia. I have worked with most popular technologies and frameworks - C++ on Windows and Linux, Objective-C, ASP.NET, node.js, python and ruby. I have experience working in Financial sector, Fast Moving Consumer Goods, media and GIS. Currently I am working at nearmap.com as a senior developer/architect/team lead.

Updated on June 18, 2022

Comments

  • Igor Zevaka
    Igor Zevaka almost 2 years

    TL;DR
    I would to run all three things("You have created a web service" page, WSDL page and actual web service) on the same URL, similarly to a WCF service project created in a standalone WebService application.

    I am working on creating WCF endpoints programatically and got most of it together. The last thing is that I can't get the metadata URL to be the same as the service URL. I know this should be possible as you can create services like that from Visual Studio.

    What happens is I can browse WSDL in the browser, I can add it as a web reference but I can't invoke it from the newly created project. If I remove both friendly page and wsdl pages, i can invoke the service.

    Below is the code that I am using.

    class Program
    {
        private static ManualResetEvent _ResetEvent = new ManualResetEvent(false);
    
        static void Main(string[] args)
        {
            Console.TreatControlCAsInput = true;
    
            var serviceUrl = "Fibonacci.svc";
            new Thread(() =>
            {
                var baseUri = new Uri("http://ws.test.com");
                var serviceUri = new Uri(baseUri, serviceUrl);
                BasicHttpBinding binding = new BasicHttpBinding();
                using (var host = new ServiceHost(typeof(Fibonacci), new[] { baseUri }))
                {
                    host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true, HttpGetUrl = new Uri(baseUri, serviceUrl) });
                    host.Description.Behaviors.Find<ServiceDebugBehavior>().IncludeExceptionDetailInFaults = true;
                    host.Description.Behaviors.Find<ServiceDebugBehavior>().HttpHelpPageUrl = serviceUri;
    
                    host.AddServiceEndpoint(typeof(IFibonacci), binding, serviceUri);
    
                    Console.WriteLine("Started service on cotnract {0}, ready for anything", typeof(IFibonacci).FullName);
    
                    host.Open();
                    _ResetEvent.WaitOne();
                }
            }).Start();
    
    
    
            while (true)
            {
                var cki = Console.ReadKey(true);
                if (cki.Key == ConsoleKey.C && (cki.Modifiers & ConsoleModifiers.Control) != 0)
                {
                    _ResetEvent.Set();
                    break;
                }
            }
    
        }
    }