简体   繁体   English

Windows窗体应用程序调用WCF服务,而WCF服务调用另一个WCF服务

[英]windows form application calling a WCF service and the WCF service calling another WCF service

This is a sample project I built to test service calling another service 这是我为测试服务而建立的示例项目,该服务调用了另一个服务

This is the Service that gets called by the other service 这是其他服务调用的服务

namespace WCFPub
{
    [ServiceContract]
    public interface IStudent
    {
        [OperationContract]
        string getName(string name);
    }

}

namespace WCFPub
{
    public class Student : IStudent
    {
        public string getName(string name)
        {
            return "Your name is " + name;
        }
    }
}

Console application that hosts the above service 承载上述服务的控制台应用程序

namespace WCFHost
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                ServiceHost sh = new ServiceHost(typeof(WCFPub.Student));
                ServiceMetadataBehavior serviceMetadataBehaviour = new ServiceMetadataBehavior()
                {
                    HttpGetEnabled = true,

                };
                sh.Description.Behaviors.Add(serviceMetadataBehaviour);
                sh.AddServiceEndpoint(typeof(WCFPub.IStudent), new WSDualHttpBinding(), "PS");
                Console.WriteLine("Host Ready, Listening on 7060");
                Console.WriteLine("Hit Enter to Stop..");
                sh.Open();
                Console.ReadLine();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

        }
    }
}

Service that calls the second service 调用第二项服务的服务

namespace WCFPub2
{
    [ServiceContract]
    public interface IMaster
    {
        [OperationContract]
        string getNameFromStudent(string name);
    }

}

namespace WCFPub2
{

    public class Master : IMaster
    {
        public string getNameFromStudent(string name)
        {
            Proxy2.StudentClient client = new Proxy2.StudentClient();
            return client.getName("ABdi");
        }
    }
}

The console app that hosts the above service 托管上述服务的控制台应用程序

namespace WCFHost2
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                ServiceHost sh = new ServiceHost(typeof(WCFPub2.Master));
                ServiceMetadataBehavior serviceMetadataBehaviour = new ServiceMetadataBehavior()
                {
                    HttpGetEnabled = true,

                };
                sh.Description.Behaviors.Add(serviceMetadataBehaviour);
                sh.AddServiceEndpoint(typeof(WCFPub2.IMaster), new WSDualHttpBinding(), "PS");
                Console.WriteLine("Host Ready, Listening on 7061");
                Console.WriteLine("Hit Enter to Stop..");
                sh.Open();
                Console.ReadLine();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

        }
    }
}

The Client 客户端

namespace WCFClient
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void button1_Click(object sender, EventArgs e)
        {

            Proxy.MasterClient client = new Proxy.MasterClient();
            MessageBox.Show(client.getNameFromStudent("ABdi"));
        }
    }
}

This doesn't work and throws an exception 这不起作用并引发异常

System.ServiceModel.FaultException`1[System.ServiceModel.ExceptionDetail]: System.ServiceModel.FaultException`1 [System.ServiceModel.ExceptionDetail]:

Could not find default endpoint element that references contract 'Proxy2.IStudent' in the ServiceModel client configuration section. 在ServiceModel客户端配置部分中找不到引用合同'Proxy2.IStudent'的默认终结点元素。 This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element. 这可能是因为找不到您的应用程序的配置文件,或者是因为在客户端元素中找不到与该协定匹配的端点元素。

(Fault Detail is equal to An ExceptionDetail, likely created by IncludeExceptionDetailInFaults=true, whose value is: (故障详细信息等于ExceptionDetail,可能由IncludeExceptionDetailInFaults = true创建,其值为:
System.InvalidOperationException: Could not find default endpoint element that references contract 'Proxy2.IStudent' in the ServiceModel client configuration section. System.InvalidOperationException:在ServiceModel客户端配置部分中找不到引用合同'Proxy2.IStudent'的默认终结点元素。 This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element. 这可能是因为找不到您的应用程序的配置文件,或者是因为在客户端元素中找不到与该协定匹配的端点元素。

at System.ServiceModel.Description.ConfigLoader.LoadChannelBehaviors(ServiceEndpoint serviceEndpoint, String configurationName) 在System.ServiceModel.Description.ConfigLoader.LoadChannelBehaviors(ServiceEndpoint serviceEndpoint,字符串configurationName)
at System.ServiceModel.ChannelFactory.ApplyConfiguration(String configurationName, Configuration configuration) 在System.ServiceModel.ChannelFactory.ApplyConfiguration处(字符串configurationName,配置配置)
at System.ServiceModel.ChannelFactory.ApplyConfiguration(String configurationName) 在System.ServiceModel.ChannelFactory.ApplyConfiguration(String configurationName)
at System.ServiceModel.ChannelFactory.InitializeEndpoint(String configurationName, EndpointAddress address) 在System.ServiceModel.ChannelFactory.InitializeEndpoint(字符串configurationName,EndpointAddress地址)
at System.ServiceModel.ChannelFactory`1..ctor(String endpointConfigurationName, EndpointAddress remoteAddress) 在System.ServiceModel.ChannelFactory`1..ctor(字符串endpointConfigurationName,EndpointAddress remoteAddress)
at System.ServiceModel.Configu...). 在System.ServiceModel.Configu ...)。

