Как программно создать службу WCF и ее метаданные на том же URL

#.net #wcf #web-services

#.net #wcf #веб-сервисы

Вопрос:

TL; DR
Я бы запустил все три вещи (страницу «Вы создали веб-службу», страницу WSDL и фактическую веб-службу) по одному и тому же URL, аналогично проекту службы WCF, созданному в автономном веб-сервисном приложении.

Я работаю над программным созданием конечных точек WCF и собрал большую часть этого вместе. Последнее, что я не могу сделать, чтобы URL метаданных совпадал с URL службы. Я знаю, что это должно быть возможно, поскольку вы можете создавать подобные службы из Visual Studio.

Что происходит, я могу просматривать WSDL в браузере, я могу добавить его в качестве веб-ссылки, но я не могу вызвать его из вновь созданного проекта. Если я удалю как дружественную страницу, так и страницы wsdl, я смогу вызвать службу.

Ниже приведен код, который я использую.

 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 amp;amp; (cki.Modifiers amp; ConsoleModifiers.Control) != 0)
            {
                _ResetEvent.Set();
                break;
            }
        }

    }
}
  

Ответ №1:

Оказывается, решение простое. Документация для HttpGetUrl немного бестолковая, в основном для того, чтобы заставить все три работать с одним и тем же URL, вам нужно создать ServiceHost с полным URL сервиса, а затем установить только ServiceMetaBaseBehaviour.HttpGetEnable значение true .

Соответствующий код приведен ниже.

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

Ответ №2:

Любезно предоставлено из статьи в InfoWorld, смотрите 4-ю строку для альтернативного, более чистого метода указания конечной точки mex, который позволяет избежать любых проблем с URL, упомянутых выше. Это полезно, когда служба предоставляет конечные точки с использованием других привязок (например, netTcp):

         host.Description.Behaviors.Add(New ServiceMetadataBehavior() With {.HttpGetEnabled = True})
        host.Description.Behaviors.Find(Of ServiceDebugBehavior)().IncludeExceptionDetailInFaults = True
        host.Description.Behaviors.Find(Of ServiceDebugBehavior)().HttpHelpPageUrl = serviceUri

        host.AddServiceEndpoint(GetType(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex")
  

(принося извинения тем, у кого аллергия на VB)