Custom Notifications

From Sense/Net Wiki
Jump to: navigation, search
  •  
  •  
  •  
  •  
  • 100%
  • 6.0.8
  • Enterprise
  • Community
  • Planned

Overview

Notification Config
Sense/Net 6.0 provides enhanced Notification feature to allow users to subscribe to different events and receive mail messages about changes in the Content Repository. The process of mail generation can be fine tuned using Notification Config files.

Details

When an event occurs in the Content Repository, an email message is sent to all subscribers, immediately or in a digest message - depending on the frequency settings of the subscription. These email messages can be customized by placing a content of NotificationConfig Content Type under a system folder of name (config), at the desired place in the Content Repository. Resolution of these configurations pretty much works the same way as resolving applications in the Smart Application Model. Here is an example structure for placing NotificationConfig content in the Content Repository:

  • Root
    • Sites
      • Default_Site
        • (apps)
        • (config)
          • NotificationConfig

This way every email about changes below the Default_Site will be controlled by the NotificationConfig content placed in the (config) system folder. The name of the configuration content must be NotificationConfig.

A NotificationConfig content can control the outlook of separate emails and therefore it currently does not support digest mode emails. Any email about a change under a path controlled by a custom NotificationConfig content will be sent separately, even if the subscription is for digest emails.

NotificationConfig Fields

Any NotificationConfig content has the following fields:

  • Subject: defines the subject of the email to be sent. {FieldName} templates can be used.
  • Body: defines the body of the email to be sent. {FieldName} templates can be used.
  • SenderAddress: defines the address of the sender of the email to be sent. This parameter is optional, if left empty, than the default value will be used that is set as NotificationSenderAddress in the Web.config file.

NotificationConfig Default Operation

The following applies to the email sending procedure when an event is affected by a NotificationConfig content:

  • emails on content that are not under a folder that contains a /(config)/Notification structure are generated with the default templates,
  • NotificationConfig content at lower levels override those on upper levels,
  • the Subject and the Body of the emails are specified by the NotificationConfig content corresponding Fields, given {FieldName} templates are replaced with their corresponding Field data,
  • the Sender of the emails is set to the SenderAddress specified by the NotificationConfig content (if not empty),
  • emails about the changes of NotificationConfig files are not sent.

Template resolution

You can use any dynamic property in a template that can be cast to a string, for example:

  • Body: Content description is {Description}

You can also use string properties of referenced content, like:

  • Subject: content changes by {CreatedBy.FullName}

Besides dynamic properties, the following NodeHead properties are supported:

  • Id
  • Name
  • Path
  • DisplayName

Custom NotificationConfig

You can create custom Notification configurations by creating a custom Content Type inheriting from NotificationConfig, and creating a custom Content Handler for it. Within the Content Handler (that should derive from SenseNet.Messaging.NotificationConfig) you can override the following functions:

  • string GetSubject(Node context): you can specify a custom function that creates a subject for the email message. The changed/created content is passed as a function parameter.
  • string GetBody(Node context): you can specify a custom function that creates a body for the email message. The changed/created content is passed as a function parameter.
  • string GetSenderAddress(Node context): you can specify a custom function that creates a sender address for the email message. The changed/created content is passed as a function parameter.
  • bool IsNotificationAllowedForContent(Node context): you can define whether an email message is to be sent for the specified content or not. The default implementation simply checks if the context is the NotificationConfig content itself, and in that case it returns false (return context.Id != this.Id;).

You can use the protected string ReplacePropertyValues(Node context, string text) function to use the built-in template resolution procedure.

See the example section on how to create a custom NotificationConfig.

Example/Tutorials

Customizing emails' subject and body

This example shows how to customize the subject and the body of notification emails for News Articles.

  1. create a new SystemFolder with the name (config) under /Root/Sites/Default_Site/NewsDemo
  2. create a new NotificationConfig content in the (config) folder
  3. set the subject to Article: {DisplayName}
  4. set the body to:
Jump to Article: <a href="localhost/{Path}">{DisplayName}</a>
<hr/>
{Subtitle}
{Lead}
{Body}

This way the emails sent about News Articles will have a customized subject and body, containing the different Field values of the Article, like DisplayName and Body.

Differentiating between Content Types

The following example shows how to send customized notifications on content in the Content Repository that can be commented and liked by users. Since Comments and Likes are also content in the Content Repository notifications are also sent to users who have subscribed when they are created. These emails should look somewhat different from other emails.

  • 1: create a new Content Handler inheriting from NotificationConfig. Create 4 new properties, for defining the templates for subjects and bodies for Likes and Comments. Override the GetSubject, GetBody and IsNotificationAllowedForContent functions:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using SenseNet.Messaging;
using SenseNet.ContentRepository;
using SenseNet.ContentRepository.Schema;
using SenseNet.ContentRepository.Storage;
 
namespace MyHandlers
{
    [ContentHandler]
    public class PostNotificationConfig : NotificationConfig
    {
        /*================================================================================= Required construction */
 
        public PostNotificationConfig(Node parent) : this(parent, "PostNotificationConfig") { }
        public PostNotificationConfig(Node parent, string nodeTypeName) : base(parent, nodeTypeName) { }
        protected PostNotificationConfig(NodeToken nt) : base(nt) { }
 
        /*================================================================================= Mapped Properties */
 
        private const string LIKESUBJECTPROPERTY = "LikeSubject";
        [RepositoryProperty(LIKESUBJECTPROPERTY, RepositoryDataType.String)]
        public virtual string LikeSubject
        {
            get { return base.GetProperty<string>(LIKESUBJECTPROPERTY); }
            set { base.SetProperty(LIKESUBJECTPROPERTY, value); }
        }
 
        private const string LIKEBODYPROPERTY = "LikeBody";
        [RepositoryProperty(LIKEBODYPROPERTY, RepositoryDataType.Text)]
        public string LikeBody
        {
            get { return base.GetProperty<string>(LIKEBODYPROPERTY); }
            set { base.SetProperty(LIKEBODYPROPERTY, value); }
        }
 
        private const string COMMENTSUBJECTPROPERTY = "CommentSubject";
        [RepositoryProperty(COMMENTSUBJECTPROPERTY, RepositoryDataType.String)]
        public string CommentSubject
        {
            get { return base.GetProperty<string>(COMMENTSUBJECTPROPERTY); }
            set { base.SetProperty(COMMENTSUBJECTPROPERTY, value); }
        }
 
        private const string COMMENTBODYPROPERTY = "CommentBody";
        [RepositoryProperty(COMMENTBODYPROPERTY, RepositoryDataType.Text)]
        public string CommentBody
        {
            get { return base.GetProperty<string>(COMMENTBODYPROPERTY); }
            set { base.SetProperty(COMMENTBODYPROPERTY, value); }
        }
 
        /*================================================================================= Required generic property handling */
 
        public override object GetProperty(string name)
        {
            switch (name)
            {
                case COMMENTSUBJECTPROPERTY:
                    return this.CommentSubject;
                case COMMENTBODYPROPERTY:
                    return this.CommentBody;
                case LIKESUBJECTPROPERTY:
                    return this.LikeSubject;
                case LIKEBODYPROPERTY:
                    return this.LikeBody;
                default:
                    return base.GetProperty(name);
            }
        }
        public override void SetProperty(string name, object value)
        {
            switch (name)
            {
                case COMMENTSUBJECTPROPERTY:
                    this.CommentSubject = (string)value;
                    break;
                case COMMENTBODYPROPERTY:
                    this.CommentBody = (string)value;
                    break;
                case LIKESUBJECTPROPERTY:
                    this.LikeSubject = (string)value;
                    break;
                case LIKEBODYPROPERTY:
                    this.LikeBody = (string)value;
                    break;
                default:
                    base.SetProperty(name, value);
                    break;
            }
        }
 
