Azure 逻辑应用的架构更新 - 2015 年 8 月 1 日预览版Schema updates for Azure Logic Apps - August 1, 2015 preview

适用于 Azure 逻辑应用的这个架构和 API 版本包含多项关键改进,使逻辑应用更可靠且更易于使用:This schema and API version for Azure Logic Apps includes key improvements that make logic apps more reliable and easier to use:

移到 API 连接Move to API connections

最大的变化是不再需要将 API 应用部署到 Azure 订阅,因此可使用 API。The biggest change is that you no longer have to deploy API Apps into your Azure subscription so that you can use APIs. 以下是可使用 API 的方式:Here are the ways that you can use APIs:

  • 托管 APIManaged APIs
  • 自定义 Web APIYour custom Web APIs

每种方法的处理方式略有不同,因为其管理和托管模型不同。Each way is handled slightly differently because their management and hosting models are different. 此模型的一个优点是不再局限于 Azure 资源组中部署的资源。One advantage of this model is you're no longer constrained to resources that are deployed in your Azure resource group.

托管 APIManaged APIs

Microsoft 代表你管理某些 API,例如 Office 365、Salesforce、Twitter 和 FTP。Microsoft manages some APIs on your behalf, such as Office 365, Salesforce, Twitter, and FTP. 某些托管 API 可以按原样使用(例如必应翻译),但另一些 API 需要进行配置,也称为连接。You can use some managed APIs as-is, such as Bing Translate, while others require configuration, also called a connection.

例如,在使用 Office 365 时,必须创建包括 Office 365 登录令牌的连接。For example, when you use Office 365, you must create a connection that includes your Office 365 sign-in token. 令牌以安全方式存储和刷新,以便逻辑应用可以随时调用 Office 365 API。Your token is securely stored and refreshed so that your logic app can always call the Office 365 API. 如果要连接到 SQL 或 FTP 服务器,则必须创建具有连接字符串的连接。If you want to connect to your SQL or FTP server, you must create a connection that has the connection string.

在此定义中,这些操作名为 APIConnectionIn this definition, these actions are called APIConnection. 下面是调用 Office 365 以发送电子邮件的连接的示例:Here is an example of a connection that calls Office 365 to send an email:

{
   "actions": {
      "Send_an_email": {
         "type": "ApiConnection",
         "inputs": {
            "host": {
               "api": {
                  "runtimeUrl": "https://msmanaged-na.azure-apim.cn/apim/office365"
               },
               "connection": {
                  "name": "@parameters('$connections')['shared_office365']['connectionId']"
               }
            },
            "method": "POST",
            "body": {
               "Subject": "Reminder",
               "Body": "Don't forget!",
               "To": "me@contoso.com"
            },
            "path": "/Mail"
         }
      }
   }
}

host 对象是特定于 API 连接的输入的一部分,并包含以下部分:apiconnectionThe host object is a part of the inputs that is unique to API connections, and contains these parts: api and connection. api 对象为承载该托管 API 的位置指定运行时 URL。The api object specifies the runtime URL for where that managed API is hosted. 可以通过调用此方法来查看所有可用的托管 API:You can see all the available managed APIs by calling this method:

GET https://management.azure.cn/subscriptions/<Azure-subscription-ID>/providers/Microsoft.Web/locations/<location>/managedApis?api-version=2015-08-01-preview

使用 API 时,该 API 可以定义也可以不定义任何连接参数。When you use an API, that API might or might not have defined any connection parameters. 因此,如果 API 未定义这些参数,则不需要任何连接。So, if the API doesn't define these parameters, no connection is required. 如果 API 定义了这些参数,则必须创建含有指定名称的连接。If the API does define these parameters, you must create a connection with a specified name.
然后,可以在 host 对象内的 connection 对象中引用该名称。You then reference that name in the connection object inside the host object. 若要在资源组中创建连接,请调用此方法:To create a connection in a resource group, call this method:

PUT https://management.azure.cn/subscriptions/<Azure-subscription-ID>/resourceGroups/<Azure-resource-group-name>/providers/Microsoft.Web/connections/<name>?api-version=2015-08-01-preview

使用以下正文:With the following body:

