如何在 Azure API 管理策略中重用响应上下文变量?

How Can I Reuse the Response Context Variable in Azure API Management Policy?

我正在使用 Azure API 管理解决方案编写概念证明。

我正在尝试编写执行以下操作的 <inbound> 政策:

这是我目前的政策:

<inbound>
  <base />

  <!-- Authenticate with the API and get authentication tokens for subsequent calls -->
  <send-request mode="new" response-variable-name="auth" timeout="20" ignore-error="true">
    <set-url>https://www.service.com/api/authenticate</set-url>
    <set-method>POST</set-method>
    <set-header name="Content-Type" exists-action="override">
      <value>application/json</value>
    </set-header>
    <set-body>
      @{
        var credentials = new JObject(); 

        credentials.Add(new JProperty("logonId", "{{API_LOGON_USERNAME}}")); 
        credentials.Add(new JProperty("logonPassword", "{{API_LOGON_PASSWORD}}")); 

        return credentials.ToString(); 
      }
    </set-body>
  </send-request>

  <!-- Make second query to a different endpoint, using the authentication tokens as http headers -->
  <send-request mode="new" response-variable-name="data" timeout="20" ignore-error="true">
    <set-url>https://www.service.com/api/data</set-url>
    <set-method>GET</set-method>
    <set-header name="TokenA" exists-action="override">
      <value>
        @{
          JObject identity = ((IResponse)context.Variables["auth"]).Body.As<JObject>(); 
          return identity.SelectToken("TokenA").ToString(); 
        }
      </value>
    </set-header>
    <set-header name="TokenB" exists-action="override">
      <value>
        @{ 
          JObject identity = ((IResponse)context.Variables["auth"]).Body.As<JObject>(); 
          return identity.SelectToken("TokenB").ToString(); 
        }
      </value>
    </set-header>
  </send-request>

  <!-- Return response from the second API -->
  <return-response response-variable-name="responseData">
    <set-status code="200" reason="OK" />
    <set-header name="Content-Type" exists-action="override">
      <value>application/json</value>
    </set-header>
    <set-body>
      @{ 
        JObject api_response = ((IResponse)context.Variables["data"]).Body.As<JObject>(); 
        return api_response.ToString();   
      }
    </set-body>
  </return-response>
</inbound>

我遇到的问题是为第二个 header(令牌 B)设置值。看来我不能 re-use 上下文变量 (IResponse)context.Variables["auth"].

当我查看跟踪时,我看到第一个 <set-header> 策略的以下输出:

"message":"Expression was successfully evaluated.", "value":"xxxxxxxxxxxxxxxxxxxxx"

但是对于第二个 <set-header> 政策,我得到:

"message":"Expression evaluation failed.", "details":"Object reference not set to an instance of an object."

我可以看到,在第一个策略上调用方法后,我无法再在第二个 <set-header> 策略中以相同的方式重用上下文变量。

我试过:

有人可以帮我解决语法问题,让我可以复制 IResponse object 或 JObject 以便我可以使用 .SelectToken() 阅读两次吗?我确定我误解了一个基本概念,但我远不是经验丰富的 C# 开发人员!

谢谢

您收到错误的原因是您阅读响应正文的方式。当您阅读正文时

JObject identity = ((IResponse)context.Variables["auth"]).Body.As<JObject>();

你基本上是从上下文变量中处理正文。因此,下次您读取变量主体时,它会抛出臭名昭著的 Object reference 错误。要在 Azure API 管理中读取主体,您需要在代码中使用 preservecontent 属性。所以你将阅读正文如下所示

JObject identity = ((IResponse)context.Variables["auth"]).Body.As<JObject>(preserveContent: true);

执行此操作时,将保留原始正文,并且在求值中仅注入正文的副本。 您可以在以下位置找到有关此内容的深入文档 "Set Body- APIM policy"