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

Posted

技术标签:

【中文标题】在 WCF Azure 服务总线中动态分配 json 响应内容类型【英文标题】:Dynamically assigning json response content-type in WCF Azure Service Bus 【发布时间】:2013-01-28 13:48:25 【问题描述】:

我正在编写一个使用 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:

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

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

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

注意事项:

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

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

编辑:504 状态代码可能是我正在测试的提琴手 推断的红鲱鱼。 从 System.Net.Http.HttpClient 发送相同的请求表示在收到响应之前连接已关闭。

编辑:将内容类型设置为几乎任何其他内容(包括无意义的值)都可以正常工作。我可以打破它的唯一内容类型是 application/json

【问题讨论】:

你能从你的配置文件中添加信息/你是如何设置服务的吗?您使用的是什么类型的绑定? 如上所述,我们使用 WebHttpRelayBinding。这个绑定/端点不是由配置创建的,它是在运行时以编程方式创建的。 啊,我猜我看了你的描述有一系列的心理失误...... 解决这个问题有进展吗? 不幸的是,没有。我们最终使用自定义标题解决了这个问题。 【参考方案1】:

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

First Fiddler 的回应。如果这是您正在寻找的内容,请继续编写代码:)

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>

【讨论】:

您的解决方案之所以有效,是因为您已经从最初导致问题的原始问题中消除了所有复杂性。如原始问题所述,我需要动态分配响应内容类型,我还需要使用 Azure Service Bus 来实现这一点。

以上是关于在 WCF Azure 服务总线中动态分配 json 响应内容类型的主要内容,如果未能解决你的问题,请参考以下文章

Azure 服务总线与服务远程处理、HTTP 和 WCF

是否可以创建 WCF 服务端点来处理来自 Azure 服务总线的死信?

Azure 服务总线中继偶发性故障异常

如何在 azure 上以编程方式托管 wcf 服务

如何使用 terraform 将多个 IP 动态添加到 azure servicebus 防火墙

MSMQ 在 Azure 上是不是可用