开始对 Office 365 网站使用 Azure WebJob

借助 Office 365,如果运行并利用的是 SharePoint Online 服务,必须重新思考如何运行传统场解决方案中的计时器作业

在传统的 SharePoint 开发中,使用计时器作业在 SharePoint 场中执行计划任务。 常用的技术是开发自定义计时器作业,以便在你的环境中持续或反复执行某些任务。 使用 Office 365 和 SharePoint Online,你没有部署服务器场解决方案的优势,而传统计时器作业通常是优势所在。 相反,你需要查找另一种方法来计划任务,借此引入了 Azure WebJob

本文介绍开始为 Office 365 网站构建自定义作业的基本概念,以及如何构建 Azure WebJob 来作为 Office 365(或本地)SharePoint 安装的计划作业。

使用 Visual Studio 构建 WebJob

若要构建新的 WebJob,只需创建新的控制台应用程序,并确保向项目中添加所需的程序集即可。 在此示例中,我们使用 Visual Studio

步骤 1:创建控制台应用程序

首先,新建一个项目,务必要选择“控制台应用”模板。 此外,请确保选择 .NET Framework 4.5 或更高版本。

在“新建项目”对话框中设置为使用 .NET Framework 4.5 创建控制台应用

步骤 2:从 NuGet 添加 SharePoint 特定程序集

如果你使用的是 Visual Studio,NuGet 包管理器对话框的外观可能会略微不同于较早版本的 Visual Studio,但概念是相同的。

  1. 转到“工具”>“NuGet 包管理器”>“管理解决方案的 NuGet 包”,然后搜索“SharePoint 相关应用程序”

  2. 安装名为 AppForSharePointOnlineWebToolkit 的包。

  3. 该工具包安装用于处理 SharePoint 客户端对象模型 (CSOM) 所需的帮助程序类。

显示搜索词“App for SharePoint”的“NuGet 包管理器”对话框。突出显示了“SharePoint Web 工具包应用程序”,并准备好单击“安装”按钮。


通过确保控制台应用程序项目中显示以下两个新类来确保 NuGet 包正常运行:

  • SharePointContext.cs
  • TokenHelper.cs

解决方案资源管理器显示新添加的类、Share Point 上下文和标记帮助。

步骤 3:添加在 Office 365 网站上执行作业所需的代码

此时,已经创建好了控制台应用程序,而且已经添加所需的程序集,这样便能轻松地与 SharePoint 进行通信了。 接下来的步骤是利用这些帮助程序类,以便通过控制台应用程序在 SharePoint 环境中执行命令。

注意

在完成的示例中,使用帐户 + 密码的方法(如服务帐户)。 本文后面将讨论身份验证选项。

连接对 SharePoint Online 网站集的调用

既然已经从 NuGet 包添加了帮助程序类,以下代码将演示如何连接对你的网站的调用。

 static void Main(string[] args)
  {
      using (ClientContext context = new ClientContext("https://redacted.sharepoint.com"))
      {
	      // Use default authentication mode
          context.AuthenticationMode = ClientAuthenticationMode.Default;
          // Specify the credentials for the account that will execute the request
          context.Credentials = new SharePointOnlineCredentials(GetSPOAccountName(), GetSPOSecureStringPassword());

          // TODO: Add your logic here!
      }
  }
 
 
  private static SecureString GetSPOSecureStringPassword()
  {
      try
      {
          Console.WriteLine(" - > Entered GetSPOSecureStringPassword()");
          var secureString = new SecureString();
          foreach (char c in ConfigurationManager.AppSettings["SPOPassword"])
          {
              secureString.AppendChar(c);
          }
          Console.WriteLine(" - > Constructed the secure password");
 
          return secureString;
      }
      catch
      {
          throw;
      }
  }
 
  private static string GetSPOAccountName()
  {
      try
      {
          Console.WriteLine(" - > Entered GetSPOAccountName()");
          return ConfigurationManager.AppSettings["SPOAccount"];
      }
      catch
      {
          throw;
      }
   }