{
   "properties": {
      "api": {
         "id": "/subscriptions/<Azure-subscription-ID>/providers/Microsoft.Web/managedApis/azureblob"
      },
      "parameterValues": {
         "accountName": "<Azure-storage-account-name-with-different-parameters-for-each-API>"
      }
   },
   "location": "<logic-app-location>"
}

在 Azure 资源管理器模板中部署托管 APIDeploy managed APIs in an Azure Resource Manager template

如果不要求交互式登录,则可通过使用资源管理器模板创建完整应用。When interactive sign-in isn't required, you can create a full app by using a Resource Manager template. 如果要求登录,仍可使用资源管理器模板,但必须通过 Azure 门户来对连接进行授权。If sign-in is required, you can still use a Resource Manager template, but you have to authorize the connections through the Azure portal.

"resources": [ {
   "apiVersion": "2015-08-01-preview",
   "name": "azureblob",
   "type": "Microsoft.Web/connections",
   "location": "[resourceGroup().location]",
   "properties": {
      "api": {
         "id": "[concat(subscription().id,'/providers/Microsoft.Web/locations/chinaeast/managedApis/azureblob')]"
      },
      "parameterValues": {
         "accountName": "[parameters('storageAccountName')]",
         "accessKey": "[parameters('storageAccountKey')]"
      }
    },
},
{
   "type": "Microsoft.Logic/workflows",
   "apiVersion": "2015-08-01-preview",
   "name": "[parameters('logicAppName')]",
   "location": "[resourceGroup().location]",
   "dependsOn": ["[resourceId('Microsoft.Web/connections', 'azureblob')]"],
   "properties": {
      "sku": {
         "name": "[parameters('sku')]",
         "plan": {
            "id": "[concat(resourceGroup().id, '/providers/Microsoft.Web/serverfarms/', parameters('svcPlanName'))]"
         }
      },
      "parameters": {
         "$connections": {
             "value": {
                  "azureblob": {
                     "connectionId": "[concat(resourceGroup().id,'/providers/Microsoft.Web/connections/azureblob')]",
                     "connectionName": "azureblob",
                     "id": "[concat(subscription().id,'/providers/Microsoft.Web/locations/chinaeast/managedApis/azureblob')]"
                  }
             }
         }
      },
      "definition": {
         "$schema": "https://schema.management.azure.com/schemas/2016-06-01/Microsoft.Logic.json",
         "contentVersion": "1.0.0.0",
         "parameters": {
            "type": "Object",
            "$connections": {
               "defaultValue": {},
 
            }
         },
         "triggers": {
            "Recurrence": {
               "type": "Recurrence",
               "recurrence": {
                  "frequency": "Day",
                  "interval": 1
               }
            }
         },
         "actions": {
            "Create_file": {
               "type": "ApiConnection",
               "inputs": {
                  "host": {
                     "api": {
                        "runtimeUrl": "https://logic-apis-chinaeast.azure-apim.cn/apim/azureblob"
                     },
                     "connection": {
                       "name": "@parameters('$connections')['azureblob']['connectionId']"
                     }
                  },
                  "method": "POST",
                  "queries": {
                     "folderPath": "[concat('/', parameters('containerName'))]",
                     "name": "helloworld.txt"
                  },
                  "body": "@decodeDataUri('data:, Hello+world!')",
                  "path": "/datasets/default/files"
               },
               "conditions": []
            }
         },
         "outputs": {}
      }
   }
} ]

在此示例中可以看到,连接只是位于资源组中的资源。You can see in this example that the connections are just resources that live in your resource group. 它们引用订阅中可供你使用的托管 API。They reference the managed APIs available to you in your subscription.

自定义 Web APIYour custom Web APIs

如果使用自己的 API(而不是 Microsoft 托管的 API),则应使用内置 HTTP 操作调用这些 API。If you use your own APIs rather than Microsoft-managed ones, use the built-in HTTP action to call your APIs. 理想情况下,应为 API 提供 Swagger 终结点。Ideally, you should provide a Swagger endpoint for your API. 此终结点可帮助逻辑应用设计器显示 API 的输入和输出。This endpoint helps Logic App Designer show your API's inputs and outputs. 如果没有 Swagger 终结点,则设计器只能将输入和输出显示为不透明的 JSON 对象。Without a Swagger endpoint, the designer can only show the inputs and outputs as opaque JSON objects.

