【问题标题】:Azure APIM Soap ServiceAzure APIM 肥皂服务
【发布时间】:2019-11-29 14:54:43
【问题描述】:

我们使用 Azure APIM 来托管我们的 SOAP 服务并将 C# 代码与服务端点集成并通过 HttpClient 进行调用。我们总是手动创建元素并将值添加到元素的内部文本并将其作为字符串内容发送到服务。这请求很少的元素很简单,但是当涉及到一个巨大的请求时,我们必须花费大量时间手动创建soap xml请求,而且很耗时,容易出错?有没有更好的方法向 APIM 发送soap 请求并解析soap 响应?

【问题讨论】:

  • 你为什么使用HttpClient,它不理解SOAP,而不是例如为此目的设计的WCF?

标签: c# azure azure-api-management apim


【解决方案1】:

您可以在 APIM > API 操作中编写入站策略,然后将请求发送到后端soap服务。

请找到以下参考。

<policies>
<inbound>
    <base />
    <rewrite-uri template="/your_soap_service_url.svc" copy-unmatched-params="false" />
    <set-body template="none">@{
          string message = context.Request.Body.As<String>(preserveContent:true);
            try
            {
                 you can write your logic here, if you want to manipulale your request

            }
            catch{}

           string soapPacketStart = "<soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:yourNamespace=\"namespace url, if you have namespace in your message">
                <soap:Header xmlns:wsa=\"http://www.w3.org/2005/08/addressing\">
                    <wsa:Action>YourAction</wsa:Action>
                    <wsa:To>https://your_backend_url.svc</wsa:To>
                </soap:Header>
                <soap:Body>";
            string soapPacketEnd ="</soap:Body>
            </soap:Envelope>";
            message = string.Format("{0}{1}{2}",soapPacketStart,message,soapPacketEnd); //your soap message is ready
            return message;
        }</set-body>
        <set-header name="Content-Type" exists-action="override">
            <value>application/soap+xml; Action="YourAction"</value>
        </set-header>
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
                //like wise you can set your response
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

【讨论】:

    【解决方案2】:

    您可以使用 APIManagementARMTemplateCreator 将其自动化,它会为您的 API 提取 ARM 模板,以便在 CI/CD 流程中使用。

    【讨论】:

    • 如果在发送到后端 api 之前编写入站策略制定肥皂正文怎么办?
    • 是的,你可以这样做
    【解决方案3】:

    您可以在流动模板中定义您的 SOAP 请求正文并解析 XML 响应并将其转换回 json,如下例所示:

    <policies>
        <inbound>
            <base />
            <set-header name="Content-Type" exists-action="override">
                <value>text/xml;charset=UTF-8</value>
            </set-header>
            <set-method>POST</set-method>
            <set-body template="liquid">
                <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tim="http://services.test.com/Service">
                    <soapenv:Header />
                    <soapenv:Body>
                        <tim:GetTimesheet>
                            <tim:input>
                                <tim:DateTimeFrom>{{context.Request.MatchedParameters["DateTimeFrom"]}}</tim:DateTimeFrom>
                                <tim:DateTimeTo>{{context.Request.MatchedParameters["DateTimeTo"]}}</tim:DateTimeTo>
                                <tim:ResourceId>{{context.Request.MatchedParameters["ResourceId"]}}</tim:ResourceId>
                            </tim:input>
                        </tim:GetTimesheet>
                    </soapenv:Body>
                </soapenv:Envelope>
            </set-body>
            <set-backend-service base-url="https://webservices/service.svc" />
            <rewrite-uri template="/" copy-unmatched-params="false" />
        </inbound>
        <backend>
            <base />
        </backend>
        <outbound>
            <base />
            <xsl-transform>
                <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
                    <xsl:output method="xml" indent="yes" />
                    <xsl:template match="* | @* | node()">
                        <xsl:apply-templates select="@* | node()|*" />
                    </xsl:template>
                    <xsl:template match="PeriodList">
                        <item>
                            <xsl:for-each select="PeriodType">
                                <timeSheet>
                                    <DateTimeFrom>
                                        <xsl:value-of select="*[local-name() = 'DateFrom']" />
                                    </DateTimeFrom>
                                    <DateTimeTo>
                                        <xsl:value-of select="*[local-name() = 'DateTo']" />
                                    </DateTimeTo>
                                    <Status>
                                        <xsl:value-of select="*[local-name() = 'Status']" />
                                    </Status>
                                    <EntryList>
                                        <xsl:for-each select="EntryList/Entry/WorkDayList/WorkDay">
                                            <Entry>
                                                <Day>
                                                    <xsl:value-of select="Day" />
                                                </Day>
                                                <HoursWorked>
                                                    <xsl:value-of select="HoursWorked" />
                                                </HoursWorked>
                                            </Entry>
                                        </xsl:for-each>
                                    </EntryList>
                                </timeSheet>
                            </xsl:for-each>
                        </item>
                    </xsl:template>
                </xsl:stylesheet>
            </xsl-transform>
            <set-body template="liquid">
            [
            {%- JSONArrayFor ts in body.item -%}        
            {
                "dateTimeFrom" : "{{ts.timeSheet.DateTimeFrom}}",
                "dateTimeTo" : "{{ts.timeSheet.DateTimeTo}}",
                "periodId" : "{{ts.timeSheet.PeriodId}}",
                "days": [
                        {%- JSONArrayFor wd in ts.timeSheet.EntryList -%}   
                        {
                            "day" : "{{wd.Entry.Day}}",
                            "hoursWorked" : "{{wd.Entry.HoursWorked}}"
                        }
                        {%- endJSONArrayFor -%}
                        ]
            }
            {%- endJSONArrayFor -%}
            ]
            </set-body>
            <set-header name="Content-Type" exists-action="override">
                <value>application/json</value>
            </set-header>
        </outbound>
        <on-error>
            <base />
        </on-error>
    </policies>
    

    【讨论】:

      猜你喜欢
      • 2018-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-30
      • 2021-07-29
      • 2017-01-16
      相关资源
      最近更新 更多