简体   繁体   English

解决WCF中的服务问题

[英]Problem addressing a service in WCF

I am writing a service using wcf. 我正在使用wcf编写服务。 I have created a solution with two projects: 我用两个项目创建了一个解决方案:

  • Library: A project to store files concerning the services (containing the interface and the corresponding implementations for that service). 库:一个项目,用于存储有关服务的文件(包含该服务的接口和相应的实现)。 This project is a library project. 该项目是一个图书馆项目。
  • Hosting application A project for hosting these services (self-hosting). 托管应用程序用于托管这些服务的项目(自我托管)。 For this reason, this project is an executable project having a config file where I put the information needed in order to configure the services. 由于这个原因,该项目是具有配置文件的可执行项目,我在其中放置了用于配置服务所需的信息。

I have also written a client in order to call the service. 我还写了一个客户来打电话给该服务。 This will be referred to as the Client application . 这将称为“ 客户端应用程序”

I have a service. 我有服务 Following are the interface and the implementation (library project): 以下是界面和实现(图书馆项目):

namespace EchoWcfLibrary {
    /// <summary>
    /// The interface specifies for those classes implementing it (services), the operation that the service will expose.
    /// </summary>
    [ServiceContract]
    public interface IService1 {
        // This does not use serialization (implicit serialization in considered: base types used).
        [OperationContract]
        string GetData(int value);
        // This uses data contracts and serialization.
        [OperationContract]
        CompositeType GetDataUsingDataContract(CompositeType composite);
    }

    [DataContract]
    public class CompositeType {
        // Members not serialized
        bool boolValue = true;
        string stringValue = "Hello ";
        // Serialized
        [DataMember]
        public bool BoolValue {
            get { return boolValue; }
            set { boolValue = value; }
        }
        // Serialized
        [DataMember]
        public string StringValue {
            get { return stringValue; }
            set { stringValue = value; }
        }
    }
}

Following is the startup of the service host application (the executable project): 以下是服务主机应用程序(可执行项目)的启动:

namespace WcfServiceApplication {
    public static class Program {
        static void Main(string[] args) {
            // Setting endpoints and setting the service to start properly.
            // Base address specified: http://localhost:8081/Service1
            Console.WriteLine("Beginning...");
            using (ServiceHost host = new ServiceHost(typeof(Service1), new Uri("http://localhost:8081/Service1"))) {
                Console.WriteLine("Opening host...");
                host.Open();
                Console.WriteLine("Waiting...");
                System.Threading.Thread.Sleep(1000000);
                Console.WriteLine("Closing...");
                host.Close();
                Console.WriteLine("Quitting...");
            }
        }
    }
}

Following is the App.config in the executable project (hosting application): 以下是可执行项目(托管应用程序)中的App.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

    <!-- When deploying the service library project, the content of the config file must be added to the host's 
  app.config file. System.Configuration does not support config files for libraries. -->
    <system.serviceModel>
        <services>
            <service name="WcfServiceLibrary.Service1">
                <host>
                    <baseAddresses>
                        <add baseAddress="http://localhost:8081/Service1" />
                    </baseAddresses>
                </host>
                <!-- Service Endpoints -->
                <!-- Unless fully qualified, address is relative to base address supplied above -->
                <endpoint address="/GoInto/Svc" 
                                    binding="basicHttpBinding" 
                                    contract="WcfServiceLibrary.IService1">
                    <!-- 
              Upon deployment, the following identity element should be removed or replaced to reflect the 
              identity under which the deployed service runs.  If removed, WCF will infer an appropriate identity 
              automatically.
          -->
                    <identity>
                        <dns value="localhost"/>
                    </identity>
                </endpoint>
                <endpoint address="/GoInto/Sav"
                                    binding="basicHttpBinding"
                                    contract="WcfServiceLibrary.IService1">
                    <!-- 
              Upon deployment, the following identity element should be removed or replaced to reflect the 
              identity under which the deployed service runs.  If removed, WCF will infer an appropriate identity 
              automatically.
          -->
                    <identity>
                        <dns value="localhost"/>
                    </identity>
                </endpoint>
                <!-- Metadata Endpoints -->
                <!-- The Metadata Exchange endpoint is used by the service to describe itself to clients. -->
                <!-- This endpoint does not use a secure binding and should be secured or removed before deployment -->
                <endpoint address="GoInto/Mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
            </service>
        </services>

        <behaviors>
            <serviceBehaviors>
                <behavior>
                    <!-- To avoid disclosing metadata information, 
          set the value below to false and remove the metadata endpoint above before deployment -->
                    <serviceMetadata httpGetEnabled="True"/>
                    <!-- To receive exception details in faults for debugging purposes, 
          set the value below to true.  Set to false before deployment 
          to avoid disclosing exception information -->
                    <serviceDebug includeExceptionDetailInFaults="False" />
                </behavior>
            </serviceBehaviors>
        </behaviors>
    </system.serviceModel>

