标签存档:Azure函数

在Visual Studio代码中构建基于项目的Azure函数

我已经使用了一段时间的Visual Studio代码的Azure函数,它们继续以很好的方式发展。最近的一次换班让我陷入了一个循环,所以我想我会为那些还没有开始的人记录一些。我还应该指出,在过去一年左右的时间里,我一直专注于用JavaScript编写函数,因为我喜欢把事情搞混一点,这也使得与不以.NET为中心的开发人员共享Azure函数更加容易。

我也写过关于在msdn杂志上用vs代码创建Azure函数的文章,但同样,自从我写这篇文章以来,情况就变了。我已经使用版本2的api有一段时间了,所以我不打算讨论(好吧,在这里写)关于从v1到v2的变化,但是使用Azure函数扩展的体验的变化。

另外值得注意的是,Azure功能团队实际上建议使用Visual Studio为JavaScript构建基于C的应用程序和VS代码。但是我经常在我的MacBook上,并且喜欢使用VS代码,所以我无论如何都要用c#沿着这条路走下去。

在对文档进行了足够多次的重新访问后,最终发现了一些关键信息,我意识到,随着与C合作的扩展,体验发生了变化。以前,我曾经使用过C脚本函数(.csx),这与您直接在门户中工作时使用的相同。但是扩展模板现在驱动您使用C项目功能,这有很大的不同。脚本函数更像是javascript函数。它们依赖于手动创建的function.json文件来定义绑定,并可以基于绑定安装适当的扩展包。CSX文件在运行时编译。有了C类库,您可以像开发其他C类库一样进行开发——安装相关的包,然后使用属性将方法标识为Azure函数和触发器,输入和输出绑定。编译库时,Azure函数工具将为您生成一个被部署的function.json文件。

因为我习惯于用javascript或脚本路径创建函数,使用C类库的Azure函数扩展的新默认值确实让我陷入了一个循环。因此,我决定用文档记录在这个工作流程中行走,因为我必须学习它。我想我还是更喜欢重量较轻的C脚本(.csx)或JavaScript流,但这可能与我在许多情况下对vs代码的偏好相一致,而不是Visual Studio。

正在准备Visual Studio代码

所以首先要做的是:您需要安装Azure的功能Azure帐户对vs代码的扩展,Azure函数扩展依赖于Azure函数核心工具。扩展安装说明将帮助您获得所需的所有信息,扩展会检查更新并提示您根据需要更新这些工具。事实上,我昨晚收到这个提示。2019年1月16日\u 09-28-10.png

安装了扩展,现在是时候创建一个函数应用程序项目了。您应该已经创建了一个文件夹来存放您的项目,您也可以用VS代码打开它。我的名字叫AzureFunctionProj。

然后你可以点击“创建新项目”功能栏上的图标(当您将鼠标悬停在功能栏上时,图标会显示出来),以便在文件夹中创建新的功能应用程序项目。

2019-01-17_18-11-39.png

