在WCF Azure服务总线中动态分配json响应内容类型

本文关键字:响应 json 类型 动态分配 WCF Azure 服务 总线 | 更新日期: 2023-09-27 17:58:49

我正在编写一个使用Microsoft.ServiceBus.dll 1.0.0.0(.NET 3.5版本)的POC应用程序。

我的WCF合同和服务如下所示:

[ServiceContract(Name="MyServiceContract", Namespace = "http://mydomain.com/")]
internal interface IServiceContract
{
    [WebInvoke(Method = "POST", UriTemplate = "/DoOperation")]
    [OperationContract]
    Stream RelayRequest(Stream requestBody);
}
[ServiceBehavior(Name = "Service1", Namespace = "http://mydomain.com/Service1/", InstanceContextMode = InstanceContextMode.Single)]
internal class Service1 : IServiceContract
{
    Stream RelayRequest(Stream requestBody)
    {
        var contents = GetJsonResponse();
        var responseStream = new MemoryStream();
        var streamWriter = new StreamWriter(responseStream);
        streamWriter.AutoFlush = true;
        var writer = new JsonTextWriter(streamWriter);
        var serializer = new JsonSerializer();
        serializer.Serialize(responseStream, contents);
        responseStream.Position = 0 // reset the position of the stream so that it's contents will be read from the beginning.
        //Problem Line:
        WebOperationContext.OutgoingResponse.ContentType = "application/json";
        return responseStream;
    }
}

侦听端点配置为使用WebHttpRelayBinding:

  • 安全模式:传输
  • 传输模式:流式传输

当我尝试将传出响应的ContentType分配给"application/json"时,不会发生错误,但调用请求返回状态代码504(网关超时)。

如果我将ContentType更改为"text/javascript",则调用请求将返回200(OK)。

需要注意的一些事项:

  • 内容类型直到运行时才知道,因此必须动态分配
  • 流的内容是纯的-100%有效-json
  • 接受和返回流的目的是为了接受流式请求并将数据流式传输到客户端。
    • 每个请求/响应可以包含一个小的json负载或一个200MB的文档
  • 如果您想重新编写-此代码将使用NewtonsoftJson库进行序列化

为什么会发生这种情况,我该如何解决?

编辑:504状态代码可能是我正在测试的fiddler推断的转移注意力的代码。从System.Net.Http.HttpClient发送相同的请求表示在收到响应之前连接已关闭。

EDIT:将内容类型设置为几乎所有其他值(包括非敏感值)都可以正常工作我能打破它的唯一内容类型是application/json

在WCF Azure服务总线中动态分配json响应内容类型

这就是我让它工作的方式,但它是一个在IIS中本地托管的简单WCF服务。我不使用Microsoft.ServiceBus或Azure。

第一小提琴手的回应。如果这是你想要的,那么继续代码:)

HTTP/1.1 200 OK
Cache-Control: private
Content-Length: 121
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/7.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Thu, 04 Apr 2013 17:17:05 GMT
[{"BoolValue":true,"StringValue":"blah"},{"BoolValue":false,"StringValue":"boo"},{"BoolValue":true,"StringValue":"floo"}]

服务定义:

namespace yourNS
{
    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        [WebGet(UriTemplate = "/CT", ResponseFormat = WebMessageFormat.Json)]
        List<CompositeType> GetData();
    }

    [DataContract]
    public class CompositeType
    {
        [DataMember]
        public bool BoolValue { get; set; }
        [DataMember]
        public string StringValue { get; set; }
    }
    public class Service1 : IService1
    {
        public List<CompositeType> GetData()
        {
            return new List<CompositeType>
            {
                new CompositeType { BoolValue = true, StringValue = "blah" },
                new CompositeType { BoolValue = false, StringValue = "boo" },
                new CompositeType { BoolValue = true, StringValue = "floo" },
            };
        }
    }
}

和web.config

<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <services>
      <service name="yourNS.Service1">
        <endpoint 
          address="" 
          binding="webHttpBinding" 
          behaviorConfiguration="MyBehave"
          contract="yourNS.IService1" />
      </service>
    </services>
    <behaviors>
      <endpointBehaviors>
        <behavior name="MyBehave">
          <webHttp />
        </behavior>
      </endpointBehaviors>
      <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="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
</configuration>