2011-11-16 59 views
4

我有一個WCF 4.0 REST服務。如果我在web.config文件中啓用automaticFormatSelectionEnabled,則服務將根據HTTP「Accept」標頭正確選擇序列化爲XML還是JSON。WCF 4.0 Rest服務返回內容類型的文本/ html

但是,當我使用瀏覽器發出GET命令時,響應主體將回到格式化爲XML格式,但HTTP內容類型標頭爲「text/html」。這導致瀏覽器沒有意識到響應是XML並嘗試將其呈現爲html(這當然不起作用)。這使得在瀏覽器中測試我的GET方法變得更加困難。

如果我禁用automaticFormatSelectionEnabled然後一切按預期工作(響應正文包含XML和HTTP內容類型是「application/xml」),但是,我希望能夠根據請求自動切換到JSON。

當通過瀏覽器請求時,是否有某種方法可以使內容類型正確回來?

+0

當它是text/html時,響應的主體是什麼?它是否包含錯誤消息(通常它會)? – carlosfigueira

+0

您可以使用像fiddler這樣的工具來查看瀏覽器正在使用的accept-Header(或使用調試器檢查WebOperationContext.Current.IncomingRequest)。至少你可以通過這種方式排除瀏覽器問題。 –

+0

瀏覽器的Accept頭是「text/html,application/xhtml + xml,application/xml; q = 0.9,*/*; q = 0.8」,我假設它只是FireFox的標準/默認值。響應主體是XML(正確和預期的XML),但問題在於響應內容類型爲text/html,因此瀏覽器不會將其視爲XML文檔,而是嘗試以HTML形式呈現。 –

回答

3

我遇到了同樣的問題,這裏有一個解決辦法。基本上你需要做的是創建一個行爲擴展,在發送響應時會改變內容類型。

你的web.config需要包括像:

<behaviors> 
    <serviceBehaviors> 
    <behavior name="WebServiceBehavior"> 
     <serviceMetadata httpGetEnabled="true" /> 
     <serviceDebug includeExceptionDetailInFaults="false" /> 
     <MessageInspector/> 
    </behavior> 
    </serviceBehaviors> 
</behaviors> 
<extensions> 
    <behaviorExtensions> 
    <add name="MessageInspector" 
      type="Namespace.ServiceContentTypeBehaviorExtensionElement, assembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> 
    </behaviorExtensions> 
</extensions> 

然後你需要創建一個從BehaviorExtensionElement

繼承
public class ServiceContentTypeBehaviorExtensionElement : BehaviorExtensionElement 
{ 
    protected override object CreateBehavior() 
    { 
     return new ServiceContentTypeMessageInspector(); 
    } 

    public override Type BehaviorType 
    { 
     get 
     { 
      return typeof(ServiceContentTypeMessageInspector); 
     } 
    } 
} 

然後終於實現IDispatchMessageInspector和類的類IServiceBehavior,它努力改變內容類型:

public class ServiceContentTypeMessageInspector : IDispatchMessageInspector, IServiceBehavior 
{ 

    #region IDispatchMessageInspector 

    public object AfterReceiveRequest(ref Message request, IClientChannel channel, 
     InstanceContext instanceContext) 
    { 
     return null; 
    } 

    public void BeforeSendReply(ref Message reply, object correlationState) 
    { 
     // inspect and/or modify the reply 
     if (WebOperationContext.Current.OutgoingResponse.Headers[HttpResponseHeader.ContentType] == "text/html; charset=utf-8" && 
      WebOperationContext.Current.OutgoingResponse.Format == WebMessageFormat.Xml) 
     { 
      WebOperationContext.Current.OutgoingResponse.Headers[HttpResponseHeader.ContentType] = "application/xml; charset=utf-8"; 
     } 
    } 

    #endregion 

    #region IServiceBehavior 

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, 
     ServiceHostBase serviceHostBase) 
    { 
     foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers) 
     { 
      foreach (var endpoint in dispatcher.Endpoints) 
      { 
       endpoint.DispatchRuntime.MessageInspectors.Add(new ServiceContentTypeMessageInspector()); 
      } 
     } 
    } 

    public void AddBindingParameters(ServiceDescription serviceDescription, 
     ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, 
     BindingParameterCollection bindingParameters) 
    { 
    } 

    public void Validate(ServiceDescription serviceDescription, 
     ServiceHostBase serviceHostBase) 
    { 
    } 

    #endregion 
} 

應該按預期工作吧!

+0

真不錯,但我只是想補充的usings這些類,也許他們會幫忙: 第一類: 使用System.ServiceModel.Configuration 第二類: 使用System.ServiceModel.Web ; using System.ServiceModel; using System.ServiceModel.Dispatcher; using System.ServiceModel.Description;使用System.Net的 ; using System.ServiceModel.Channels; using System.Collections.ObjectModel; – Khattab

+0

感謝Bevan提供解決方案。我還會注意到,這是ASP.NET WebAPI開箱即用的方式。 –