工作流的此部分未更改。

  1. 它将要求您指向一个文件夹,打开的文件夹应该作为默认选择。
  2. 然后它会让你选择一种你将在应用程序中使用的语言。从选项(c,JavaScriptPython(仍然是预览版)和Java(也是预览版),我会选择C。

因此,将使用模板创建新的.NET核心项目,您将在文件夹资源管理器中看到以下内容:

2019-01-17_18-19-58.png

azurefunctionproj文件夹中的所有这些文件都是由模板创建的。最重要的是csproj文件,其中我突出显示了一些最相关的设置。

         
          
           
            NETCOREAPP2.1
           
           
            
             V2
            
          
          
           
            
          
          
           
            
             PreserveNewest
            
           
           
            
             PreserveNewest
            
            
             从来没有
            
           
          
         

在函数应用程序中创建一个函数,事情就大不一样了。

像往常一样,以"add a function"开头图标2019 - 01 - 17 - _18 - 11 - 39 copy.png

第一步很熟悉,选择功能应位于哪个文件夹中的功能应用程序:

2019-01-17_22-06-37.png

我会选择azurefunctionproj。

然后有许多触发器模板可供选择,下面的三个选项更有趣:

2019-01-17_16-42-25.png首先是项目运行时,我肯定想要v2(“~2”)。您可以在功能应用程序中为不同的功能使用不同的语言。这显示了我已经选择的默认值:c。最后,触发器模板列表过滤为“已验证”。

您可以通过单击这些选项来更改它们。

过滤器选项已验证,核心和所有。核心和所有当前显示相同的列表,其中包括一些额外的预览触发器:DurableFunctionsOrchestration,森德格尔事件hubtrigger和iothubtrigger。

2019-01-17_16-43-20.png

过去我在.NET核心功能应用程序中创建了javascript函数,但现在我将继续使用C,因为这正是我真正感到惊讶的地方。我将选择HttpTrigger,然后提示我提供一个名称。我只留下默认值:httptriggercsharp。然后要求我为将要创建的类提供一个名称空间名称。默认设置是“Company.Project”。我将它更改为FunctionTests.HttpTest1。要收集的最后一点信息是,您需要为函数选择安全性。选项中,我将选择匿名,因为它是一个演示,我不想处理凭证。

就是这样。将创建函数。

更多的类库项目差异

我过去的经验让我期望在app function文件夹中创建一个新文件夹,其中包含函数名和函数名,将是函数的类文件和包含绑定配置的function.json文件。类文件在那里(虽然不在它自己的文件夹中)。但是没有function.json文件。对我来说,运行方法上的FunctionName属性和运行方法签名中的HttpRequest上的HttpTrigger属性也是有趣的和新的。也,我不习惯在使用CSX脚本时使用所有这些using语句。2019年1月19日\u 15-16-45.png

在建设项目时,.NET核心读取该属性并构建一个进入bin文件夹进行部署的function.json。2019 - 01 - 17 - _22 - 38 - 03. png

但它不仅仅是熟悉的绑定。注意生成者,配置源,脚本文件和入口点标记。

所以第一次装订,httpTrigger绑定,我看起来很熟悉。该函数将响应httpTrigger。

您可以通过运行或调试来测试这个默认值。运行,您可以使用vs code的ctrl-f5键盘组合键,或者,如果您喜欢使用CLI,使用azure函数cli命令:

主机启动

这将运行该函数并提供一个URL来尝试。模板“桩在地上”方法的编写目的是接受主体中的查询参数或JSON。我将使用一个查询参数:

http://localhost:7071/api/httptriggercsharp?名字=朱莉

以及浏览器输出

2019-01-19_15-57-04.png

将输出绑定添加到
Azure宇宙DB

如果我想添加一个输出绑定呢?我习惯于通过编辑function.json来实现这一点。但是由于我在属性定义绑定的路径上,我会这样添加绑定。让我们为AzureCosmosDB添加一个输出绑定。这样,该函数将响应HTTP请求,并将一些数据插入到cosmos-db数据库中。我已经有了一个Azure Cosmos数据库帐户,因此,我将定义它来针对现有帐户中的新数据库中的新集合。

为了使用与Azure Cosmos DB绑定的工作,我需要将相关包添加到我的项目中。因为我正在使用C类库构建我的函数,我可以像对任何其他nuget包那样这样做…直接将其添加到csproj或使用dotnet core cli添加包:

但是现在我只是编写一个C类库,这样我就可以使用dotnet cli添加包,或者手动将它添加到.csproj中。我会使用CLI:

dotnet添加包microsoft.azure.webjobs.extensions.cosmossdb--版本3.0.3

注意,如果我使用javascript或c脚本构建函数,我需要使用工具cli(func extensions install-p)注册包packagename)。

