短信服务开发概述

上次修改时间: 2010年4月14日

适用范围: SharePoint Foundation 2010

本主题概述如何使用 SharePoint Foundation 软件开发工具包 (SDK) 的手机信息 API 向 Microsoft SharePoint Foundation 开发项目添加手机信息功能。可以将这些 API 有效地分为两个大组:使用 Office 手机信息服务 (OMS) 通信协议支持短信服务 (SMS) 信息(也称为"文本信息")的 API 和可用来为其他通信或信息结构协议构建支持的 API。在大多数开发方案中,信息的发送方是 SharePoint Foundation Web 应用程序而不是特定用户,因此 SharePoint Foundation 部署将需要一个手机信息服务提供商 (MSP) 公司的帐户,以支持您的解决方案所使用的通信协议。

Office 手机信息服务 (OMS) 协议是一个通信 协议,用于实现 SMS 和多媒体信息服务 (MMS) 信息结构 协议。OMS 需要针对 Web 服务访问的 SOAP 协议。下文 OMS-SMS 信息解决方案中讨论的支持 OMS 的 API 专用于 SMS 信息。Microsoft.SharePoint.MobileMessage 命名空间中提供的其名称中包含"MMS"的任何类或成员,或仅在 MMS 信息上下文中起作用的任何类或成员,都仅供内部使用,您的代码不应调用这些类或成员。若要开发不使用 OMS 作为通信协议或针对 MMS 信息使用 OMS 的信息解决方案,请使用下文针对其他协议进行开发中讨论的更抽象级别的 API。

OMS-SMS 信息解决方案

SharePoint Foundation 为您提供了执行所有 OMS Web 方法调用和执行所有 XML 分析和编写的 API。您的代码只需使用熟悉的面向对象的语法来调用这些 API。

为 Web 应用程序创建 MSP 帐户

每个 SharePoint Foundation Web 应用程序(包括管理中心 Web 应用程序)都可以具有 MSP 帐户。通常,这些帐户是由服务器场管理员在管理中心应用程序的应用程序管理部分设置的。但是,您可以通过编程的方式创建帐户,并将其分配给 Web 应用程序。首先,调用不需要 SPMobileMessageServiceProvider 参数的 SPMobileMessagingAccount() 构造函数。然后调用 UpdateSmsAccount(SPMobileMessagingAccount) 方法以将帐户分配给 Web 应用程序。在下面的代码段中,webApp 是对 SPWebApplication 对象的引用。(有关如何获取对此类对象的引用的详细信息,请参阅获取对网站、Web 应用程序和其他关键对象的引用。)该代码段假设文件中具有 Microsoft.SharePointSystem.Security 的 using 语句。请注意,对 UpdateSmsAccount(SPMobileMessagingAccount) 的调用是做为匿名委托的一部分传递给 RunWithElevatedPrivileges(SPSecurity.CodeToRunElevated) 方法的。

SecureString password = new SecureString();
password.AppendChar(‘a’);
password.AppendChar(‘Z’);
password.AppendChar(‘3’);
password.AppendChar(‘&’);

SPMobileMessagingAccount account = new SPMobileMessagingAccount("Contoso Messaging",
                                                                "https://contoso.com/services/mobilemessages",
                                                                 "BobG",
                                                                 password);

SPSecurity.RunWithElevatedPrivileges(delegate() {webApp.UpdateSmsAccount(account);
                                                 webApp.Update();});
Dim password As New SecureString()
        password.AppendChar("a")
        password.AppendChar("z")
        password.AppendChar("3")
        password.AppendChar("&")

        Dim account As New SPMobileMessagingAccount("Contoso Messaging", "https://contoso.com/services/mobilemessages", "BobG", password)


        SPSecurity.RunWithElevatedPrivileges(Sub()
                                                 webApp.UpdateSmsAccount(account)
                                                 webApp.Update()
                                             End Sub)

为 Web 应用程序分配了 MSP 帐户后,您的代码随后即可使用 OutboundSmsServiceAccount 属性作为对该 Web 应用程序帐户对象的引用。

创建 Web 服务对象

分配了 SPMobileMessagingAccount 之后,您的代码即可使用它创建 SPMobileMessageWebService 对象,该对象包含用于发送 SMS 信息的方法。建议您在获取对永久性的 SPMobileMessagingAccount 对象的引用时,始终验证该对象是否非 null,并且它的 IsValidAccount() 属性为 true。下面的代码段演示如何创建 Web 服务对象。webApp 是对 SPWebApplication 对象的引用。

SPMobileMessagingAccount account = webApp.OutboundSmsServiceAccount;
if (account == null || !account.IsValidAccount())
{
    throw new SPException("The account passed in is invalid.");
}
else
{
    SPMobileMessageWebService messagingWebService = new SPMobileMessageWebService(account);
}
Dim account As SPMobileMessagingAccount = webApp.OutboundSmsServiceAccount
If account Is Nothing OrElse (Not account.IsValidAccount()) Then
    Throw New SPException("The account passed in is invalid.")
Else
    Dim messagingWebService As New SPMobileMessageWebService(account)
End If

构建和发送手机信息

接下来的两个重要任务是构建和发送信息。

构建信息

有了 SPMobileMessageWebService 对象,您的代码可以通过将该对象的方法用作代理来调用服务的 OMS Web 方法。当然,其中最重要的是 SendMessage(String) 方法。但是,在调用该方法之前,必须先使用代码构建信息。可以使用 3 个方法来构建信息。

  • 可以使用代码调用静态 BuildSmsMessage(SPMobileMessagingAccount, String, String) 方法,并向其传递有关发件人帐户、收件人和信息正文的参数。该方法最简单,但最灵活。

  • 可以使用代码调用 SetTextContent() 的其中一个重载。这要求您先构造 SPMobileMessageSmsBuilder,并使用 AddRecipient(String) 方法的调用添加收件人,还需要将信息从 SetTextContent() 创建的 SPMobileSmsMessage 对象转换为 OMS 协议的相应的信息 XML。但使用这种信息构建方法可以添加多个收件人,您还可以将子网页数量的限制设置为低于服务提供商强制的限制。如果信息文本超过服务强制的字符限制,信息将被拆分为(ContentParts)。

  • 可以使用代码创建信息构建事务。这种事务包含:

    1. StartTextMessage() 的调用

    2. AddChunk(String) 的一个或多个调用

    3. EndTextMessage() 某个重载的调用

    这种信息构建方法像前面的方法一样复杂,并所提供了所有选项,但使用该此方法还可以更好地控制将信息拆分为页的方式,并可使用更多选项(例如,可以添加页码)。

无论使用哪种方法,如果信息超过服务提供商的字符数限制,信息构造算法将通过在文本"块"之间拆分信息来尝试将信息分割为多个信息。文本块是一个信息中应尽可能排列在一起的一系列字符。与将父信息强制拆分为相等的部分相比,这种方式生成的信息系列的连贯性更强。如果特定块本身超过字符限制,也会将其拆分。只有第三种信息构建方法允许您使用代码在一定程度上控制将信息拆分为块的方式。下面的代码段演示第三种方法。请注意有关此示例中的以下内容:

  • account 是对 SPMobileMessagingAccount 对象的引用。

  • 尽管只有一个 AddRecipient(String) 调用,但您可以多次调用它,以将同一信息发送给多个收件人,直到达到 MSP 强制的限制。

  • SplitLongMessage 是在下面的代码块中定义的。

  • message 是包含信息的 String 对象。

  • 信息构建事务完成后,SPMobileMessageSmsBuilder 对象会将信息存放到其 Message 属性中。

SPMobileMessageSmsBuilder smsBuilder = new SPMobileMessageSmsBuilder(account);
smsBuilder.AddRecipient(mobile_telephone_number);

// Begin the message building transaction
smsBuilder.StartTextMessage();

// Add the message text, split as needed into chunks.
List<StringBuilder> messageParts = SplitLongMessage(message)
foreach (StringBuilder chunk in messageParts)
{
    smsBuilder.AddChunk(chunk.ToString());
}

// Finish the transaction
smsBuilder.EndTextMessage();

// At this point, the smsBuilder.Message property holds the message as an SPMobileSmsMessage object.
Dim smsBuilder As New SPMobileMessageSmsBuilder(account)
smsBuilder.AddRecipient(mobile_telephone_number)

' Begin the message building transaction
smsBuilder.StartTextMessage()

' Add the message text, split as needed into chunks.
Dim messageParts As List(Of StringBuilder) = SplitLongMessage(message)
For Each chunk As StringBuilder In messageParts
    smsBuilder.AddChunk(chunk.ToString())
Next

' Finish the transaction
smsBuilder.EndTextMessage()

' At this point, the smsBuilder.Message property holds the message as an SPMobileSmsMessage object

SplitLongMessage 方法实现简单算法以确保任何信息块都不超过每个连接的 SMS 信息块(有时称为"长 SMS 信息")133 个(单字节)字符的 SMS 限制。此外,此方法确保始终在空格处进行拆分,以便不会拆分各信息部分之间的单词。如果手机信息解决方案无法假定信息中的所有字符都是单字节,将需要使用更复杂的算法。

