Implement Forum subscription in Sitefinity 3.x

January 05, 2010 Digital Experience
In this post I will show you how you can implement Forum subscription in Sitefinity. Instead of going each time to a given post you can just subscribe to the forum post and receive email notification once someone reply to you or you just want to stay informed about the progress of a post.

 

1. I created a database table where I will persist the subscriber - threadID data. You can use the code below to create the same table at your end.

SET ANSI_NULLS ON 
GO 
 
SET QUOTED_IDENTIFIER ON 
GO 
 
CREATE TABLE [dbo].[ForumSubscribers]( 
    [ThreadID] [uniqueidentifier] NOT NULL
    [UserID] [uniqueidentifier] NOT NULL
    [UserEmail] [nvarchar](50) NOT NULL
 CONSTRAINT [PK_ForumSubscribers] PRIMARY KEY CLUSTERED  
    [ThreadID] ASC
    [UserID] ASC 
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ONON [PRIMARY
ON [PRIMARY
 
GO 
 

2. I created a simple LINQ-SQL class called ForumSubscriptionDataContext

3. I modified templates below.

 ~/Sitefinity/ControlTemplates/Forums/SingleThread.ascx - this template list all post in a thread. Here I will add "subscribe" and unsubscribe links.

 

    <div class="sf_threadTitle"
        <h1><asp:Literal runat="server" ID="threadTitle"></asp:Literal></h1
        <asp:LinkButton ID="deleteThreadButton" runat="server" Text="<%$Resources:DeleteThread %>"></asp:LinkButton> 
       <asp:LinkButton ID="subscribeBtn" runat="server" Text="Subscribe to this thread" ></asp:LinkButton> 
       <asp:LinkButton ID="UnSubscribeBtn" runat="server" Text="UnSubscribe to this thread" ></asp:LinkButton> 
    </div> 

 

Now I have to create a code behind of this template and subscribe for Click event of each link, so that I can execute our logic.

- Page_Load - subscribe for click events of our buttons.

- OnPreRender - here I am getting the thread ID from the QueryString. ForumSubscriptionDataContext class  is used to manage the data from my custom tablet. Here OnPreRender I check whethet the current user is subscribed to this thread or not and show/hide Sibscribe and Unsibscribe links.

- UnSubscribeBtn_Click - remove the user from the datasource

- subscribeBtn_Click - add new subscriber to the datasource

 

public partial class Sitefinity_ControlTemplates_Forums_SingleThread : System.Web.UI.UserControl 
    public void Page_Load(object sender, EventArgs e) 
    { 
        // subscribe for click events of our buttons 
        this.subscribeBtn.Click += new EventHandler(subscribeBtn_Click); 
        this.UnSubscribeBtn.Click += new EventHandler(UnSubscribeBtn_Click); 
    } 
 
    // Here we have to check whether the user is subscribed to the forum or not  
    // and hide or show - subscribe and unsubscribe links 
    protected override void OnPreRender(EventArgs e) 
    { 
        base.OnPreRender(e); 
        if (!String.IsNullOrEmpty(HttpContext.Current.Request.QueryString["mode"]) && !String.IsNullOrEmpty(HttpContext.Current.Request.QueryString["thread"])) 
        { 
            Guid ThreadID = new Guid(HttpContext.Current.Request.QueryString["thread"].ToString()); 
            ForumSubscriptionDataContext dataContext = new ForumSubscriptionDataContext(); 
            //we are sure that this query it will only result in one record - the current user email. So we use  
            // SingleOrDefault(); Returns the only element of a sequence, or a default value if the sequence is empty; 
            //this method throws an exception if there is more than one element in the sequence. 
            var query = (from sub in dataContext.ForumSubscribers 
                         where sub.ThreadID == ThreadID 
                         select sub.UserEmail).SingleOrDefault(); 
            if (query != null
            { 
                subscribeBtn.Visible = false
                UnSubscribeBtn.Visible = true
            } 
            else 
            { 
                subscribeBtn.Visible = true
                UnSubscribeBtn.Visible = false
 
            } 
        } 
    } 
    /// <summary> 
    /// remove an user from the database 
    /// </summary> 
    /// <param name="sender"></param> 
    /// <param name="e"></param> 
    void UnSubscribeBtn_Click(object sender, EventArgs e) 
    { 
        Guid ThreadID = new Guid(HttpContext.Current.Request.QueryString["thread"].ToString()); 
        string uName = Telerik.Security.UserManager.GetCurrentUserName(); 
        MembershipUser user = Membership.GetUser(uName); 
        Guid userID = new Guid(user.ProviderUserKey.ToString()); 
        string eMail = user.Email; 
        ForumSubscriptionDataContext dataContext = new ForumSubscriptionDataContext(); 
        var query = from sub in dataContext.ForumSubscribers 
                    where sub.ThreadID == ThreadID && sub.UserID == userID 
                    select sub; 
        var record = query.First<ForumSubscriber>(); 
        dataContext.ForumSubscribers.DeleteOnSubmit(record); 
        dataContext.SubmitChanges(); 
        subscriptionMessage.Text = "<span style=background-color:Red;>YOU HAVE BEEN SUCCESSFULLY UNSUBSCRIBED</span>"
    } 
    /// <summary> 
    /// add user to the datbase 
    /// </summary> 
    /// <param name="sender"></param> 
    /// <param name="e"></param> 
    void subscribeBtn_Click(object sender, EventArgs e) 
    { 
        if (!String.IsNullOrEmpty(HttpContext.Current.Request.QueryString["mode"]) && !String.IsNullOrEmpty(HttpContext.Current.Request.QueryString["thread"])) 
        { 
            // get the thread ID. 
            Guid ThreadID = new Guid(HttpContext.Current.Request.QueryString["thread"].ToString()); 
            string uName = Telerik.Security.UserManager.GetCurrentUserName(); 
            MembershipUser user = Membership.GetUser(uName); 
            Guid userID = new Guid(user.ProviderUserKey.ToString()); 
            string eMail = user.Email; 
            // subscribe this user  
            ForumSubscriptionDataContext dataContext = new ForumSubscriptionDataContext(); 
            ForumSubscriber newSubscriber = new ForumSubscriber(); 
            newSubscriber.ThreadID = ThreadID; 
            newSubscriber.UserID = userID; 
            newSubscriber.UserEmail = eMail; 
            dataContext.ForumSubscribers.InsertOnSubmit(newSubscriber); 
            dataContext.SubmitChanges(); 
            subscriptionMessage.Text = "<span style=background-color:Green;>YOU HAVE BEEN SUCCESSFULLY SUBSCRIBED</span>"
        } 
    } 
 

 

 ~/Sitefinity/ControlTemplates/Forums/EditPost.ascx -  I use this template to get the newly added content and all previous posts and send an emil to the subscribed user. Here I created a code behind of the template and on Page_Load I subscribed for save button click.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Data.Linq; 
using System.Web; 
using System.Web.UI; 
using System.Web.UI.WebControls; 
using Telerik.Forums.WebControls; 
using Telerik.Forums; 
using Telerik.Security; 
using System.Web.Security; 
using Telerik.Web.UI; 
using System.Net.Mail; 
using System.Collections; 
using Telerik.Forums.Data; 
 
public partial class Sitefinity_ControlTemplates_Forums_EditPost : System.Web.UI.UserControl 
    protected void Page_Load(object sender, EventArgs e) 
    { 
        this.saveButton.Click += new EventHandler(saveButton_Click); 
    } 
 
    void saveButton_Click(object sender, EventArgs e) 
    { 
        if (!String.IsNullOrEmpty(HttpContext.Current.Request.QueryString["mode"]) && !String.IsNullOrEmpty(HttpContext.Current.Request.QueryString["thread"])) 
        { 
            // get the thread ID. 
            Guid ThreadID = new Guid(HttpContext.Current.Request.QueryString["thread"].ToString()); 
            ForumSubscriptionDataContext dataContext = new ForumSubscriptionDataContext(); 
            string uri = HttpContext.Current.Request.Url.ToString(); 
            // get our subscriber 
            var query = from sub in dataContext.ForumSubscribers 
                        where sub.ThreadID == ThreadID 
                        select sub.UserEmail; 
            // send email to our subscriber that there is a new post 
            foreach (var email in query) 
            { 
                MailMessage message = new MailMessage("yourhost@here.com", email); 
                message.IsBodyHtml = true
                message.Body = "<b>ThreadConversation</b>:" + tbQuote.Content + "<b>LastReply is:</b>" + editor.Content + "<br />" + "<i>Click the link below to reply</i>" + "<p>" + uri; 
                message.From = new MailAddress("yourhost@here.com"); 
                message.Sender = new MailAddress("yourhost@here.com"); 
                SmtpClient client = new SmtpClient(); 
                client.Send(message); 
            } 
            dataContext.Dispose(); 
        } 
    } 
 

The Progress Team