现在这个包在csproj中:

          
           
            
           
          
恢复后,我可以添加输出绑定。当前默认函数是异步的,不能向异步方法添加参数。返回值是一个选项。见 https://docs.microsoft.com/en-us/azure/azure函数/函数使用函数返回值触发绑定获取详细信息。ICollector或IAsyncCollector是另一个( https://docs.microsoft.com/en-us/azure/azure-functions/functions-dotnet-class-library#writing-multiple-output-values)。
但我要只是使run方法同步,并创建一个输出参数。像触发器绑定参数一样,我需要向输出参数添加一个属性来指定绑定。我还提供数据库和集合名称的参数,具有到数据库帐户的连接字符串的设置的名称,以及最后一个确保在需要时创建数据库和集合的设置。
[函数名(“httpTriggerCSharp”)]public static actionResult run([httpTrigger(authorizationLevel.anonymous,“得到”,“邮政”route=null)]httprequest req,[COSMOSSDB(数据库名称:“CSharpDatabase”,collectionname:“CSharpcollection”,connectionStringsetting=“mycosmosdbconnection”,CreateIfNotExists=true)] out dynamic document,ILOGER日志
我添加了mycosmosdbconnection,它是在local.settings.json文件中定义的:
“IsEncrypted”:假,“values”:“azurewebjobsstorage”:“”,“functions_worker_runtime”:“dotnet”,“mycosmosdbconnection”:“这是连接字符串的位置“}
请注意,如果使用一个Azure Cosmos DB触发器创建一个新函数,工具将提示您获取所有相关的数据库信息,在函数代码中包含一个属性,并将其添加到function.json中。
现在只有最后一个拼图。函数期望我为文档变量提供一个值,然后绑定将该值插入到数据库中。下面是完整的类清单,其中用红色突出显示了用名称和添加属性填充文档的一行。函数和绑定将完成剩下的所有工作。
使用系统;使用Microsoft.aspnetcore.mvc;使用Microsoft.Azure.WebJobs;使用microsoft.azure.webjobs.extensions.http;使用Microsoft.aspnetcore.http;使用Microsoft.Extensions.Logging;命名空间函数tests.httptest1公共静态类httptriggercsharp[函数名(“httptriggercsharp”)]公共静态操作结果运行([httptrigger(authorizationlevel.anonymous,“得到”,“邮政”route=null)]httprequest req,[COSMOSSDB(数据库名称:“CSharpDatabase”,collectionname:“CSharpcollection”,connectionStringsetting=“mycosmosdbconnection”,CreateIfNotExists=true)] out dynamic document,ilogger log)log.loginformation(“C HTTP触发器函数处理了一个请求”);字符串名称=请求查询[“名称”];document=新建name=名称,添加=datetime.now;返回名称!= NULL?(actionresult)新的OkObjectResult($你好,name”):new badRequestObjectResult(“请在查询字符串上传递名称”);} }
根据我以前手动配置function.json的经验,我以为建好房子后,bin文件夹中包含cosmossdb输出绑定信息的function.json,但没有。再一次,这是由于javascript/c脚本函数和c库函数之间的差异造成的。
在vs代码中,我可以运行或调试函数。调试是F5或调试图标。运行,没有调试,您可以使用ctrl-f5或tools cli命令:
主机启动
使用cli命令时,我在测试中发现我使用的版本似乎需要我运行 清洁网首先是成功。ctrl-f5为您完成这一步。我在一个预先存在的GitHub问题中记录了这一点。你可以读到 在这里.
官方文件中有很多有用的信息。我所倚重的两件事是:

使用门户复制Azure函数应用程序,GitHub和Cloud Shell

我有一个带有一些函数的Azure函数应用程序,这些函数是我为一个会议会话的演示而构建的。我在AngularMix首次使用它,并命名了函数应用程序AngularMix12017。当我上周为dev交集做这个时,我将它重新创建为DevIntersection2017,因为你无法重命名一个功能应用程序。下周我将在另一个会议(netconf.co)上再次这样做,并决定是时候创建一个可重用的名称:dataapidemo。

如果你严格地在门户网站上工作(这就是我在构建功能应用程序的第一个学习阶段的工作方式),你就不能简单地复制一个功能应用程序。通过再次下载和上传,您可以很容易地复制它。

请记住,如果您正在开发Vs2017或Vs代码中的函数(与AzureCLI结合使用),则可以使用工具发布函数应用程序以及设置。但我不喜欢走捷径。走这条路,我学到了很多新的技巧和工具。即使我在下一轮测试中利用了工具,我学到了很多东西,这让我对整体情况有了更好的了解,更多的控制和故障排除技能。

我的第一步是创建新的函数应用程序(dataapidemo)。

Azure功能应用程序的概览blade有一个“下载应用程序内容”选择权。这将把所有相关文件拖到您的机器上。所以下一步,我进入devintersection2017功能应用程序概述,点击下载应用程序内容链接。

下载应用程序内容时,您还可以选择获取应用程序设置。我的设置中存储了许多秘密…比如数据库的密钥,帐户id等。如果你检查一下,设置将下载到本地设置文件。如果您使用此功能在本地继续开发,例如在VS2017中,然后你就会想要它们。但在我看来,它们是没有用的,甚至可能是一个安全问题(您很快就会看到),所以我将不检查它。

我可以看到我电脑上指定文件夹中的文件。