</configuration>

Following is the program startup in the client executable project (a link to library project has been made), basically this is the client: 以下是客户端可执行项目中的程序启动(已链接到库项目),基本上这是客户端:

namespace WcfServiceClient {
    class Program {
        static void Main(string[] args) {
            ServiceEndpoint httpEndpoint = new ServiceEndpoint(ContractDescription.GetContract(typeof(IService1)), new BasicHttpBinding(), new EndpointAddress("http://localhost:8081/Service1"));
            ChannelFactory<IService1> channelFactory = new ChannelFactory<IService1>(httpEndpoint);
            IService1 svc = channelFactory.CreateChannel();
            Console.WriteLine(svc.GetData(121));
            System.Threading.Thread.Sleep(10000);
        }
    }
}

Well... My problem is the following: this application WORKS!!! 好吧...我的问题如下:此应用程序有效!!! Why is it a problem??? 为什么有问题呢??? The problem is that I specified, when hosting the service, in the App.config file, three endpoints: two basicHttp and one metadata endpoint. 问题是,在托管服务时,我在App.config文件中指定了三个终结点:两个basicHttp和一个元数据终结点。 Well, I would like to address the <endpoint address="/GoInto/Svc"... endpoint which has, I assume this to be the complete address (note that I have specified a base address): http://localhost:8081/Service1/GoInto/Svc . 好吧,我想解决<endpoint address="/GoInto/Svc"...终结点,该终结点具有完整的地址(请注意,我已经指定了基本地址): http://localhost:8081/Service1/GoInto/Svc

Well, unfortunately, in the client, I address this endpoint: http://localhost:8081/Service1 which is just the base address...... WHY DOES IT WORK???? 好吧,不幸的是,在客户端中,我寻址了这个端点: http://localhost:8081/Service1 ,这仅仅是基地址……为什么这样做? I want to specify this address in the client: 我想在客户端中指定此地址:

namespace WcfServiceClient {
    class Program {
        static void Main(string[] args) {
            ServiceEndpoint httpEndpoint = new ServiceEndpoint(ContractDescription.GetContract(typeof(IService1)), new BasicHttpBinding(), new EndpointAddress("http://localhost:8081/Service1/GoInto/Svc"));
            ChannelFactory<IService1> channelFactory = new ChannelFactory<IService1>(httpEndpoint);
            IService1 svc = channelFactory.CreateChannel();
            Console.WriteLine(svc.GetData(121));
            System.Threading.Thread.Sleep(10000);
        }
    }
}

But if I do this, a mismatch error is raised: 但是,如果我这样做,则会引发不匹配错误:

The message with To 'http://localhost:8081/Service1/GoInto/Svc' cannot be processed at the receiver, due to an AddressFilter mismatch at the EndpointDispatcher. 由于EndpointDispatcher上的AddressFilter不匹配,因此无法在接收方处理带有To'http:// localhost:8081 / Service1 / GoInto / Svc'的消息。 Check that the sender and receiver's EndpointAddresses agree. 检查发送方和接收方的EndpointAddresses是否一致。

Why doesn't it work? 为什么不起作用?

The base address must be specified in one place, either on the ServiceHost constructor, or in the element. 基址必须在ServiceHost构造函数或元素中的一个位置中指定。 If you have in both places, WCF will throw an exception saying that you have two base addresses for the same scheme (HTTP). 如果您在两个地方都有,则WCF会抛出一个异常,指出您具有同一方案(HTTP)的两个基地址。

What is likely happening is that you have a mismatch on the service name on app.config of the hosting project, so that configuration is not being picked up (and what you get is a default endpoint, whose address is at the same one as the base address). 可能发生的情况是您在托管项目的app.config上的服务名称不匹配,因此未选择配置(您得到的是默认终结点,该终结点的地址与该终结点的地址相同)。基本地址)。 Try adding the foreach loop on your hosting code, and you should see the addresses of the endpoints your service is listening at. 尝试在托管代码上添加foreach循环,您应该看到服务正在侦听的端点的地址。

                Console.WriteLine("Opening host...");
            host.Open();

            foreach (ServiceEndpoint endpoint in host.Description.Endpoints)
            {
                Console.WriteLine("Endpoint:");
                Console.WriteLine("   Address: {0}", endpoint.Address.Uri);
                Console.WriteLine("   Binding: {0}", endpoint.Binding);
                Console.WriteLine("   Contract: {0}", endpoint.Contract.Name);
            }

            Console.WriteLine("Waiting...");

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

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