在示例应用程序中可以看到,已经添加了两个帮助程序方法,用于从 app.config 文件获取帐户名和帐户密码。 这些内容在本文后面的身份验证部分进行了解释。

主要方法而言,这就是将内容连接到门户所需的一切。 在深入探讨如何从代码操作 SharePoint 之前,让我们先讨论一下用于身份验证的选项。

考虑身份验证选项

有两个身份验证选项。 以下部分介绍这些常用的方法以及它们之间的差异。

选项 1:使用服务帐户(用户名 + 密码)

这种方法非常简单明了,只需向 Office 365 租户输入帐户和密码即可使用 CSOM 等在网站上执行代码。 这是在前面的示例代码中所完成的操作。

在 Office 365 中创建新的服务帐户

为此,应创建一个作为服务帐户的特定帐户,用于此特定应用程序或你的所有作业和服务可以使用的通用服务应用程序帐户。

为了此演示,我们已经创建了一个名为“SP WebJob”的新帐户:

仪表板显示新创建的 SP WebJob 帐户。

根据作业应具有的权限,在设置帐户时,必须编辑帐户的权限。

将凭据存储在 app.config 中

可以在项目的 app.config 文件中指定凭据,以便从可执行代码中轻松提取这些凭证。 app.config 如下所示:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
 <startup> 
   <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
 </startup>
 <appSettings>
   <add key="SPOAccount" value="spwebjob@redacted.onmicrosoft.com"/>
   <add key="SPOPassword" value="redacted"/>
 </appSettings>
</configuration>

可以在 app.config 文件中看到以下两项设置:

  • SPOAccount
  • SPOPassword

倘若查看第一个代码片段,则这些设置来自 app.config 文件。 请记住,这意味着帐户名称和密码以明文形式存储在 app.config 中。你需要在自己的项目中确定存储密码的方式和位置并对其进行保护,你应选择这种方法。

在指定帐户下运行作业

在应用程序运行后,它将使用在 SharePointOnlineCredentials() 构造函数中指定的帐户运行。

自动翻译日志显示归属于 SP WebJob 的四个文本翻译。

在上述示例中,WebJob 在对 SharePoint Online 网站集托管的一个网站中的自定义列表执行操作。

因此,可以在由服务帐户执行的门户中很好地跟踪更改。 这就是合理命名帐户为何重要的原因;仅需查看修改/创建的元数据,所有人就会知道由服务自动完成的修改。

选项 2:使用 OAuth 并将身份验证令牌包含在请求中,以避免指定帐户/密码

Kirk Evans 发布的名为将 SharePoint 外接程序构建为计时器作业的文章中,他介绍了如何利用和传递访问令牌来避免用户名/密码设置,以防你不想将密码和凭据存储在应用程序中。

使用 CSOM 扩展代码

此时,你已经有了可用的控制台应用程序,它可以验证和执行对 Office 365 网站的请求。 代码中尚未完成什么特别的操作,因此这里有一个示例片段,用于从名为“自动翻译”的列表中提取一些信息。 代码逻辑确定列表中是否有任何项目尚未翻译。 然后执行对翻译服务的调用,并将文本翻译为所需的输出语言。

