在单个ServiceHost中是否可以具有多种服务类型和服务终结点?

时间:2018-09-06 09:08:49

标签: c# web-services wsdl

也欢迎使用.NET 3.5但4.5解决方案。

我有几个WSDL,每个WSDL定义了一个我需要作为服务器托管的唯一Web服务。以下代码说明了我如何运行单个Web服务

using System;
using System.ServiceModel;
using System.ServiceModel.Description;

namespace Playground
{
    class Program
    {
        static BasicHttpBinding GetBinding()
        {
            var binding = new BasicHttpBinding();
            binding.MaxBufferSize = int.MaxValue;
            binding.MaxReceivedMessageSize = int.MaxValue;
            binding.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
            binding.AllowCookies = true;
            binding.MaxReceivedMessageSize = int.MaxValue;

            return binding;
        }

        static void Main(string[] args)
        {
            using (ServiceHost host = new ServiceHost(
                typeof(ServiceAImplementation),
                new Uri("http://127.0.0.1:8081/")
                ))
            {
                host.Description.Behaviors.Remove(typeof(ServiceDebugBehavior));
                host.Description.Behaviors.Add(
                    new ServiceDebugBehavior
                    {
                        IncludeExceptionDetailInFaults = true
                    });
                host.AddServiceEndpoint(typeof(ServiceAInterface), GetBinding(), "ServiceA.soap");

                try
                {
                    host.Open();
                }
                catch (TimeoutException timeoutExp)
                {
                    Console.WriteLine("Timeout");
                }
                catch (CommunicationException commExp)
                {
                    Console.WriteLine("Communication problem");
                }
                finally
                {
                    Console.WriteLine("Press any key to exit...");
                    Console.ReadLine();
                    host.Close();
                }
            }
        }
    }
}

我正在考虑将多个服务类型和服务点添加到同一主机。

假设我有以下服务:

  • ServiceAServiceAInterfaceServiceAImplementation,在http://127.0.0.1:8080/ServiceA.soap上可用
  • ServiceBServiceBInterfaceServiceBImplementation,在http://127.0.0.1:8081/ServiceB.soap上可用
  • ServiceCServiceCInterfaceServiceCImplementation,在http://127.0.0.1:8082/ServiceC.soap上可用

到目前为止,我还无法找到一种方法来使ServiceHost(请注意 a ,这意味着一个!)可以处理多个Web服务。单独的构造函数(ServiceHost(object, Uri[])ServiceHost(type, Uri[])显然指向一个主机,一个服务策略。当然可以分配多个服务端点,但这不能解决问题我要面对。

有没有办法做到这一点,或者我必须实现自己的自定义ServiceHost吗?

更新:看来我的问题不清楚。我知道我可以创建其他一些主机,然后基本上从上方为每个服务复制粘贴代码(我什至创建了一个版本,其中每个主机在单独的线程中运行)。我正在寻找一种主机,多种服务的解决方案。我已经通过添加单独的服务端点以及传递单个实现(上面示例代码中的Service...Implementation)来提供多个服务协定(Web服务的接口)的研究。问题在于,所有操作都具有至少一个重叠操作,这意味着相同的操作签名(返回类型,名称和输入参数),但是根据Web服务的不同,返回值也不同。是的,恕我直言,这些服务的设计不良,这是我必须处理的事情。

1 个答案:

答案 0 :(得分:0)

嗯,您之前读错了查询。

如果我现在正确地理解了您,我认为这是您的意思:

using System;
using System.ServiceModel;
using System.ServiceModel.Description;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            ServiceHost hostA = new ServiceHost(typeof(ServiceAImplementation), new Uri("http://127.0.0.1:6600/"));
            ServiceHost hostB = new ServiceHost(typeof(ServiceBImplementation), new Uri("http://127.0.0.1:6601/"));

            InitHost<ServiceAInterface>(hostA, "ServiceA.soap");
            InitHost<ServiceBInterface>(hostB, "ServiceB.soap");

            try
            {
                hostA.Open();
                hostB.Open();
            }
            catch (TimeoutException ex)
            {
                Console.WriteLine("Timeout");
            }
            catch (CommunicationException ex)
            {
                Console.WriteLine("Communication problem");
            }
            finally
            {
                Console.WriteLine("Press any key to exit...");
                Console.ReadLine();
                hostA.Close();
                hostB.Close();
            }
        }

        private static BasicHttpBinding GetBinding()
        {
            var binding = new BasicHttpBinding();
            binding.MaxBufferSize = int.MaxValue;
            binding.MaxReceivedMessageSize = int.MaxValue;
            binding.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
            binding.AllowCookies = true;
            binding.MaxReceivedMessageSize = int.MaxValue;

            return binding;
        }

        private static void InitHost<T>(ServiceHost host, string endpointEnd)
        {
            host.Description.Behaviors.Remove(typeof(ServiceDebugBehavior));
            host.Description.Behaviors.Add(
                new ServiceDebugBehavior
                {
                    IncludeExceptionDetailInFaults = true
                });
            host.AddServiceEndpoint(typeof(T), GetBinding(), endpointEnd);

            ServiceMetadataBehavior smb = host.Description.Behaviors.Find<ServiceMetadataBehavior>();
            if (smb == null)
                smb = new ServiceMetadataBehavior();
            smb.HttpGetEnabled = true;
            smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
            host.Description.Behaviors.Add(smb);
            host.AddServiceEndpoint(
              ServiceMetadataBehavior.MexContractName,
              MetadataExchangeBindings.CreateMexHttpBinding(),
              "mex"
            );
        }
    }
}

screenshot of WCFClient (sorry might be blocked by my firewall)