I need help please 我需要帮助

I don't see where you specify addresses for services and clients (I don't see for ex. Host = new ServiceHost(new Service.BossService(), baseUrl ); or new Proxy.MasterClient(endpointConfiguraionName) or Proxy.MasterClient(binding, baseAddress)). 我没有看到你指定服务和客户端地址(我没有看到前主机=新的ServiceHost(新Service.BossService() 的baseUrl);或新Proxy.MasterClient(endpointConfiguraionName)或Proxy.MasterClient(绑定,baseAddress))。 If you are using config files everywhere (with addresses in it), then you do not need any extra steps for setting up services (Behaviors.Add, ...AddServiceEndpoint) - all service creation steps will be performed automatically by using config. 如果您到处都在使用配置文件(其中有地址),则不需要任何其他步骤来设置服务(Behaviors.Add,... AddServiceEndpoint)-所有服务创建步骤都将通过config自动执行。

My recommendations: 我的建议:

1) Remove all service hosting code, use only config file-based configuration (including base address, which can be relative if you are hosting in *.svc or absolute). 1)删除所有服务托管代码,仅使用基于配置文件的配置(包括基地址,如果在* .svc中托管,则可以是相对地址,也可以是绝对地址)。 This is much more flexible and convenient way (if you have possibility to use config files, coz sometimes you don't have) - I used it for years. 这是一种更加灵活和便捷的方式(如果您有可能使用配置文件,有时甚至没有),我已经使用了很多年。 See simple wcf configuration example ) 参见简单的wcf配置示例

2) Use singletone instance (as more predictable). 2)使用单调实例(更可预测)。 Finally you will have just one line of code like Host = new ServiceHost(new MyService()) . 最终,您将只有一行代码,例如Host = new ServiceHost(new MyService())

3) Do not use generated (svcutil) wcf client code. 3)不要使用生成的(svcutil)wcf客户端代码。 Just share contracts library (service contracts, data contracts) between service and client. 只需在服务和客户之间共享合同库(服务合同,数据合同)即可。 And then use ChannelFactory to call service methods: Channel = new ChannelFactory<MyService>("bindingConfigurationName").CreateChannel() or new ChannelFactory<MyService>(binding, serviceAddress).CreateChannel() . 然后使用ChannelFactory调用服务方法: Channel = new ChannelFactory<MyService>("bindingConfigurationName").CreateChannel()new ChannelFactory<MyService>(binding, serviceAddress).CreateChannel() This is just fine and enough to call service methods synchronously (with some extra work you can even call service methods asynchronously by knowing and using simple synchronous service interface!) 这很好,足以同步调用服务方法(通过做一些额外的工作,您甚至可以通过了解和使用简单的同步服务接口来异步调用服务方法!)

4) Do not use WSDualHttpBinding - it does not work as it should (at least over internet and firewalls). 4)不要使用WSDualHttpBinding-它不能正常工作(至少在Internet和防火墙上)。 I recommend tcpbinding (duplex by nature, works good almost everywhere). 我建议使用tcpbinding(本质上是双工的,几乎在任何地方都可以使用)。 But if you use WSDualHttpBinding - why don't you have bidirectional methods (duplex contract, see example )? 但是,如果您使用WSDualHttpBinding-为什么没有双向方法(双工协定,请参见示例 )?

5) Test you services with standard clients like wcftestclient, SoapUI, or even fiddler or postman (for RESTful services). 5)使用标准客户端(例如wcftestclient,SoapUI甚至是提琴手或邮递员)测试您的服务(用于RESTful服务)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM