2011-09-09 19 views
2

我有一個服務兩個端點(SOAP,JSON)和一個服務方法

 [OperationContract] 
    [WebGet(UriTemplate = "/GetData")] 
    List<FieldInfo> GetSerializedData(); 

和web.config中

<system.web> 
    <webServices> 
     <protocols> 
     <add name="HttpGet" /> 
     <add name="HttpPost" /> 
     </protocols> 
    </webServices> 
    <httpRuntime executionTimeout="90" maxRequestLength="1048576" useFullyQualifiedRedirectUrl="false" minFreeThreads="8" minLocalRequestFreeThreads="4" appRequestQueueLimit="100"/> 
    <compilation debug="true" targetFramework="4.0"/> 
    </system.web> 
    <system.serviceModel> 
    <bindings> 
     <webHttpBinding> 
     <binding name="webHttpBindingSettings" maxBufferPoolSize="524288" maxReceivedMessageSize="654321" sendTimeout="00:10:00" closeTimeout="00:01:00" openTimeout="00:10:00" receiveTimeout="00:10:00"> 
      <security mode="None"> 
      <transport clientCredentialType="None" /> 
      </security> 
      <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" /> 
     </binding> 
     </webHttpBinding> 
     <wsHttpBinding> 
     <binding name="wsHttpBindingSettings" maxBufferPoolSize="524288" maxReceivedMessageSize="654321" sendTimeout="00:10:00" closeTimeout="00:01:00" openTimeout="00:10:00" receiveTimeout="00:10:00"> 
      <security mode="None"> 
      <transport clientCredentialType="None" /> 
      </security> 
      <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" /> 
     </binding> 
     </wsHttpBinding> 
    </bindings> 
    <services> 
     <service behaviorConfiguration="MetadataBehavior" name="ServiceModel.Service"> 
     <endpoint name="soap" address="soap" behaviorConfiguration="Default" binding="wsHttpBinding" 
      bindingConfiguration="wsHttpBindingSettings" contract="ServiceModel.IService" /> 
     <endpoint name="Json" address="json" behaviorConfiguration="JSON" binding="webHttpBinding" 
     bindingConfiguration="webHttpBindingSettings" contract="ServiceModel.IService" /> 
     <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> 
     <host> 
      <baseAddresses> 
      <add baseAddress="http://service.com/Service.svc/" /> 
      </baseAddresses> 
     </host> 
     </service> 
    </services> 
    <behaviors> 
     <serviceBehaviors> 
     <behavior name="MetadataBehavior"> 
      <dataContractSerializer maxItemsInObjectGraph="2147483647"/> 
      <serviceDebug includeExceptionDetailInFaults="true" /> 
      <serviceMetadata httpGetEnabled="true" /> 
     </behavior> 
     </serviceBehaviors> 
     <endpointBehaviors> 
     <behavior name="JSON"> 
      <webHttp automaticFormatSelectionEnabled="true"/> 
      <dataContractSerializer maxItemsInObjectGraph="10000000"/> 
     </behavior> 
     <behavior name="Default"> 
      <dataContractSerializer maxItemsInObjectGraph="10000000"/> 
     </behavior> 
     </endpointBehaviors> 
    </behaviors> 

爲什麼在客戶端只產生一個終點?

<client> 
    <endpoint address="http://service.renault.com/Service.svc/soap" 
    binding="wsHttpBinding" bindingConfiguration="soap" contract="ServiceReference1.IService" 
    name="soap" /> 
</client> 

我的觀點是從asp.net頁面codebehind執行服務方法,wcf在soap或json中返回數據依賴於ContentType。但是,如果在具有文本/ html內容的情況下,如何在asp.net頁面內容類型中設置application/json。我有理解它的問題。

+0

我認爲問題出在客戶端。你可以在客戶電話上發佈詳細信息嗎? –

+0

在客戶端只會生成一個端點 - soap;/ – netmajor

回答

1

如果可能的話,儘量在設計Visual Studio的是這樣的:

  • 解決方案
    • 與合同(僅IXXXXService)
    • 與實施網絡項目和所有端點項目(參考合同項目)
    • 客戶端項目不使用VS生成的代理,而是一個可以選擇正確的端點和協議的工廠。 (參考合同項目)

下面是我在一個場景中使用的樣本類與你相似:

public class ServiceHelper 
{ 