下面是演示新 metadata.apiDefinitionUrl 属性的示例:Here is an example showing the new metadata.apiDefinitionUrl property:

"actions": {
   "mycustomAPI": {
      "type": "Http",
      "metadata": {
         "apiDefinitionUrl": "https://mysite.chinacloudsites.cn/api/apidef/"  
      },
      "inputs": {
         "uri": "https://mysite.chinacloudsites.cn/api/getsomedata",
         "method": "GET"
      }
   }
}

如果将 Web API 托管在 Azure 应用服务中,则 Web API 会自动显示在设计器中提供的操作列表中。If you host your Web API on Azure App Service, your Web API automatically appears in the list of actions available in the designer. 如果未自动显示,则必须直接粘贴在 URL 中。If not, you have to paste in the URL directly. Swagger 终结点必须未经身份验证才能在逻辑应用设计器中使用(不过可以使用 Swagger 中支持的任何方法保护 API 本身)。The Swagger endpoint must be unauthenticated to be usable in the Logic App Designer, although you can secure the API itself with whatever methods that Swagger supports.

使用 2015-08-01-preview 调用已部署的 API 应用Call deployed API apps with 2015-08-01-preview

如果以前部署了 API 应用,则可以通过 HTTP 操作调用该应用。If you previously deployed an API App, you can call that app with the HTTP action. 例如,如果使用 Dropbox 列出文件,则 2014-12-01-preview 架构版本定义可能具有与下面类似的内容:For example, if you use Dropbox to list files, your 2014-12-01-preview schema version definition might have something like:

"definition": {
   "$schema": "https://schema.management.azure.com/schemas/2016-06-01/Microsoft.Logic.json",
   "contentVersion": "1.0.0.0",
   "parameters": {
      "/subscriptions/<Azure-subscription-ID>/resourcegroups/avdemo/providers/Microsoft.AppService/apiapps/dropboxconnector/token": {
         "defaultValue": "eyJ0eX...wCn90",
         "type": "String",
         "metadata": {
            "token": {
               "name": "/subscriptions/<Azure-subscription-ID>/resourcegroups/avdemo/providers/Microsoft.AppService/apiapps/dropboxconnector/token"
            }
         }
      }
    },
    "actions": {
       "dropboxconnector": {
          "type": "ApiApp",
          "inputs": {
             "apiVersion": "2015-01-14",
             "host": {
                "id": "/subscriptions/<Azure-subscription-ID>/resourcegroups/avdemo/providers/Microsoft.AppService/apiapps/dropboxconnector",
                "gateway": "https://avdemo.azurewebsites.net"
             },
             "operation": "ListFiles",
             "parameters": {
                "FolderPath": "/myfolder"
             },
             "authentication": {
                "type": "Raw",
                "scheme": "Zumo",
                "parameter": "@parameters('/subscriptions/<Azure-subscription-ID>/resourcegroups/avdemo/providers/Microsoft.AppService/apiapps/dropboxconnector/token')"
             }
          }
       }
    }
}

现在,可生成类似的 HTTP 操作并让逻辑应用定义的 parameters 部分保持不变,例如:Now, you can now build a similar HTTP action and leave the logic app definition's parameters section unchanged, for example:

"actions": {
   "dropboxconnector": {
      "type": "Http",
      "metadata": {
         "apiDefinitionUrl": "https://avdemo.chinacloudsites.cn/api/service/apidef/dropboxconnector/?api-version=2015-01-14&format=swagger-2.0-standard"  
      },
      "inputs": {
         "uri": "https://avdemo.chinacloudsites.cn/api/service/invoke/dropboxconnector/ListFiles?api-version=2015-01-14",
         "method": "POST",
         "body": {
            "FolderPath": "/myfolder"
         },
         "authentication": {
            "type": "Raw",
            "scheme": "Zumo",
            "parameter": "@parameters('/subscriptions/<Azure-subscription-ID>/resourcegroups/avdemo/providers/Microsoft.AppService/apiapps/dropboxconnector/token')"
         }
      }
   }
}

逐个演练这些属性:Walking through these properties one-by-one:

操作属性Action property 说明Description
type Http 而不是 APIappHttp instead of APIapp
metadata.apiDefinitionUrl 若要在逻辑应用设计器中使用此操作,请包括元数据终结点,该终结点是通过以下方式构造的:{api app host.gateway}/api/service/apidef/{last segment of the api app host.id}/?api-version=2015-01-14&format=swagger-2.0-standardTo use this action in the Logic App Designer, include the metadata endpoint, which is constructed from: {api app host.gateway}/api/service/apidef/{last segment of the api app host.id}/?api-version=2015-01-14&format=swagger-2.0-standard
inputs.uri 构造方式:{api app host.gateway}/api/service/invoke/{last segment of the api app host.id}/{api app operation}?api-version=2015-01-14Constructed from: {api app host.gateway}/api/service/invoke/{last segment of the api app host.id}/{api app operation}?api-version=2015-01-14
inputs.method 始终是 POSTAlways POST
inputs.body 与 API 应用参数相同Same as the API App parameters
inputs.authentication 与 API 应用身份验证相同Same as the API App authentication

此方法应适用于所有 API 应用操作。This approach should work for all API App actions. 但是请记住,以前的这些 API 应用不再受支持。However, remember that these previous API Apps are no longer supported. 因此,应移到以前的其他两个选项(托管 API 或托管自定义 Web API)之一。So you should move to one of the two other previous options, a managed API or hosting your custom Web API.

已将“repeat”重命名为“foreach”Renamed 'repeat' to 'foreach'

对于以前的架构版本,很多客户反馈说,“Repeat”操作名称让人困惑,并且没有正确地表达“Repeat”实际上是一个 for-each 循环。For the previous schema version, we received much customer feedback that the Repeat action name was confusing and didn't properly capture that Repeat was really a for-each loop. 因此,我们将 repeat 重命名为 foreachSo, we renamed repeat to foreach. 以前,你会如下例所示编写此操作:Previously you'd write this action like this example:

"actions": {
   "pingBing": {
      "type": "Http",
      "repeat": "@range(0,2)",
      "inputs": {
         "method": "GET",
         "uri": "https://www.bing.com/search?q=@{repeatItem()}"
      }
   }
}

现在,需改为这样编写:Now you'd write this version instead:

"actions": {
   "pingBing": {
      "type": "Http",
      "foreach": "@range(0,2)",
      "inputs": {
         "method": "GET",
         "uri": "https://www.bing.com/search?q=@{item()}"
      }
   }
}

此外,repeatItem() 函数现已重命名为 item(),该函数引用当前迭代期间循环处理的项。Also, the repeatItem() function, which referenced the item that the loop is processing during the current iteration, is now renamed item().

引用“foreach”的输出Reference outputs from 'foreach'

为简化操作,不再将 foreach 操作的输出包装在名为 repeatItems 的对象中。For simplification, the outputs from foreach actions are no longer wrapped in an object named repeatItems. 此外,由于进行了这些更改,删除了 repeatItem()repeatBody()repeatOutputs() 函数。Also, with these changes, the repeatItem(), repeatBody(), and repeatOutputs() functions are removed.

因此,使用之前的 repeat 示例,将获取这些输出:So, using the previous repeat example, you get these outputs:

"repeatItems": [ {
   "name": "pingBing",
   "inputs": {
      "uri": "https://www.bing.com/search?q=0",
      "method": "GET"
   },
   "outputs": {
      "headers": { },
      "body": "<!DOCTYPE html><html lang=\"en\" xml:lang=\"en\" xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:Web=\"https://schemas.live.com/Web/\">...</html>"
   },
   "status": "Succeeded"
} ]

现在,则会收到这些输出:Now you get these outputs instead:

[ {
   "name": "pingBing",
      "inputs": {
         "uri": "https://www.bing.com/search?q=0",
         "method": "GET"
      },
      "outputs": {
         "headers": { },
         "body": "<!DOCTYPE html><html lang=\"en\" xml:lang=\"en\" xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:Web=\"https://schemas.live.com/Web/\">...</html>"
      },
      "status": "Succeeded"
} ]

以前,引用这些输出时,若要从操作获取 body,需要:Previously, to get the body from the action when referencing these outputs:

"actions": {
   "secondAction": {
      "type": "Http",
      "repeat": "@outputs('pingBing').repeatItems",
      "inputs": {
         "method": "POST",
         "uri": "https://www.example.com",
         "body": "@repeatItem().outputs.body"
      }
   }
}

现在可改用此版本:Now you can use this version instead:

"actions": {
   "secondAction": {
      "type": "Http",
      "foreach": "@outputs('pingBing')",
      "inputs": {
         "method": "POST",
         "uri": "https://www.example.com",
         "body": "@item().outputs.body"
      }
   }
}

本机 HTTP 侦听器Native HTTP listener

HTTP 侦听器功能现为内置功能,因此不需要部署 HTTP 侦听器 API 应用。HTTP listener features are now built-in, so you don't have to deploy an HTTP Listener API App. 有关详细信息,请了解如何使逻辑应用终结点可调用For more information, learn how to make your logic app endpoint callable.

由于这些更改,逻辑应用将 @accessKeys() 函数替换为 @listCallbackURL() 函数,后者可在必要时获取终结点。With these changes, Logic Apps replaces the @accessKeys() function with the @listCallbackURL() function, which gets the endpoint when necessary. 此外,现在必须在逻辑应用中定义至少一个触发器。Also, you now must define at least one trigger in your logic app. 如果要对工作流执行 /run 操作,则必须使用以下触发器类型之一:ManualApiConnectionWebhookHttpWebhookIf you want to /run the workflow, you have to use one of these trigger types: Manual, ApiConnectionWebhook, or HttpWebhook

调用子工作流Call child workflows

以前,调用子工作流需要转到该工作流,获取访问令牌,然后将令牌粘贴到要调用该子工作流的逻辑应用定义中。Previously, calling child workflows required going to the workflow, getting the access token, and pasting the token in the logic app definition where you want to call that child workflow. 借助此架构,逻辑应用引擎会在运行时自动为子工作流生成 SAS,因此不必将任何机密粘贴到定义中。With this schema, the Logic Apps engine automatically generates a SAS at runtime for the child workflow so you don't have to paste any secrets into the definition. 以下是示例:Here is an example:

"myNestedWorkflow": {
   "type": "Workflow",
   "inputs": {
      "host": {
         "id": "/subscriptions/<Azure-subscription-ID>/resourceGroups/<Azure-resource-group-name>/providers/Microsoft.Logic/myWorkflow001",
         "triggerName": "myEndpointTrigger"
      },
      "queries": {
         "extrafield": "specialValue"
      },
      "headers": {
         "x-ms-date": "@utcnow()",
         "Content-type": "application/json"
      },
      "body": {
         "contentFieldOne": "value100",
         "anotherField": 10.001
      }
   },
   "conditions": []
}

此外,子工作流会获取对传入请求的完全访问权限。Also, child workflows get full access to the incoming request. 因此,可在 queries 部分以及在 headers 对象中传递参数。So, you can pass parameters in the queries section and in the headers object. 还可完全定义整个 body 部分。You can also fully define the entire body section.

最终,子工作流会拥有这些所需的更改。Finally, child workflows have these required changes. 尽管之前可以直接调用子工作流,但现在必须在工作流中为要调用的父级定义触发器终结点。While you could previously and directly call a child workflow, you must now define a trigger endpoint in the workflow for the parent to call. 通常,会添加类型为 Manual 的触发器,并在父定义中使用该触发器。Generally, you would add a trigger that has Manual type, and then use that trigger in the parent definition. host 属性明确具有 triggerName,因为必须始终指定要调用的触发器。The host property specifically has a triggerName because you must always specify the trigger you're calling.

其他更改Other changes

新“queries”属性New 'queries' property

所有操作类型现在都支持名为 queries 的新输入。All action types now support a new input called queries. 此输入可以是一个结构化对象,而不必手动组合字符串。This input can be a structured object, rather than you having to assemble the string by hand.

已将“parse()”函数重命名为“json()”Renamed 'parse()' function to 'json()'

parse() 函数现已针对未来的内容类型重命名为 json() 函数。The parse() function is now renamed the json() function for future content types.

企业集成 APIEnterprise Integration APIs

此架构尚不支持企业集成 API 的托管版本,例如 AS2。This schema doesn't yet support managed versions for Enterprise Integration APIs, such as AS2. 但是,可以通过 HTTP 操作使用现有的已部署 BizTalk API。However, you can use existing deployed BizTalk APIs through the HTTP action. 有关详细信息,请参阅集成路线图中的“使用已部署的 API 应用”。For more information, see "Using your already deployed API apps" in the integration roadmap.