static void Main(string[] args)
{
   try
   {
      Console.WriteLine("Initiating Main()");

      using (ClientContext context = new ClientContext("https://redacted.sharepoint.com"))
      {
         Console.WriteLine("New ClientContext('https://redacted.sharepoint.com') opened. ");

         context.AuthenticationMode = ClientAuthenticationMode.Default;
         context.Credentials = new SharePointOnlineCredentials(GetSPOAccountName(), GetSPOSecureStringPassword());

         Console.WriteLine("Authentication Mode and Credentials configured");

         List translationlist = context.Web.Lists.GetByTitle("Automatic Translations");
         context.Load(translationlist);
         context.ExecuteQuery();

         Console.WriteLine("TranslationList fetched, loaded and ExecuteQuery'ed");

         if (translationlist != null && translationlist.ItemCount > 0)
         {
             Console.WriteLine("The list exist, let's do some magic");

             CamlQuery camlQuery = new CamlQuery();
             camlQuery.ViewXml =
             @"<View>  
             <Query> 
                 <Where><Eq><FieldRef Name='IsTranslated' /><Value Type='Boolean'>0</Value></Eq></Where> 
             </Query> 
         </View>";

             ListItemCollection listItems = translationlist.GetItems(camlQuery);
             context.Load(listItems);
             context.ExecuteQuery();

             Console.WriteLine("Query for listItems executed.");

             foreach (ListItem item in listItems)
             {
                 item["Output"] = TranslatorHelper.GetTranslation(item["Title"], item["Target Language"], item["Original Language"]);
                 item["IsTranslated"] = true;
                 item.Update();
             }


             context.ExecuteQuery();
             Console.WriteLine("Updated all the list items you found. Carry on...");
         }
      }
   }
   catch (Exception ex)
   {
       Console.WriteLine("ERROR: " + ex.Message);
       Console.WriteLine("ERROR: " + ex.Source);
       Console.WriteLine("ERROR: " + ex.StackTrace);
       Console.WriteLine("ERROR: " + ex.InnerException);
   }
}

TranslatorHelper 类是调用自定义翻译 API 的帮助程序类,但本文不会对此进行详细阐述,因为它超出了本文的范围。

注意

通过代码可以看到,这是一个演示,绝对不会用于生产。 请根据编码标准和安全准则对其进行修改和调整。 不过,为了便于在 Azure 门户中轻松查看作业的执行情况,所有 Console.WriteLine 添加内容均已添加。 有关日志记录和监视的详细信息,请参阅本文后部分内容。

将 WebJob 发布到 Azure

在开发 WebJob 后并且准备将其部署到 Azure 环境(部署到 Azure 网站)时,你有两个主要选项,如以下部分所述。

选项 1:将具有 WebJob 二进制文件的 zip 文件上载到 Azure 门户

使用可以在其中保留 Azure 中的所有优势的 Azure 门户,可以上载包含来自 Visual Studio 生成的输出的 zip 文件。 这是给将为你执行部署的其他人编译和传送代码的一种简便方法。

创建 zip 文件

只需从你的 Visual Studio 生成中获取所有输出文件(通常在 bin/Debug 或 bin/Release 文件夹中)。

显示 bin/Debug 文件夹的 Windows 资源管理器视图。


对其进行压缩以便获得出色的 WebJob zip 文件。

显示已完成的 .zip 文件的 Windows 资源管理器视图。

查找应在其上部署作业的网站

  1. 鉴于已获得包,下一步是转到 Azure 门户并登录。

  2. 必须从中创建新网站或使用现有网站。 此网站是 WebJob 的主机。

  3. 如果在网站的设置窗格中向下滚动,你将在“操作”标题下找到一个名为“WebJobs”的磁贴。

    显示作者的 Azure 门户,并带有指向“WebJob”的箭头。

  4. 单击箭头指向的区域。

上载 WebJob

  1. 通过选择[+ 添加]符号上载 WebJob。

    显示 WebJob Azure 门户,并带有指向“添加”的箭头。

  2. 选择一个名称和作业应运行的方式,然后上载实际 zip 文件:

    系统显示“添加 Web 作业”。“名称”字段包含文本“Zimmergren-O365-WebJobSample”,“如何运行”字段包含文本“按需”。

    重要

    “如何运行”备选项当前仅提供“按需”或“连续”,但不久还将支持“已计划”,这才是你真正想要的。 在“直接发布到 Azure”部分,可以从 Visual Studio 内部对其进行安排。

  3. 现在可以从 Azure 门户运行 Webjob 了。

    WebJobs Azure 门户与新的作业列表一起显示。作业上方会显示一个上下文菜单,其中包含“运行”和“删除”选项。

选项 2:从 Visual Studio 直接发布到 Azure

可以使用 Visual Studio 中的工具来快速将任意更改直接发布到托管服务。 还可以按照自己的方式计划作业直接从 Visual Studio 中的对话框执行。

从 Visual Studio 发布 WebJob

注意

如果运行的是旧版 Visual Studio,这些对话框可能会略有不同。 此外,如果是首次这样做,可能会看到用于登录 Azure 帐户的登录对话框。

右键单击项目,然后选择“发布为 Azure WebJob”

显示解决方案资源管理器上下文菜单,并突出显示“发布为 Azure WebJob 选项”。

添加 Azure WebJob

这将使你进入新的对话框,可在其中配置作业。 由于需要应按计划执行的定期作业(比如每晚一次),因此可直接从对话框配置计划。

系统显示“添加 Azure Web 作业”对话框。“WebJob 名称”字段包含文本 Zimmergren-O365-WebJobSample,“WebJob 运行模型”字段包含选项“按计划运行”,“重复周期”字段包含选项“重复周期作业”且复选框“无结束日期”处于选中状态,“重复间隔”字段设置为 1 天,而开始日期设置为 2015 年 1 月 9 日。

  1. 确保 WebJob 名称是 Web 友好型。

  2. 选择你的 WebJob 运行模式。 如果想要在每天的特定时间发生,请选择“按计划运行”

  3. 作业应为定期作业还是一次性作业? 因为想要模拟一个计时器作业,它需要重复执行,而且如果此作业将于每晚运行,则没有任何结束日期。

  4. 可以根据需要将重复周期细化至每分钟一次。

  5. 指示起始日期时间,以及时区

  6. 选择“确定”。 Visual Studio 发送以下消息:安装 WebJob 发布 NuGet 包

    显示“WebJob NuGet 包安装”对话框(显示微调框和文本,安装 WebJob 发布 NuGet 包)。

    这实际上会将一个名为“webjob-publish-settings.json”的新文件添加到你的项目,其中包含作业的配置。

    文件如下所示:

     {
     "$schema": "http://schemastore.org/schemas/json/webjob-publish-settings.json",
     "webJobName": "Zimmergren-O365-WebJobSample",
     "startTime": "2015-01-09T01:00:00+01:00",
     "endTime": null,
     "jobRecurrenceFrequency": "Day",
     "interval": 1,
     "runMode": "Scheduled"
     }
    

    注意

    目前你不需要该文件,因为已经使用对话框设计了计划。

选择发布/部署目标

对话框中的下一步指示在何处发布/部署你的 WebJob。 可以导入发布配置文件,也可以选择 Azure 网站,以便验证并选择一个现有的网站。

在 Azure 门户中选择“导入”并指定从 Azure 网站下载的发布配置文件。

显示具有可见的“连接”选项卡的“发布 Web”对话框。

发布

完成此操作后,只需选择“发布”即可。 “Web 发布活动”对话框然后会显示 WebJob 部署的进度。

显示“Web 发布活动”对话框。


完成后,应该会在 Azure 门户中看到 WebJob。

Azure 门户在 WebJob 列表中显示“Zimmergren-O365-WebJobSample”,它的状态为“2 分钟前完成”。

现在,WebJob 状态显示为“已完成”。 如果它引发任何未处理的异常或者提供不正常的行为,则会提示“失败/错误”

类型还会提示“按需”,但现在此作业实际上每小时运行一次。

监视作业并查看日志

如果已完成上述所有步骤,现在将获得作为计划任务在云中为你工作的作业,从而对你的 Office 365 网站执行操作。

如果你想要查看作业上次运行的时间、每次执行作业产生的结果或作业执行期间发生的情况,可以选择 WebJob 概述中的“日志”下的链接。

WebJob 对话框,并带有指向“日志”链接的箭头。


你将会看到所选作业的所有执行的概况,其中包括状态/结果。

WebJob 详细信息,包括最近运行的作业。


选择突出显示的链接,可以深入了解特定的执行情况,从而检查作业日志,并确保一切正常。 如果作业实际上导致了错误,而且你需要调查发生了什么错误,或者如果该作业的结果不正确或不像预期的那样,这可能更具相关性。

还可以看到,我们在此演示的控制台应用中使用的 Console.WriteLine 语句现在显示在作业执行日志中。

WebJob 详细信息显示日志文件中的行。

另请参阅