    /// <summary> 
    /// WCF proxys do not clean up properly if they throw an exception. This method ensures that the service 
    /// proxy is handeled correctly. Do not call TService.Close() or TService.Abort() within the action lambda. 
    /// </summary> 
    /// <typeparam name="TService">The type of the service to use</typeparam> 
    /// <param name="action">Lambda of the action to performwith the service</param> 
    [System.Diagnostics.DebuggerStepThrough] 
    public static void UsingProxy<TService>(Action<TService> action) 
     where TService : ICommunicationObject, IDisposable, new() 
    { 
     var service = new TService(); 
     bool success = false; 
     try 
     { 
      action(service); 
      if (service.State != CommunicationState.Faulted) 
      { 
       service.Close(); 
       success = true; 
      } 
     } 
     finally 
     { 
      if (!success) 
      { 
       service.Abort(); 
      } 
     } 
    } 
    /// <summary> 
    /// WCF proxys do not clean up properly if they throw an exception. This method ensures that the service 
    /// proxy is handeled correctly. Do not call TService.Close() or TService.Abort() within the action lambda. 
    /// </summary> 
    /// <typeparam name="TIServiceContract">The type of the service contract to use</typeparam> 
    /// <param name="action">Action to perform with the client instance.</param> 
    /// <remarks>In the configuration, an endpoint with names that maches the <typeparamref name="TIServiceContract"/> name 
    /// must exists. Otherwise, use <see cref="UsingContract&lt;TIServiceContract&gt;(string endpointName, Action<TIServiceContract> action)"/>. </remarks> 
    [System.Diagnostics.DebuggerStepThrough] 
    public static void UsingContract<TIServiceContract>(Action<TIServiceContract> action) 
    { 
     UsingContract<TIServiceContract>(
      typeof(TIServiceContract).Name, 
      action 
      ); 
    } 
    /// <summary> 
    /// WCF proxys do not clean up properly if they throw an exception. This method ensures that the service 
    /// proxy is handeled correctly. Do not call TService.Close() or TService.Abort() within the action lambda. 
    /// </summary> 
    /// <typeparam name="TIServiceContract">The type of the service contract to use</typeparam> 
    /// <param name="action">Action to perform with the client instance.</param> 
    /// <param name="endpointName">Name of the endpoint to use</param> 
    [System.Diagnostics.DebuggerStepThrough] 
    public static void UsingContract<TIServiceContract>(
      string endpointName, 
      Action<TIServiceContract> action) 
    { 
     var cf = new ChannelFactory<TIServiceContract>(endpointName); 
     var channel = cf.CreateChannel(); 
     var clientChannel = (IClientChannel)channel; 

     bool success = false; 
     try 
     { 
      action(channel); 
      if (clientChannel.State != CommunicationState.Faulted) 
      { 
       clientChannel.Close(); 
       success = true; 
      } 
     } 
     finally 
     { 
      if (!success) clientChannel.Abort(); 
     } 
    } 
} 

在客戶端的配置,我手動設置我的引用:

<system.serviceModel> 
<client> 
    <endpoint address="http://localhost/myapp/myservice.svc/soap" 
      binding="wsHttpBinding" 
      contract="MyProject.Contracts.IMyService" 
      name="IMyServiceSoap"/> 
    <endpoint address="http://localhost/myapp/myservice.svc/rest" 
      binding="webHttpBinding" 
      contract="MyProject.Contracts.IMyService" 
      name="IMyServiceRest"/> 

</client> 
</system.serviceModel> 

然後,在你的代碼,你可以簡單地調用:

 ServiceHelper.UsingContract<"IMyServiceSoap", MyProject.Contracts.IMyService>(
      svc => svc.DoTheJob() 
      ); 

 ServiceHelper.UsingContract<"IMyServiceRest", MyProject.Contracts.IMyService>(
      svc => svc.DoTheJob() 
      ); 

[編輯]服務器配置是類似這樣的:

<services> 
<service name="MyService"> 
    <endpoint address="soap" 
    binding="wsHttpBinding" 
         contract="MyContracts.IMyService"/> 
    <endpoint address="rest" 
    binding="webHttpBinding" 
         contract="MyContracts.IMyService"/> 
    <endpoint address="mex" 
         binding="mexHttpBinding" 
         contract="IMetadataExchange"/> 
</service> 
</services> 
+0

但是在您的解決方案中,soap或json序列化依賴於我,但是我想使用WCF功能來選擇正確的序列化類型取決於ContentType的請求 – netmajor

+0

序列化類型取決於端點(及其綁定)。沒有辦法改變單個端點的序列化類型。我可能錯過了什麼,確定請求的內容類型是什麼?換句話說,使用soap協議或其他協議的條件是什麼? –

+0

我的服務在asp.net頁面上調用,並且依賴於接受類型(application/json或application/soap + xml)應該返回適​​當的數據。現在我得到json,但肥皂失敗 – netmajor

3

爲什麼在客戶端只產生一個終點?

因爲WCF不會爲非SOAP端點發送元數據。與用於SOAP的WSDL和MEX不同,「REST」端點沒有廣泛使用的元數據格式(WADL就是其中之一,但它沒有多少用處,也沒有由WCF實現),所以在添加服務引用(或svcutil)中只會看到元數據中只有一個端點,並且只創建一個端點。

我想使用WCF功能,選擇合適的序列化類型取決於請求的ContentType

JSON VS XML是一種序列化類型決定; JSON vs SOAP不是(SOAP是一個明確定義的協議,其規則是什麼請求應該看起來像) - 請參閱WCF Dynamic Response Format的更多信息。您的webHttBinding -endpoint將執行此操作(根據傳入請求返回JSON或XML),因爲您啓用了自動格式選擇,但您使用此服務的方式不需要使用WCF客戶端 - 使用WebClient,HttpWebRequest應該工作得很好。

+0

其他問題是,即使我在瀏覽器中測試服務時鍵入http://service.renault.com/Service.svc/soap/GetSerializedData或http://服務時將json端點添加到客戶端.result.com/Service.svc/json/GetSerializedData.Json結果總是返回,當soap不是和WCF Trace返回時「從網絡接收到的XML存在問題,請參閱內部異常以獲取更多詳細信息。 > System.Xml.XmlException:由於消息正文爲空,因此無法讀取正文「 – netmajor

+1

您不能使用瀏覽器直接調用SOAP端點(即在地址欄中輸入地址)。所有的SOAP請求都是通過HTTP POST完成的,瀏覽器會發送一個GET請求來輸入在其欄中輸入的地址。 – carlosfigueira

相關問題