我已经创建了一个Github存储库,将这些文件存储在:https://github.com/julielerman/dataapiazzurefunctions中。

在新文件夹的命令行中,我将初始化,将所有文件添加到本地repo并提交它们。然后我可以运行git命令将该文件夹连接到我的github repo,然后将本地存储库推送到联机存储库中。

完成后,这些文件都在我的Github报告中。

因为我使用的是公共存储库,这就是为什么我不想下载包含我的秘密的local.settings.json文件的原因。当然,我可以在本地删除它,或者告诉Git忽略该文件。关于这方面的其他几点。如果我是在本地开发的,然后我可以在本地使用该文件,并使用VS2017或Azure CLI工具将我的应用程序以及设置发布到门户。但这不是我的目标。

现在,我可以利用Azure门户的一个长期特性:将它连接到一个存储库,以便从存储库自动部署到我的应用程序(在我的函数应用程序中)。

回到入口,我再次选择新的功能应用程序,然后从它的平台功能页面,打开部署选项。选择Setup new deployment,按照以下步骤将函数应用程序连接到存储库。完成设置后,可以使用“同步”按钮强制进行部署。所有文件现在都在我的新dataapidemo函数中,包括包含函数设置的function.json文件(例如集成等)以及我可能添加到函数中的任何其他文件。

因为我用的是斜纹布,我的一个函数在project.json文件中引用了twilio,我需要将这个包恢复到这个函数应用程序中。我通过打开project.json并对其进行一个小的修改来做到这一点……添加或删除一行空白,然后保存它。这会触发包还原。

但是,功能应用程序设置不存在。这些是为应用程序定义并由一个或多个函数使用的设置。有一些由Azure创建的默认设置,但我也有一些其他的…那些秘密,例如,我的twilio集成的帐号和电话号码以及功能键。

其中一些设置是我在新函数中需要的自定义设置。我可以通过门户应用程序设置界面添加它们,但我不喜欢我有一系列设置的路径。

这意味着我们将继续使用另一个在Azure门户网站上令人惊叹的工具——云外壳。您可以在订阅中的服务上直接从Azure CLI运行bash或powershell命令。您也可以在您的机器上本地执行此操作,但需要注意的是,您必须在那里提供凭证和其他元数据。

在门户,打开云壳。这是一个交互式终端窗口。

如果您有多个订阅,您需要确保它设置为存储应用程序功能的位置。

可以通过使用AZ帐户列表命令。

如果你想要的不是默认值,然后设置为:

az帐户集-s[id]

这个外壳可以自动完成,所以如果ID以A123开头,你可以打字

AZ账户集-S A123

然后点击标签,ID就完成了。按回车键,它将成为默认的订阅。

我将使用azure functionapp命令将设置放到我的函数应用程序中。

首先,我将列出现有的设置。你用命令来做这个

az functionapp config appsettings list--名称[功能名称]--资源组[资源名称]

名称和资源组的参数快捷方式为-n和-g。我的都是同一个名字:dataapidemo。下面是命令的样子(除了我的博客强制的换行):

az函数app config appsettings list-n dataapidemo-g dataapidemo

默认情况下,appsettings列为json,尽管您可以使用输出参数影响输出格式.

我需要看到的设置,我想复制从其他功能的应用程序,所以我运行:

az functionapp config appsettings list -n devintersection2017 -g devintersection2017 -o tsv

这给了我要选择的设置列表。

除了列出设置外,您可以使用设置动词和删除方式删除动词。两者都将取代动词列表.

通过将set命令和–settings参数组合使用set。在–settings参数之后,你可以用这种格式列出一个或多个设置:

az函数app config appsettings set-n dataapidemo-g dataapidemo--settings“property1name=value”,“property2name=值”

请注意,这是在博客文章中包装的,而不是在shell窗口中。

所以我添加了一些我想要添加的设置,看起来更像:

az functionapp config appsettings set -n dataapidemo -g dataapidemo——设置“osid =myvalue”,“twilioaccount=myvalue”

还有其他一些我必须补充的。例如,我的函数需要知道如何访问我的cosmos-db文档数据库,所以它有一个设置,使用db name作为属性名,dbs account endpoint作为值。

一旦我做到了,我能够摆脱为每个会议命名的功能应用程序,使用一个通用的应用程序,不管我在哪里共享它。

我学到了很多新东西吗?