public static List<StringBuilder> SplitLongMessage(String message)
{
    // Split the original message at white space.
    String[] words = message.Split(null);

    List<StringBuilder> chunks = new List<StringBuilder>();
    StringBuilder latestChunk = new StringBuilder(132);

    // Reconstruct the message in chunks of up to 133 characters.
    foreach (String word in words)
    {
        if (word.Length + latestChunk.Length <= 132) //Not 133 because a space will be added
        {
            latestChunk.Append(word + " "); // Add back the white space
        }
        else
        {
            // Add a copy of the chunk to the list
            chunks.Add(new StringBuilder(latestChunk.ToString()));

            // Empty out latest chunk so the next one can be started
            latestChunk.Remove(0, latestChunk.Length);

            // The word that exceeded the limit becomes the first word of the next chunk
            latestChunk.Append(word + " ");
        }
    }

    // Add the last short chunk
    if (latestChunk.Length > 0)
    {
        chunks.Add(latestChunk);
    }

    return chunks;
}
Public Shared Function SplitLongMessage(ByVal message As String) As List(Of StringBuilder)
    ' Split the original message at white space.
    Dim words() As String = message.Split(Nothing)

    Dim chunks As New List(Of StringBuilder)()
    Dim latestChunk As New StringBuilder(132)

    ' Reconstruct the message in chunks of up to 133 characters.
    For Each word As String In words
        If word.Length + latestChunk.Length <= 132 Then 'Not 133 because a space will be added
            latestChunk.Append(word & " ") ' Add back the white space
        Else
            ' Add a copy of the chunk to the list
            chunks.Add(New StringBuilder(latestChunk.ToString()))

            ' Empty out latest chunk so the next one can be started
            latestChunk.Remove(0, latestChunk.Length)

            ' The word that exceeded the limit becomes the first word of the next chunk
            latestChunk.Append(word & " ")
        End If
    Next word

    ' Add the last short chunk
    If latestChunk.Length > 0 Then
        chunks.Add(latestChunk)
    End If

    Return chunks
End Function

无论是使用 SetTextContent() 的调用还是使用信息构建事务构建 SPMobileSmsMessage 对象(在 SPMobileMessageBuilder.Message 属性中引用),都必须使用代码将该对象转换为相应的 OMS 格式信息 XML。这是通过调用 GetMessageXml() 方法实现的。如果使用 BuildSmsMessage(SPMobileMessagingAccount, String, String) 方法的调用来构建信息,则不需要使用这一额外的 XML 写入步骤,因为该调用会返回信息 XML。

String messageXml = smsBuilder.GetMessageXml();
Dim messageXml As String = smsBuilder.GetMessageXml()

发送信息

信息发送是通过将符合 OMS 的完整信息 XML 传递给 SPMobileMessageWebService 对象的 SendMessage(String) 方法实现的。有关如何创建此类对象的信息,请参阅上文中的创建 Web 服务对象。在下面的代码段中,messagingWebService 是一个 SPMobileMessageWebService 对象,messageXml 是符合 OMS 的完整信息。

SPMobileMessageDeliveryReport report = messagingWebService.SendMessage(messageXml);
Dim report As SPMobileMessageDeliveryReport = messagingWebService.SendMessage(messageXml)

SendMessage(String) 返回的报告包含有关信息是否成功发送的信息,如果未成功发送,还应包含失败的原因。建议您包含用于处理报告、记录成功信息以及响应失败的代码。有关报告结构的信息,请参阅 SPMobileMessageDeliveryReport

批量发送信息

如果您的解决方案使用批量发送,则需要使用代码将批作业之间创建的信息存储在某种序列结构中,批量发送时可以刷新这种结构(如,List<T><SPMobileSmsMessage>)。批作业首先创建要向其添加各信息对象的 SPMobileMessageBatchPackage 对象。然后,将包传递给 BatchSendMessages(SPMobileMessageBatchPackage) 方法。

在下面的代码段中,messageCollection 是一个 List<T><SPMobileSmsMessage> 对象,messagingWebService 是一个 SPMobileMessageWebService 对象。有关如何创建此类对象的信息,请参阅上文中的创建 Web 服务对象

SPMobileMessageBatchPackage package = new SPMobileMessageBatchPackage();

foreach (SPMobileSmsMessage message in messageCollection)
{
    package.AddMessage(message);
}

List<SPMobileMessageDeliveryReport> reports = messagingWebService.BatchSendMessages(package);
Dim package As New SPMobileMessageBatchPackage()

For Each message As SPMobileSmsMessage In messageCollection
    package.AddMessage(message)
Next message

Dim reports As List(Of SPMobileMessageDeliveryReport) = messagingWebService.BatchSendMessages(package)

请注意,不必将包中的 SPMobileSmsMessage 对象明确转换为符合 OMS 的 XML 消息。该包在其 Xml 属性中返回整个批处理作业 XML。BatchSendMessages(SPMobileMessageBatchPackage) 方法就是将该 XML 发送给信息传递 Web 服务。

建议您包含用于处理 BatchSendMessages(SPMobileMessageBatchPackage) 方法返回的报告列表、记录成功信息以及响应失败的代码。

其他 Web 服务方法

SPMobileMessageWebService 类提供了两个其他方法(即,GetUserInfo(String)GetServiceInfo()),分别充当 OMS Web 方法 GetUserInfoGetServiceInfo 的代理。

针对其他协议进行开发

Microsoft 不支持从 Microsoft.SharePoint.MobileMessage 中的任何类进行派生来创建不使用 OMS 协议的手机信息解决方案。如果希望您的解决方案使用这种不支持 OMS 的 MSP,请考虑创建一个 Web 服务,将其作为 SharePoint Foundation 手机信息 API 和使用其他协议的 MSP 之间的中间层。该服务将接受来自 SharePoint Foundation 的 OMS 协议信息,然后将其转换为使用其他协议的 MSP 适用的信息。