2017年5月12日,星期五

从SharePoint Framework Web部件(SPFx)调用Azure函数–第2部分:从SPFx调用并传递数据

在上一篇文章中,我们研究了可以通过SPFx Web部件调用并可以使用PnP核心库的Azure Function的工作。通过CORS设置功能,为PnP提供NuGet支持以及从源代码控制进行部署,我们’现在准备完成代码。作为回顾,我’m将步骤和代码分成以下两篇文章:

第1部分–设置,使用PnP Core,CORS和连续部署(上一篇文章):
  • 最初创建功能
  • 部署功能代码(使用来自GitHub的持续部署)
  • 允许在Azure函数上使用CORS,以便可以从JavaScript调用它(包括SPFx工作台的特殊条目)
  • 使用SharePoint PnP Core库-通过Azure Functions NuGet支持
  • 在Azure函数中使用应用程序设置(环境变量)
第2部分–从SPFx调用并传递数据(本文):
  • Azure函数方面的代码(即,根据一些传递的参数创建现代页面的工作)
  • SPFx端的代码
  • 将数据传递给函数和设置正确的标题
  • 从函数返回数据,并在我们的SPFx Web部件中显示成功/失败

编码– Azure Function side

I’首先讨论几个值得注意的事情,然后显示完整的代码。

收集从客户端传递的数据

We’将假设调用者将请求数据以JSON形式发布到函数中–样板函数代码也这样做,所以我们’re just extending things a little. We can then access the pieces of data through the Content.ReadAsync() method using a C# dynamic variable and plain 目的 type:

// collect site/page details from request body.. 
  dynamic data = await req.Content.ReadAsAsync<object>(); 
  string siteUrl = data.SiteUrl; 
  string pageName = data.PageName; 
  string pageText = data.PageText; 

  log.Info($"Received siteUrl={siteUrl}, pageName={pageName}, pageText={pageText}"); 

如果你想成为“tighter”关于如何将数据传递到服务器,您当然可以使用适当的字段/属性来实现特定的类,并将其指定为.NET的类型。’的ReadAsAsync方法应尝试将请求正文反序列化为(而不是‘object’)。但是,上面的代码只是一种简单的方法,用于收集传递给函数的一些数据–当然,在客户端,我们将确保将具有相同属性的适当的JSON字符串设置为请求的主体(如下所示)。

以正确的方式返回给客户

我们希望我们的端点在这里遵守HTTP约定,如果一切都很好,则返回一个HTTP 200,如果请求不正确,则返回一些适当的4xx错误代码’t有效,依此类推。我们可以使用HttpRequestMessage.CreateResponse()方法来执行此操作。我们可能希望函数传回错误的一个例子是’从SharePoint Framework本地工作台而不是实际网站调用– if we don’没有网站,我们的职能部门如何知道在哪里创建页面?因此,在这种情况下,我发送回HTTP 400(错误请求):

if (siteUrl.Contains("www.contoso.com")) { 
   // N.B. the “www.contoso.com” URL indicates the local workbench in SPFx.. 
  return req.CreateResponse(HttpStatusCode.BadRequest, "Error: please run in the context of a real SharePoint site, not the local workbench. We need this to know which site to create the page in!"); 
} 

..现在,它将以正确的方式显示在浏览器开发工具/ Fiddler /其他监视工具中,依此类推。

Azure函数创建现代页面的完整代码为:

We’很快就会到达SPFx Web部件,但是请注意,Azure门户为您提供了一种在测试之前测试功能的好方法’ve实际上创建了一个呼叫者。您可以对请求正文进行精心设计,使其包含具有函数期望的属性的JSON,然后按“Run”按钮以查看结果。您的函数将执行,并且您拥有的所有日志记录消息都将输出到控制台:

SNAGHTMLb00f684_thumb2

将功能与SPFx Web部件集成

所以让’s创建了一个简单的SPFx Web部件,它调用了我们的Function。我们 ’ll提供一个简单的形式来收集页面名称和默认内容的参数,并提供一个按钮来实际调用该函数并创建页面。我没有’不要在这里做任何幻想–我结束了这个:

