AlertUser API

This API is used to contact the IPF portals from a third-party application and start a session. The API creates a new temporary session in memory and runs custom code under a mapped portal user account. For example, you could use this alert to send rich-HTML portal email based on back office actions, such as order entry. When an order is placed in the back office, the application can contact the Customer Portal, and the Customer Portal can send out an order verification email message.

This API has four signatures:

  • void AlertUser(string userId, IPFEventI e)
  • void AlertUser(string userId, string eventName)
  • void AlertUser(string userId, IPFEventI e, int LCID)
  • void AlertUser(string userId, string eventName, int LCID)

userId: The IPF user under which the custom code is executed.

e / eventName: The payload to be delivered to the custom code, either a full event with variables, or simply a name.

LCID: The Microsoft locale ID used when the alert is handled on the target portal. If the LCID is invalid or not supplied, then the target portal's default locale is used.

This API throws exceptions if either of these is true:

  • userId is null, empty, does not refer to a valid IPF user, or the calling user does not have permission to run custom code under the userId's account. See the next section for details.
  • e is null

OnUserAlert handler

After a logged-in user has been alerted, the custom code is run under the given user. This custom code is located in the portal's user-authenticated script. The UserAuthenticated event fires, and any handlers connected to this event will execute, just like any other user logging in to the portal. If access has been granted, then the OnUserAlert event fires, and any handlers connected to this event will execute. These handlers have this signature:

  • OnUserAlerted(ByVal context As SessionUserAlertContextI, ByVal parms As SessionUserAlertParmsI)

context: Gives access to the same level of functionality as the SessionUserAuthenticatedContext, essentially leaving out alerts and any functionality having to do with layouts and rendering.

parms: Contains information having to do with the AlertUser request:

  • IPFEventI Event: The payload of the alert.
  • String FromUser: The IPF user who initiated the alert.

Calling from a third-party application

The AlertUser API is used by portal users who are already logged in, however, the same action can be taken by outside applications, such as . By calling the AlertUser web service available in the portal, outside applications can get the same result from outside the portal.

A third-party application should contain the following code in a separate VB file in its Visual Studio project. In order for this code to be compiled, the .NET assembly 'System.ServiceModel' must be added as a reference to the project.


Option Strict On
Option Explicit On

Imports System
Imports System.Runtime.Serialization
Imports System.ServiceModel

Namespace IPFAlertService
    Public Class AlertServiceClient

        Public Sub New(ByVal portalURL As String)
            _portalURL = portalURL
            Dim MAXSIZE As Integer = Int32.MaxValue
            Dim binding As BasicHttpBinding = New BasicHttpBinding()
            binding.MessageEncoding = WSMessageEncoding.Text
            binding.MaxBufferSize = MAXSIZE
            binding.MaxReceivedMessageSize = MAXSIZE
            binding.SendTimeout = New TimeSpan(0, 10, 0)
            binding.ReceiveTimeout = New TimeSpan(0, 10, 0)

            Dim readerQuotasDictionary As System.Xml.XmlDictionaryReaderQuotas 
= New System.Xml.XmlDictionaryReaderQuotas()
            readerQuotasDictionary.MaxStringContentLength = MAXSIZE
            readerQuotasDictionary.MaxArrayLength = MAXSIZE
            readerQuotasDictionary.MaxDepth = MAXSIZE
            readerQuotasDictionary.MaxNameTableCharCount = MAXSIZE
            binding.ReaderQuotas = readerQuotasDictionary

            Dim bindingSecurity As BasicHttpSecurity = New BasicHttpSecurity()
            bindingSecurity.Mode = BasicHttpSecurityMode.TransportCredentialOnly

            Dim bindingTransportSecurity As HttpTransportSecurity = New 
HttpTransportSecurity()
            bindingTransportSecurity.ClientCredentialType = 
HttpClientCredentialType.Windows
            bindingSecurity.Transport = bindingTransportSecurity
            binding.Security = bindingSecurity

            binding.ProxyAddress = New Uri(portalURL)
            binding.UseDefaultWebProxy = False
            Try
                Dim endPoint As EndpointAddress = New EndpointAddress(portalURL)
                _client = New 
IPFAlertService.AlertServiceClient.AlertServiceClient(binding, endPoint)
_client.ClientCredentials.Windows.AllowedImpersonationLevel = 
System.Security.Principal.TokenImpersonationLevel.Identification
_client.ChannelFactory.Credentials.Windows.ClientCredential = 
System.Net.CredentialCache.DefaultNetworkCredentials
            Catch ex As Exception
                Throw New Exception("Unable to connect")
            End Try
        End Sub

        Public Sub AlertUser(ByVal userId As String, ByRef e As IPFEvent)
            _client.AlertUser_Event(userId, e)
        End Sub
        Public Sub AlertUser(ByVal userId As String, ByVal eventName As String)
            _client.AlertUser_EventName(userId, eventName)
        End Sub
        Public Sub AlertUser(ByVal userId As String, ByRef e As IPFEvent, ByVal 
LCID As Integer)
            _client.AlertUser_Event_LCID(userId, e, LCID)
        End Sub
        Public Sub AlertUser(ByVal userId As String, ByVal eventName As String, 
ByVal LCID As Integer)
            _client.AlertUser_EventName_LCID(userId, eventName, LCID)
        End Sub

        Private _portalURL As String
        Private _client As AlertServiceClient

        <System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", 
"4.0.0.0"), _
         
System.ServiceModel.ServiceContractAttribute([Namespace]:="IPFAlertService", 
ConfigurationName:="AlertServiceReference.IAlertService")> _
        Private Interface IAlertService
<System.ServiceModel.OperationContractAttribute(Action:="IPFAlertService/IAle
rtService/AlertUser_Event", 
ReplyAction:="IPFAlertService/IAlertService/AlertUser_EventResponse")> _
            Sub AlertUser_Event(ByVal userId As String, ByVal e As 
IPFAlertService.IPFEvent)
<System.ServiceModel.OperationContractAttribute(Action:="IPFAlertService/IAle
rtService/AlertUser_EventName", 
ReplyAction:="IPFAlertService/IAlertService/AlertUser_EventNameResponse")> _
            Sub AlertUser_EventName(ByVal userId As String, ByVal eventName As 
String)
<System.ServiceModel.OperationContractAttribute(Action:="IPFAlertService/IAle
rtService/AlertUser_Event_LCID", 
ReplyAction:="IPFAlertService/IAlertService/AlertUser_Event_LCIDResponse")> _
            Sub AlertUser_Event_LCID(ByVal userId As String, ByVal e As 
IPFAlertService.IPFEvent, ByVal LCID As Integer)
<System.ServiceModel.OperationContractAttribute(Action:="IPFAlertService/IAle
rtService/AlertUser_EventName_LCID", 
ReplyAction:="IPFAlertService/IAlertService/AlertUser_EventName_LCIDResponse"
)> _
            Sub AlertUser_EventName_LCID(ByVal userId As String, ByVal eventName 
As String, ByVal LCID As Integer)
        End Interface

        <System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", 
"4.0.0.0")> _
        Private Interface IAlertServiceChannel
            Inherits IPFAlertService.AlertServiceClient.IAlertService, 
System.ServiceModel.IClientChannel
        End Interface

        <System.Diagnostics.DebuggerStepThroughAttribute(), _
         System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", 