        /*================================================================================= NotificationConfig */
 
        // gets the associated Post
        private Node GetPost(Node context)
        {
            var article = context.NodeType.IsInstaceOfOrDerivedFrom("Post") ? context : Node.GetAncestorOfNodeType(context, "Post");
            return article;
        }
 
        // defines two custom templates that can be used from the UI: {Post} for the Description of the Post and {PostPath} for its path
        private string ReplaceText(string text, Node context)
        {
            var post = GetPost(context);
            return text.Replace("{Post}", post.Description).Replace("{PostPath}", post.Path);
        }
 
        // returns the customized subject for the email, differentiating according to the Content Type of the changed/created content
        public override string GetSubject(Node context)
        {
            if (context.NodeType.IsInstaceOfOrDerivedFrom("Comment"))
                return this.ReplacePropertyValues(context, ReplaceText(this.CommentSubject, context));
 
            if (context.NodeType.IsInstaceOfOrDerivedFrom("Like"))
                return this.ReplacePropertyValues(context, ReplaceText(this.LikeSubject, context));
 
            return base.GetSubject(context);
        }
 
        // returns the customized body for the email, differentiating according to the Content Type of the changed/created content
        public override string GetBody(Node context)
        {
            if (context.NodeType.IsInstaceOfOrDerivedFrom("Comment"))
                return this.ReplacePropertyValues(context, ReplaceText(this.CommentBody, context));
 
            if (context.NodeType.IsInstaceOfOrDerivedFrom("Like"))
                return this.ReplacePropertyValues(context, ReplaceText(this.LikeBody, context));
 
            return base.GetBody(context);
        }
 
        // only Posts, Comments and Likes generate email notifications, nothing else
        public override bool IsNotificationAllowedForContent(Node context)
        {
            if (context.NodeType.IsInstaceOfOrDerivedFrom("Post") || context.NodeType.IsInstaceOfOrDerivedFrom("Like") || context.NodeType.IsInstaceOfOrDerivedFrom("Comment"))
                return true;
 
            return false;
        }
    }
}
  • 2: create a new Content Type that inherits from NotificationConfig and define the Fields for the properties given in the above Content Handler:
<ContentType name="PostNotificationConfig" parentType="NotificationConfig" handler="MyHandlers.PostNotificationConfig" xmlns="http://schemas.sensenet.com/SenseNet/ContentRepository/ContentTypeDefinition">
  <DisplayName>Posts Notification Configuration</DisplayName>
  <Description></Description>
  <Icon>Content</Icon>
  <Fields>
    <Field name="LikeSubject" type="ShortText">
      <DisplayName>LikeSubject</DisplayName>
      <Description></Description>
    </Field>
    <Field name="LikeBody" type="LongText">
      <DisplayName>LikeBody</DisplayName>
      <Description></Description>
    </Field>
    <Field name="CommentSubject" type="ShortText">
      <DisplayName>CommentSubject</DisplayName>
      <Description></Description>
    </Field>
    <Field name="CommentBody" type="LongText">
      <DisplayName>CommentBody</DisplayName>
      <Description></Description>
    </Field>
  </Fields>
</ContentType>
  • 3: create a new PostNotificationConfig with the name NotificationConfig under a (config) SystemFolder under /Root/Sites/Default_Site/workspaces/Project/budapestprojectworkspace
  • 4: set the config content's Field values optionally:
    • LikeSubject: Wall Posts: {Post} - {CreatedBy.FullName} liked
    • LikeBody: <a href="knowledgebase/{ArticlePath}">knowledgebase/{ArticlePath}</a>
    • CommentSubject: Wall Posts: {Post} - {CreatedBy.FullName} commented
    • CommentBody:
<a href="localhost/{PostPath}">{Post}</a>
<hr/>
{CreatedBy.FullName} commented: {Description}

This way email messages on Likes and Comments will be fully customized.

Related links

References

This page contains no references to outer Internet pages or articles.