SNAGHTML1551102d_thumb2

所以让’朝那个方向前进。首先,我们需要功能’s URL –我们可以从Azure门户获得此信息。找到此链接可以做到这一点:

SNAGHTMLad22f4c_thumb2

Now we need to think about calling our Function from SPFx. You can do this using the HttpClient 目的 of course, but there are some things to know to structure the request correctly in terms of the headers and body content. We also need to collect some information from our form fields, but the important thing when POSTing data in SPFx is the use of the Headers and IHttpClientOptions 目的s in the SharePoint Framework:

const requestHeaders: Headers = new Headers();
requestHeaders.append("Content-type", "application/json");
requestHeaders.append("Cache-Control", "no-cache");

let siteUrl: string = this.context.pageContext.web.absoluteUrl;
let pageName: string = (document.getElementById("txtPageName")).value;
let pageText: string = (document.getElementById("txtPageText")).value;

console.log(`SiteUrl: '${siteUrl}', PageName: '${pageName}.aspx', PageText: '${pageText}'`);

const postOptions: IHttpClientOptions = {
   headers: requestHeaders,
   body: `{ SiteUrl: '${siteUrl}', PageName: '${pageName}.aspx', PageText: '${pageText}' }`
};

..然后我们可以使用这组标题/正文内容(在‘postOptions’ 目的) in a POST request to our Function with the httpClient.post() method:

this.context.httpClient.post(this.functionUrl, HttpClient.configurations.v1, postOptions).then((response: HttpClientResponse) => {
    // code omitted..
}

这里重要的是,通过确保对httpClient.post()的调用同时具有“ onFulfilled”和“ onRejected”处理程序(分别是第一个和第二个参数)来捕获来自服务器的任何不成功的响应。您可以在下面SPFx Web部件的完整代码中看到这一点:

因此,在对服务器端和客户端双方的代码进行排序之后,我们的Web部件现在可以使用PnP方法创建现代页面。由于Azure函数会发回适当的响应,因此它’对于我们而言,很容易在UI中显示成功/失败。

成功:

SNAGHTML15522249_thumb2

失败:

SNAGHTML1553a261_thumb2

假设一切正常,那么当您在当前站点中创建一个新的现代页面’d expect:

SNAGHTML155478cc_thumb2

请注意,如果要重新创建此Web部件,则还需要* .module.scss文件中的某些样式:

概要

此外“timer”在处理和处理Azure BLOB和队列项目的过程中,Azure函数是向客户端应用程序和Web部件添加少量.NET代码的好方法。我们在此处的SharePoint Framework Web部件的上下文中进行了展示,但是任何一种JavaScript都可以调用我们的Function–其中包括移动应用程序,SharePoint Content Editor Web部件,SPFx扩展/自定义项(JSLink / CustomActions等的替代品)等。我们经历了启用CORS的过程,通过project.json文件为NuGet引入了PnP Core组件,设置了源代码控制集成和其他步骤。

生产中可能需要考虑的其他事项包括身份验证。我的例子“函数身份验证+ SharePointOnlineCredentials”,但您可能想改用AAD保护您的功能,并在代码中使用真实的应用程序身份验证。这意味着首先要注册一个AAD应用程序并通过adal.js获取访问令牌,这肯定会更复杂,并且如果您的Web部件可以在多个页面上,则会在“回复URL”周围出现问题。 Vesa和Waldek讨论了一个有趣的替代方法,该替代方法通过IFrame调用Function (带有Cookie),但仅在您的代码可以使用仅应用程序身份验证时才有效。老实说,将来有比这更好的选择会很好。

还考虑到功能正在超越.csx文件而发展,因此,尽管您始终可以从那里引用自己的DLL并以此方式分解代码,但现在也存在使用类库的其他更直接的方法– see 将.NET类库发布为Function App

无论哪种方式,函数都是一个很好的工具,作为开发人员,您’熟悉它们会受益:)

没意见: