Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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;
            }
        }

    }
}
like image 799
Igor Zevaka Avatar asked May 06 '11 06:05

Igor Zevaka


People also ask

What is service metadata in WCF?

WCF services use metadata to describe how to interact with the service's endpoints so that tools, such as Svcutil.exe, can automatically generate client code for accessing the service. Most of the types that make up the WCF metadata infrastructure reside in the System. ServiceModel. Description namespace.

What are 3 basic WCF configurations required for hosting a WCF service?

There are three types of hosting environments for WCF services: IIS, WAS, and self-hosting. The term “self-hosting” refers to any application that provides its own code to initialize the hosting environment. This includes console, Windows Forms, WPF, and managed Windows services.


1 Answers

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();
}
like image 133
Igor Zevaka Avatar answered Nov 15 '22 09:11

Igor Zevaka