"4.0.0.0")> _
        Partial Private Class AlertServiceClient
            Inherits System.ServiceModel.ClientBase(Of 
IPFAlertService.AlertServiceClient.IAlertService)
            Implements IPFAlertService.AlertServiceClient.IAlertService
            Public Sub New()
                MyBase.New()
            End Sub
            Public Sub New(ByVal endpointConfigurationName As String)
                MyBase.New(endpointConfigurationName)
            End Sub
            Public Sub New(ByVal endpointConfigurationName As String, ByVal 
remoteAddress As String)
                MyBase.New(endpointConfigurationName, remoteAddress)
            End Sub
            Public Sub New(ByVal endpointConfigurationName As String, ByVal 
remoteAddress As System.ServiceModel.EndpointAddress)
                MyBase.New(endpointConfigurationName, remoteAddress)
            End Sub
            Public Sub New(ByVal binding As System.ServiceModel.Channels.Binding, 
ByVal remoteAddress As System.ServiceModel.EndpointAddress)
                MyBase.New(binding, remoteAddress)
            End Sub
            Public Sub AlertUser_Event(ByVal userId As String, ByVal e As 
IPFAlertService.IPFEvent) Implements 
IPFAlertService.AlertServiceClient.IAlertService.AlertUser_Event
                MyBase.Channel.AlertUser_Event(userId, e)
            End Sub
            Public Sub AlertUser_EventName(ByVal userId As String, ByVal eventName 
As String) Implements 
IPFAlertService.AlertServiceClient.IAlertService.AlertUser_EventName
                MyBase.Channel.AlertUser_EventName(userId, eventName)
            End Sub
            Public Sub AlertUser_Event_LCID(ByVal userId As String, ByVal e As 
IPFAlertService.IPFEvent, ByVal LCID As Integer) Implements 
IPFAlertService.AlertServiceClient.IAlertService.AlertUser_Event_LCID
                MyBase.Channel.AlertUser_Event_LCID(userId, e, LCID)
            End Sub
            Public Sub AlertUser_EventName_LCID(ByVal userId As String, ByVal 
eventName As String, ByVal LCID As Integer) Implements 
IPFAlertService.AlertServiceClient.IAlertService.AlertUser_EventName_LCID
                MyBase.Channel.AlertUser_EventName_LCID(userId, eventName, LCID)
            End Sub
        End Class
    End Class

    <System.Diagnostics.DebuggerStepThroughAttribute(), _
System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization"
, "4.0.0.0"), _
System.Runtime.Serialization.DataContractAttribute(Name:="IPFEvent", 
[Namespace]:="IPFAlertService"), _
System.SerializableAttribute()> _
    Partial Public Class IPFEvent
        Inherits Object
        Implements System.Runtime.Serialization.IExtensibleDataObject, 
System.ComponentModel.INotifyPropertyChanged
        <System.NonSerializedAttribute()> _
        Private extensionDataField As 
System.Runtime.Serialization.ExtensionDataObject
        <System.Runtime.Serialization.OptionalFieldAttribute()> _
        Private NameField As String
        <System.Runtime.Serialization.OptionalFieldAttribute()> _
        Private VariablesField As System.Collections.Generic.Dictionary(Of 
String, Object)
        Public Sub New()
            Variables = New System.Collections.Generic.Dictionary(Of String, 
Object)
        End Sub

        <Global.System.ComponentModel.BrowsableAttribute(False)> _
        Public Property ExtensionData() As 
System.Runtime.Serialization.ExtensionDataObject Implements 
System.Runtime.Serialization.IExtensibleDataObject.ExtensionData
            Get
                Return Me.extensionDataField
            End Get
            Set(ByVal value As System.Runtime.Serialization.ExtensionDataObject)
                Me.extensionDataField = value
            End Set
        End Property

        <System.Runtime.Serialization.DataMemberAttribute()> _
        Public Property Name() As String
            Get
                Return Me.NameField
            End Get
            Set(ByVal value As String)
                If (Object.ReferenceEquals(Me.NameField, value) <> True) Then
                    Me.NameField = value
                    Me.RaisePropertyChanged("Name")
                End If
            End Set
        End Property

        <System.Runtime.Serialization.DataMemberAttribute()> _
        Public Property Variables() As System.Collections.Generic.Dictionary(Of 
String, Object)
            Get
                Return Me.VariablesField
            End Get
            Set(ByVal value As System.Collections.Generic.Dictionary(Of String, 
Object))
                If (Object.ReferenceEquals(Me.VariablesField, value) <> True) Then
                    Me.VariablesField = value
                    Me.RaisePropertyChanged("Variables")
                End If
            End Set
        End Property

        Public Event PropertyChanged As 
System.ComponentModel.PropertyChangedEventHandler Implements 
System.ComponentModel.INotifyPropertyChanged.PropertyChanged

        Protected Sub RaisePropertyChanged(ByVal propertyName As String)
            Dim propertyChanged As 
System.ComponentModel.PropertyChangedEventHandler = Me.PropertyChangedEvent
            If (Not (propertyChanged) Is Nothing) Then
                propertyChanged(Me, New 
System.ComponentModel.PropertyChangedEventArgs(propertyName))
            End If
        End Sub
    End Class
End Namespace

This code exposes two classes, AlertServiceClient and IPFEvent, located in the IPFAlertService namespace. An AlertServiceClient instance is created by passing in the URL of the alert service endpoint of the portal to contact:

<Full Portal URL> /ipf/svc/au_wcf

After this object is created, it has four methods that have the same parameters as the four AlertUser portal scripting methods shown in the previous section. The following example creates a client object, creates an IPFEvent object with two variables, and alerts a user with the event payload.

Dim client As IPFAlertService.AlertServiceClient = New IPFAlertService.AlertServiceClient("http://myPortal:8282/ipf/svc/au_wcf")

Dim eventPayload As IPFAlertService.IPFEvent = New IPFAlertService.IPFEvent()
eventPayload.Name = "EmailOrderConfirmation"
eventPayload.Variables.Add("Timestamp", System.DateTime.Now)
eventPayload.Variables.Add("OrderId", 201)

client.AlertUser("ipf_user_to_alert", eventPayload)

Any call made to this service endpoint must be authenticated using Windows domain authentication. If issues are encountered, an exception is thrown giving details as to why the call failed.

The calling application can see this message:

Issue Exception message
IPF cannot determine the identity of who called the service. No Windows account appears for this request.
The identity can be determined, but it is not listed in the external interface mapping in the Portal Manager (see next section). The Windows Account '<account>' does not map to any IPF user.
The identity can be determined and is listed in the external interface mapping, but the IPF user to which it maps does not exist. The user '<user>' in the external interface mapping is not a valid IPF user.
The portal has not been configured with a task repository. This requires creating an MSSQL data source in the Portal Manager and designating it as a task repository by applying the 'IPF Task Repository' Managed Revision Based Schema against it. This portal has not been configured with a valid IPF Task Repository.
The user being alerted by the AlertUser call does not exist. The user '<user>' to be alerted is not a valid IPF user.

External interface mapping

When an external application connects to this interface, Windows domain authentication is used to ensure that the external application is on the same domain as the portal it is trying to connect with. Following this authentication, the calling Windows account must be associated with a portal user account. This association is made in the Portal Manager on the External Interface tab.

Viewing tasks

The AlertUser API, along with other features of IPF 4.x, is implemented by placing a task into an MSSQL content database for a thread to pick up and process. This enables longer-running requests to be executed in a way that does not block other tasks that are running at the same time.

Like the email repository, this can be set up in the configuration of an MSSQL data source, as described in the portal installation guide. If a data source has been set up to be a Task Repository, then a View Tasks link is available with the data source record in the Portal Manager. When View Tasks is clicked, a modal window shows current and past tasks on the portal.

Changing the task repository

If you must change the task repository from one content database to another, you are prompted to confirm if either the current or new repository is not empty. These messages are displayed:

Condition Message
The current repository is non-empty. Your current task repository has existing tasks that will no longer run on this portal. Are you sure you want to continue?
The new repository is non-empty. The new repository you are about to select has existing tasks that will now be activated for this portal. Are you sure you want to continue?
Both the current and new repositories are non-empty. Your current task repository and the new repository you are about to select are both non-empty. This means that tasks in the current repository will no longer run on this portal, and tasks in the new repository will now be activated for this portal. Are you sure you want to continue?