Overview of Mobile Messaging Development
Published: May 2010
This topic provides an overview of adding mobile messaging functionality to a Microsoft SharePoint Foundation development project using the mobile messaging APIs of the SharePoint Foundation Software Development Kit (SDK). These APIs can be usefully divided into two broad groups: those that support Short Message Service (SMS) messaging (also called “texting”) using the Office Mobile Service (OMS) communication protocol and those that enable you to build support for other communication or message structure protocols. In most development scenarios, the sender of the messages is the SharePoint Foundation Web application as opposed to a particular user, so the SharePoint Foundation deployment will need to have an account with a mobile messaging service provider (MSP) company that supports the communication protocol that your solution uses.
Office Mobile Service (OMS) Protocol is a communication protocol that provides an implementation of the SMS and Multimedia Message Service (MMS) message structure protocols. OMS requires the SOAP protocol for Web service access. The OMS-supporting APIs discussed in OMS-SMS Messaging Solutions below are designed for SMS messaging. Any classes or members you find in the Microsoft.SharePoint.MobileMessage namespace with “MMS” in their name, or which only make sense in the context of MMS messaging, are for internal use only and should not be called from your code. To develop messaging solutions that do not use OMS as the communication protocol or that use OMS for MMS messages, use the more abstract level of APIs discussed in Developing for Other Protocols below.
SharePoint Foundation provides APIs that do all the OMS Web Method calling, and all of the XML parsing and writing, for you. Your code simply calls the APIs in familiar object-oriented syntax.
Creating an MSP Account for a Web Application
Each SharePoint Foundation Web application, including the Central Administration Web application, can have an account with an MSP. Normally, these accounts are set by a farm administrator in the Application Management portion of the Central Administration application. However, you can programmatically create an account and assign it to a Web application. First, call a SPMobileMessagingAccount() constructor that does not require an SPMobileMessageServiceProvider parameter. Then call the UpdateSmsAccount(SPMobileMessagingAccount) method to assign the account to a Web application. In the following snippet, webApp is a reference to an SPWebApplication object. (See Getting References to Sites, Web Applications, and Other Key Objects for information about how to get a reference to such an object.) The snippet assumes that the file has using statements for Microsoft.SharePoint and System.Security. Note that the call to UpdateSmsAccount(SPMobileMessagingAccount) is passed as part of an anonymous delegate to the RunWithElevatedPrivileges(SPSecurity.CodeToRunElevated) method.
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)
After the Web application has been assigned an account with the MSP, your code can thereafter use the OutboundSmsServiceAccount property as a reference to the Web application’s account object.
Creating a Web Service Object
When you have an SPMobileMessagingAccount, your code can use it to create an SPMobileMessageWebService object that contains the methods for sending SMS messages. We recommend that whenever you obtain a reference to a persisted SPMobileMessagingAccount object, you always verify that it is not null and that its IsValidAccount() property is true. The following snippet illustrates how to create a Web service object. webApp is a reference to an SPWebApplication object.
Building and Sending a Mobile Message
The next two critical tasks are building and sending the message.
Building a Message
With a SPMobileMessageWebService object your code can call the service’s OMS Web Methods by using the methods of the object as proxies. The most important of these, of course, is the SendMessage(String) method. However, before you can call it, your code must build the message. There are three methods for doing this.
Your code can call the static BuildSmsMessage(SPMobileMessagingAccount, String, String) method and pass it parameters for the sender’s account, a recipient, and the text for the message. This is the simplest, but least flexible way.
Your code can call one of the overloads of SetTextContent(). This would require you to first construct the SPMobileMessageSmsBuilder and add recipients with calls of the AddRecipient(String) method and also to convert the message from the SPMobileSmsMessage object that SetTextContent() creates to the proper message XML of the OMS protocol. But this way of building the message gives you the option to have multiple recipients. It also enables you to set a lower limit on the number of child pages than the limit that is imposed by the service provider.(ContentParts) into which the message is split if the message text exceeds the character limit imposed by the service.
Your code can create a messaging building transaction. Such a transaction consists of the following:
A call of StartTextMessage()
One or more calls of AddChunk(String)
A call of one of the overloads of EndTextMessage()
This way of building the message gives you all the options, and all the complications, as the preceding way, but also gives you greater control over how the message is split into pages as well as additional options, such as the option to add page numbers.
Regardless of the method used, if a message exceeds the service provider’s limit on the number of characters, the message construction algorithm will attempt to divide the message into multiple messages by splitting the message between “chunks” of text. A chunk of text is a run of characters that should stay together in a single message, if possible. This will make the resulting series of messages more coherent than if the parent message was divided into equal, but arbitrarily divided, parts. If a specific chunk itself exceeds the character limit, it will be split anyway. Only the third method of building a message enables your code to have some control over how the message is split into chunks. The following snippet illustrates the third method. Note the following about this example:
account is a reference to an SPMobileMessagingAccount object.
Although there is only one call of AddRecipient(String), you can call it multiple times to send the same message to multiple recipients, up to the limit imposed by the MSP.
SplitLongMessage is defined in the next code block below.
message is a String object that contains the message.
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
The SplitLongMessage method implements a simple algorithm to ensure that no chunk of the message exceeds the SMS limit of 133 (single-byte) characters for each chunk of a concatenated SMS message, sometimes called a “long SMS message”. Moreover, it ensures that splits always come at white space, so no word is split between message parts. A more complex algorithm would be needed if your mobile messaging solution cannot assume that all the characters in the message will be single-byte.
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
Whether you built the SPMobileSmsMessage object (referenced in the SPMobileMessageBuilder.Message property) with a call of SetTextContent() or by using a message building transaction, your code must convert that object into the proper OMS format message XML. This is done by a call of the GetMessageXml() method. This additional XML writing step is not required if you build your message by using a call of the BuildSmsMessage(SPMobileMessagingAccount, String, String) method, because it returns the message XML.
Sending a Message
A message is sent by passing the complete, OMS-compliant message XML to the SendMessage(String) method of an SPMobileMessageWebService object. See Creating a Web Service Object above for information about how to create such an object. In the following snippet, messagingWebService is an SPMobileMessageWebService object and messageXml is the complete OMS-compliant message.
The report that is returned by SendMessage(String) contains information about whether the message was successfully sent and, if not, why it was not. We recommend that you include code that processes the report, logs successful messages, and responds to failures. For information about the structure of the report, see SPMobileMessageDeliveryReport.
Sending Batches of Messages
If your solution uses batch sending, your code will need to store the messages that are created between batch jobs in some kind of queue structure that can be flushed when the batch is sent, such as List<T><SPMobileSmsMessage>. The batch job begins with the creation of an SPMobileMessageBatchPackage object to which each message object is added. Then the package is passed to the BatchSendMessages(SPMobileMessageBatchPackage) method.
In the snippet below, messageCollection is a List<T><SPMobileSmsMessage> object and messagingWebService is an SPMobileMessageWebService object. See Creating a Web Service Object above for information about how to create such an object.
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)
Note that there is no need to explicitly convert the SPMobileSmsMessage objects that are in the package to OMS-compliant XML messages. The package returns the entire batch job XML in its Xml property. It is this XML that the BatchSendMessages(SPMobileMessageBatchPackage) method sends to the messaging Web service.
We recommend that you include code that processes the list of reports returned by the BatchSendMessages(SPMobileMessageBatchPackage) method, logs successful messages, and responds to failures.
Other Web Service Methods
Microsoft does not support deriving from any of the classes in Microsoft.SharePoint.MobileMessage to create a mobile messaging solution does not use the OMS Protocol. If you want your solution to work with such an MSP that does not use OMS, consider creating a Web service that acts as a middle layer between SharePoint Foundation mobile messaging APIs and the MSP that uses another protocol. The service would accept OMS protocol messages from SharePoint Foundation and transform them into messages appropriate for the MSP that uses the other protocol.