+1-888-365-2779
Try Now
More in this section

Forums / General Discussions / Workflow and Page Approval Notifications/emails

Workflow and Page Approval Notifications/emails

13 posts, 0 answered
  1. Kim Harris
    Kim Harris avatar
    2 posts
    Registered:
    16 Apr 2009
    28 Jan 2009
    Link to this post
    After reading the knowledge base article for notifying "approvers" when a news feed is updated, I needed my site to update "approvers" when a page is updated. I saw scattered pieces throughout the telerik forums, but no good answers, hence this post... To notify the approvers role, go to the following page: 

    SiteFinity\Admin\ControlTemplates\Pages\PageViewer.ascx

    and add the following to the 1st line:

    <%@ Control Language="C#" AutoEventWireup="true" CodeFile="PageViewer.ascx.cs" Inherits="Sitefinity_Admin_ControlTemplates_Pages_PageViewer" %>


    Create a code behind file called, "PageViewer.ascx.cs" here:

    SiteFinity\Admin\ControlTemplates\Pages\

    and use the code below. If nobody is assigned as an "approver", I'm sending the notification to the administrator. Also, please note that I wrote this code against SiteFinity v3.5.

    using System; 

    using System.Web.UI.WebControls; 

    using Telerik.Workflow; 

    using System.Collections.Generic; 

    using Telerik.Workflow.WebControls; 

    using Telerik.Cms.Engine; 

    using System.Net.Mail; 

     

    public partial class Sitefinity_Admin_ControlTemplates_Pages_PageViewer : System.Web.UI.UserControl 

        protected void Page_Load(object sender, EventArgs e) 

        { 

            workflow.Command += new CommandEventHandler(PageWorkflowMenu_Command); 

        } 

     

        void PageWorkflowMenu_Command(object sender, CommandEventArgs e) 

        { 

            WorkflowInstance workflow = ((WorkflowMenu)sender).GetWorkflow(); 

            if (workflow != null

            { 

                List<EventActivity> commands = new List<EventActivity>(); 

                this.LoadCommands(commands, workflow.Activity.Activities); 

                int idx = int.Parse((string)e.CommandArgument); 

     

                // The workflow events you could handle are: SendForApproval, Approve, Decline, Publish 

                if ((commands.Count > idx) && (commands[idx].CommandName.Equals("SendForApproval"))) 

                { 

                    // Getting currently modified content and format the message 

                    Telerik.Cms.CmsManager manager = new Telerik.Cms.CmsManager();

                    Telerik.Cms.ICmsPage page = manager.Provider.GetPageByWorkflow(workflow.ID);

     

                    //Build message to send

                    string message = String.Format("'{0}' page has been sent for approval\n\n{1}", page.MenuName, ResolveProtocol() + Request.Url.Host + FixupUrl(page.StaticUrl)); 

                    MailMessage mailMsg = new MailMessage(); 

     

                    // From - Not needed if specified in web.config

                    //MailAddress mailAddress = new MailAddress(""); 

                    //mailMsg.From = mailAddress; 

     

                    // Subject and Body  

                    mailMsg.Subject = "Web page pending approval"

                    mailMsg.Body = message; 

     

                    // To 

                    string approversRole = "Approver"

                    string[] usernames = Telerik.Security.UserManager.Default.GetUsersInRole(approversRole); 

     

                    //If there's not an approver, then send it to the administrator.

                    if(usernames.Length == 0)

                        usernames = Telerik.Security.UserManager.Default.GetUsersInRole("administrators");

     

                    foreach (string username in usernames) 

                    { 

                        System.Web.Security.MembershipUser user = Telerik.Security.UserManager.Default.GetUser(username); 

                        mailMsg.To.Add(user.Email); 

                    } 

     

                    // Init SmtpClient and send  

                    SmtpClient smtpClient = new SmtpClient(); 

                    smtpClient.Send(mailMsg); 

                } 

            } 

        }

        /// <summary>

        /// Converts an ASP.NET tilda (~) based URL into a usable client URL.

        /// </summary>

        /// <param name="url"></param>

        /// <returns></returns>

        public static string FixupUrl(string url)

        {

            if (url != null && url.Length > 0 && url[0].Equals('~'))

                return (System.Web.HttpContext.Current.Request.ApplicationPath + url.Substring(1)).Replace("//", "/");

            else

                return url;

        }

        /// <summary>

        /// Returns SSL protocol string.

        /// </summary>

        /// <param name="url"></param>

        /// <returns></returns>

        public static string ResolveProtocol()

        {

            string protocol = System.Web.HttpContext.Current.Request.ServerVariables["SERVER_PORT_SECURE"];

            return (protocol == null || protocol.Equals("0")) ? "http://" : "https://";

        }

        private void LoadCommands(List<EventActivity> commands, IList<Activity> activities) 

        { 

            foreach (Activity act in activities) 

            { 

                if (act is EventActivity

                    commands.Add((EventActivity)act); 

                this.LoadCommands(commands, act.Activities); 

            } 

        } 

     



     

  2. Kim Harris
    Kim Harris avatar
    2 posts
    Registered:
    16 Apr 2009
    28 Jan 2009
    Link to this post
    I added some more logic to this notification workflow.
    • Send email to “approver” upon author approval
    • Send email to “Author” upon an approver’s “decline” action stating that they need to make some modification
    • Send email to “publisher” upon approver’s “Approve” action and CC:\\ the original author

    You can view and download the code here.


  3. Georgi
    Georgi avatar
    3583 posts
    Registered:
    28 Oct 2016
    29 Jan 2009
    Link to this post
    Hi Sam Stange,

    Thank you for posting the solution in our forums and your blog. This seems like a good thing to have.

    We have updated your account for this.

    Regards,
    Georgi
    the Telerik team

    Check out Telerik Trainer, the state of the art learning tool for Telerik products.
  4. clayman
    clayman avatar
    38 posts
    Registered:
    23 Sep 2009
    09 Oct 2009
    Link to this post
    Thanks for posting this - it's going to definitely help streamline the content publishing process.

    Something that I would also like to do is provide a direct link back into the "All Pages" view of the sitemap in the Sitefinity admin tool - with the proper filter applied.  So for example, if the content was declined, then the view only pages with status "Declined" filter would be applied on the PageViewer and they'd be able to delve right into edit mode.  Similarly, a content approver would get linked into the "For Approval" filtered view, and so on.

    View only pages with status: Draft | For Approval | Declined | Approved | Published | Archived or View all 

    Any idea how to achieve this - could I pass the filter on the query string and trigger the filter event on the page viewer?

    thanks!


  5. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    09 Dec 2016
    09 Oct 2009
    Link to this post
    Hello clayman,

    Below is a sample implementation that illustrates getting the current page by ID, getting the wokflow status, creating a new link.

    public partial class Sitefinity_Admin_ControlTemplates_Pages_PageViewer : System.Web.UI.UserControl
    {
        protected void Page_Load(object sender, EventArgs e)
        {
     
        }
     
        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            CmsManager manager = new CmsManager();
            Guid pageID = ((Telerik.Cms.Web.UI.PageEditor)(this.Parent.Parent.Parent.Parent.Parent.Parent)).SelectedPageId;
            ICmsPage currentPage = (ICmsPage)manager.GetPage(pageID, true);
            WorkflowInstance wInstance = currentPage.GetWorkflow();
            PageWorkflow activity = (PageWorkflow)wInstance.Activity;
            if (activity.ApprovalStatus == ApprovalStatus.Declined)
            {
                HyperLink link = new HyperLink();
                link.Text = activity.ApprovalStatus.ToString();
                //IMPLEMENT FILTERING HERE
                link.NavigateUrl = "~/sitefinity/admin/pages.aspx";
                Controls.Add(link);
            }
     
        }
    }

    You should add the logic to PageViewer.ascx code behind. The template( you need to convert it to control) can be found under Sitefinity/Admin/ControlTempalates/Pages. You should also implement logic for filtering the Grid.

    Regards,
    Ivan Dimitrov
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
  6. Laura
    Laura avatar
    311 posts
    Registered:
    25 Feb 2008
    05 May 2010
    Link to this post
    I am using a combination of code from here and here on DOTNETSAM (thanks Sam) and it is working great.

    One problem I have is that I am not getting the email generated upon Publish for some reason.  Is there another way that the status of Publish needs to be read or something???
    Thank you.

    Here is how the workflow item is generated:
    void PageWorkflowMenu_Command(object sender, CommandEventArgs e)
       {
           WorkflowInstance workflow = ((WorkflowMenu)sender).GetWorkflow();
           if (workflow != null)
           {
               List<EventActivity> commands = new List<EventActivity>();
               this.LoadCommands(commands, workflow.Activity.Activities);
               int idx = int.Parse((string)e.CommandArgument);
     
              if (commands.Count > idx)
               {


    And below the case for Publish:
    if (commands.Count > idx)
    {
        // Getting currently modified content and format the message 
        Telerik.Cms.CmsManager manager = new Telerik.Cms.CmsManager();
       Telerik.Cms.ICmsPage page = manager.Provider.GetPageByWorkflow(workflow.ID);
     
        Guid pageID = ((Telerik.Cms.Web.UI.PageEditor)(this.Parent.Parent.Parent.Parent.Parent.Parent)).SelectedPageId;
        Telerik.Cms.ICmsPage currentPage = (Telerik.Cms.ICmsPage)manager.GetPage(pageID, true);
     
     
        //Build message to send
        MailMessage mailMsg = new MailMessage();
     
        //Retrieve the author of the draft.
        Int32 numrows;
        IList<Telerik.Cms.IStagedPage> hist = page.GetHistory(page.Version, 1, out numrows);
     
        switch (commands[idx].CommandName)
        {
            case "SendForApproval":
                ...
               break;
            case "Approve":
                ...
                break;
            case "Decline":
                ...
                break;
     
            case "Publish":
     
               //Retrieve approvers in marketing role
                string[] Marketing = Telerik.Security.UserManager.Default.GetUsersInRole("marketing");
     
                //If there's not an publisher, then send it to the administrator.
                if (Marketing.Length == 0)
                    Marketing = Telerik.Security.UserManager.Default.GetUsersInRole("administrators");
     
                // Add the recipients to message.
                foreach (string username in Marketing)
                {
                    System.Web.Security.MembershipUser user = Telerik.Security.UserManager.Default.GetUser(username);
                    mailMsg.To.Add(user.Email);
                }
                // From: current user
                mailMsg.From = new MailAddress(Telerik.Security.UserManager.Default.GetUser(Telerik.Security.UserManager.GetCurrentUser().Identity.Name).Email);
     
     
                mailMsg.Subject = "Page Published";
                mailMsg.Body = String.Format("'{0}' page has been Published.\n{1}", page.MenuName, ResolveProtocol() + Request.Url.Host + FixupUrl(page.StaticUrl));
     
               break;
        }




  7. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    09 Dec 2016
    05 May 2010
    Link to this post
    Hello Laura,

    You could create a custom Workflow service that is called by your custom PageWorkflow. You could initialize the workflow service in Application_Start of your Global.asax You should use the custom workflow service for sending emails

    sample

    CustomPageWorkflow

    protected override void LoadActivities()
    {
     
     callMethod = Activity.Load<CallExternalMethodActivity>(base.Transaction);
     callMethod.InterfaceType = typeof(MailWorkflowService);
     callMethod.MethodName = "SendEmail";
     callMethod.Parameters = new object[] { base.ItemId, setStatus.ApprovalStatus };
     eventActivity.AddActivity(callMethod);
     
     }

    MailingWebSerivice

    public class MailWorkflowService
    {
        public MailWorkflowService()
        {
           // add the service here
        }
      
        public void SendEmail(Guid workflowId, ApprovalStatus status)
        {
           // create SMTP client and call GetPageByWorkflow for the current ICmsPage object
            switch (status)
            {
            }
         }
    }


    Sincerely yours,
    Ivan Dimitrov
    the Telerik team

    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
  8. Laura
    Laura avatar
    311 posts
    Registered:
    25 Feb 2008
    05 May 2010
    Link to this post
    Thank you Ivan.

    What about this example? (I am using 3.7 SP1)
    How to notify roles that a page has been sent through workflow

    Is that is a valid way of doing this then I have a question:

    It says that to send email notifications for when the Page is published do this:
        public EmailActivity() { Status = ApprovalStatus.Published;} 
     But what if you want the notification to be emailed for all workflow statuses?
  9. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    09 Dec 2016
    05 May 2010
    Link to this post
    Hello Laura,

    You should create a service as suggested in the previous reply.

    Regards,
    Ivan Dimitrov
    the Telerik team

    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
  10. Laura
    Laura avatar
    311 posts
    Registered:
    25 Feb 2008
    05 May 2010
    Link to this post
    Thank you. Just so I can understand could you possibly explain why the case="Publish" is not being hit (in the code I previously pasted)?
  11. Kieran
    Kieran avatar
    56 posts
    Registered:
    14 Aug 2008
    20 Oct 2010
    Link to this post
    Hi

    I don't follow what you mean by "You could create a custom Workflow service that is called by your custom PageWorkflow"

    Can you tell me where exactly to put the code.

    I implement the other option and it all works bar the publish event"


    I'm using SF 3.7
    thanks
    Kieran

  12. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    09 Dec 2016
    20 Oct 2010
    Link to this post
    Hi Kieran,

    There are several ways to initialize a custom workflow

    - Application_Start of Global.asax
    - Inside CreateChildControls of a view that is part of custom module
    - Cms provider declared inside <cms> section of the web.config by using pageWorkflowType

    <add connectionStringName="DefaultConnection" pageWorkflowType="CustomPageWorkflow" allowPageHistory="true"
              allowPageWorkflow="true" cachingProviderName="ASPNET" name="Sitefinity"
              type="Telerik.Cms.Data.DefaultProvider, Telerik.Cms.Data" />


    Sincerely yours,
    Ivan Dimitrov
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  13. AA
    AA avatar
    28 posts
    Registered:
    19 Jul 2012
    23 Jul 2012
    Link to this post
    Hi,

    Please help me.
    I want to create a work flow in which when a user logged in is a designer, he can design templates. If the user is an editor, he can create pages by the created templates. After that the page needs approval from admin. If the page is approved, it can be viewed on live site. Otherwise it should be resend to editor. He has to modify it and can send again for approval.

    Please help me. I don't know from where I have to start and how can I manage it. Where and in which folder I can create .aspx pages which will help to check the logged in users and redirecting to corresponding pages. 


    I want to know is there any options in sitefinity for creating a flow like this or I have to code for this.

    Its an urgent requiremqnt. Im a new comer in this. Please help me..
     
    Since I cant create new files (.aspx, .ascx, .cs,... etc) in the downloaded website and I cant edit web.config file also. Please anyone help me from the base..    
Register for webinar
13 posts, 0 answered