2011-05-12 37 views
1

我正在使用wcf編寫服務。 我創建了一個解決方案有兩個項目:在WCF中解決服務問題

  • 庫:一個項目來存儲相關服務(含接口和該服務的相應實現)文件。這個項目是一個圖書館項目。
  • 託管應用一種承載這些服務的(自託管)項目。由於這個原因,這個項目是一個可執行項目,它有一個配置文件,我在其中放置了配置服務所需的信息。

我也爲了調用服務編寫客戶端。這將被稱爲客戶端應用程序

我有一個服務。以下是接口和實現(庫項目):

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

以下是服務主機應用程序的啓動(可執行項目):

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..."); 
      } 
     } 
    } 
} 

以下是在執行項目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> 

以下是客戶端可執行項目(鏈接到庫項目的鏈接),basica lly這是客戶端:

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

那麼...我的問題是以下內容:此應用程序工作! 爲什麼它是一個問題? 的問題是,我指定的託管服務時,在App.config文件,三個端點:二basicHttp和一個元數據端點。那麼,我想要解決的端點有<endpoint address="/GoInto/Svc"...,我認爲這是完整的地址(注意我指定了一個基地址):http://localhost:8081/Service1/GoInto/Svc

不幸的是,在客戶端,我解決了這個端點:http://localhost:8081/Service1這只是基地址......爲什麼它工作?我想指定該地址在客戶端:

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

但如果我這樣做,不匹配引發錯誤:

與要 「HTTP消息://本地主機:8081 /服務1/GoInto/Svc' 無法在接收端 處進行處理,因爲EndpointDispatcher的地址篩選不匹配 。檢查發送方和接收方的 EndpointAddresses是否同意。

爲什麼它不工作?

回答

1

基地址必須在ServiceHost構造函數或元素中的一個地方指定。如果你在兩個地方都有,WCF會拋出一個異常,說你有兩個基地址用於同一個方案(HTTP)。

可能發生的情況是您在託管項目的app.config上的服務名稱不匹配,因此配置沒有被拾取(並且您得到的是默認端點,其地址位於與基地址相同)。嘗試在您的託管代碼中添加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...");