【问题标题】:WCF 4.0 Rest Service returns content-type text/htmlWCF 4.0 Rest 服务返回内容类型 text/html
【发布时间】:2012-02-17 17:51:22
【问题描述】:

我有一个 WCF 4.0 REST 服务。如果我在web.config 文件中启用automaticFormatSelectionEnabled,那么服务将根据HTTP“接受”标头正确选择序列化为XML 或JSON。

但是,当我使用浏览器发出 GET 命令时,响应正文以 XML 格式返回,但 HTTP 内容类型标头是“text/html”。这会导致浏览器没有意识到响应是 XML 并尝试将其呈现为 html(这当然不能很好地工作)。这使得在浏览器中测试我的 GET 方法变得更加困难。

如果我禁用automaticFormatSelectionEnabled,那么一切都会按预期工作(响应正文包含 XML 并且 HTTP 内容类型是“application/xml”),但是,我希望能够在请求时自动切换到 JSON。

在通过浏览器请求时,有什么方法可以使内容类型正确返回吗?

【问题讨论】:

  • 当它是 text/html 时,响应的正文是什么?它是否包含错误消息(通常是这样)?
  • 您可以使用 fiddler 之类的工具来查看浏览器正在使用什么 accept-Header(或使用调试器检查 WebOperationContext.Current.IncomingRequest)。至少您可以通过这种方式排除浏览器问题。
  • 浏览器的 Accept 标头是 "text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8" 我假设只是 FireFox 标准/默认值。响应正文是 XML(正确且预期的 XML),但问题是响应内容类型是 text/html,因此浏览器不会将其视为 XML 文档,而是尝试呈现为 HTML。
  • 如果您使用像addons.mozilla.org/firefox/addon/modify-headers 这样的插件并将Accept 标头设置为aplication/xml,您会看到它可以正常工作。

标签: .net wcf


【解决方案1】:

我遇到了同样的问题,这是一个解决方法。本质上,您需要做的是创建一个行为扩展,它将在发送响应时更改内容类型。

您的 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
}

现在应该可以正常工作了!

【讨论】:

  • 真的很好,但我只是想添加这些类的使用,也许他们会有所帮助: 第一类:使用 System.ServiceModel.Configuration 第二类:使用 System.ServiceModel.Web ;使用 System.ServiceModel;使用 System.ServiceModel.Dispatcher;使用 System.ServiceModel.Description;使用 System.Net;使用 System.ServiceModel.Channels;使用 System.Collections.ObjectModel;
  • 感谢 Bevan 提供的解决方案。我还会注意到,这与 ASP.NET WebAPI 开箱即用的一样。
猜你喜欢
  • 1970-01-01
  • 2011-06-16
  • 1970-01-01
  • 1970-01-01
  • 2014-09-17
  • 1970-01-01
  • 2011-09-09
  • 2014-12-15
  • 1970-01-01
相关资源
最近更新 更多