Verint | Telligent Community
Verint | Telligent Community
  • Site
  • User
  • Site
  • Search
  • User
Verint Community 11.x
  • Verint Community
Verint Community 11.x
Developer Training Page Definition and URL Routing
  • User Documentation
  • Ask the Community
  • API Documentation
  • Manager Training
  • Developer Training
  • Tags
  • More
  • Cancel
  • New
  • +Getting Started
  • +External Integration
  • +Plugins/Framework extension
  • +Automations
  • -UI Customization
    • Anatomy of a Page Request
    • +Themes
    • +Widgets
    • Responsive Design
    • -UI Extensibility
      • Extending the Administration UI
      • Extending the Content Editor
      • Extending the Contextual Management UI
      • Factory Default Widget Providers
      • HTML Headers
      • HTTP Callbacks
      • Page Definition and URL Routing
      • Sockets and Presence
      • Widget Contexts
    • UI Automation
  • +Scripting

Page Definition and URL Routing

Custom functionality may require that URLs be defined that can be referenced by code to enable specific workflows (editing content, viewing content, listing content, etc). New pages can be declared in code at custom routed URLs to provide reliable URLs for specific functionality to custom plugins and UI extensions.

[toc]

Routed Pages vs. Custom Pages

Custom pages are useful for custom UI specific to a single blog, group, or site that is not required as part of a larger application. When a page/URL must exist to enable a workflow, a routed page may be a better option. The table below shows all differences between routed pages and custom pages:

  Routed Pages Custom Pages
Supports parsing the URL into a programmatic context Yes

No

Defined within a specific theme instance (a single blog, group, site, etc) No

Yes

Has a factory default implementation Yes

No

Created in code Yes

No

Created in the user interface No

Yes

Requires /p/ in URL path No

Yes

Defining Site Pages

The INavigable Plugin type is used to define routed site pages.  In addition to the base IPlugin members, INavigable adds the following:

void RegisterUrls(IUrlController controller);

The RegisterUrls method provides a reference to the IUrlController.  The controller allows you to register urls with the platform.

Example 1:  Site Page

The Site Page example will create a blank page at the root of the site with the URL "custom."  For example, if your community URL was  http://mycommunity, the new page would be found at http://community/custom.

Fullscreen 5518.CustomSitePageExample.cs Download
using Telligent.Evolution.Extensibility.Urls.Version1;

namespace Telligent.Evolution.Examples
{
    public class CustomSitePageExample : INavigable
    {
        void INavigable.RegisterUrls(IUrlController controller)
        {
            controller.AddPage("page-custom", "custom", null, null, "page-custom", new PageDefinitionOptions());
        }

        public string Description
        {
            get { return "Define a custom site page"; }
        }

        public void Initialize()
        {
        }

        public string Name
        {
            get { return "Custom Site Page Example"; }
        }
    }
}

We use the controller.AddPage method to add a new widget page.  For additional information on the IUrlController and its methods see the IUrlController documentation.

Example 2: Members Page

The Members page adds a page for each user on the site at http://mycommunity/{username}/custompage.  

Fullscreen 3051.CustomUserPageExample.cs Download
using System;
using System.Web;
using Telligent.Evolution.Extensibility;
using Telligent.Evolution.Extensibility.Api.Version1;
using Telligent.Evolution.Extensibility.Urls.Version1;
using Telligent.Evolution.Extensibility.Version1;

namespace Telligent.Evolution.Examples
{
    public class CustomPageExamples : INavigable, ITranslatablePlugin
    {
        private ITranslatablePluginController _translationController;

        void INavigable.RegisterUrls(IUrlController controller)
        {
            object userNameConstraints = new { UserName = @"^[a-zA-Z0-9\-\._]+$" };

            controller.AddPage("page-members-custom", "members/{UserName}/custompage", null, userNameConstraints, "page-members-custom", new PageDefinitionOptions()
            {
                DefaultPageXml = @"<contentFragmentPage pageName=""page-members-custom"" isCustom=""false"" layout=""Content"" themeType=""0c647246-6735-42f9-875d-c8b991fe739b"">
      <regions>
        <region regionName=""Content"">
          <contentFragments>
            <contentFragment type=""Telligent.Evolution.ScriptedContentFragments.ScriptedContentFragment, Telligent.Evolution.ScriptedContentFragments::796a5296bbb74d24b4113eee9352d431"" showHeader=""False"" cssClassAddition=""no-wrapper with-spacing responsive-1"" isLocked=""False"" configuration="""" />
         </contentFragments>
        </region>
      </regions>
      <contentFragmentTabs />
    </contentFragmentPage>",
                TitleFunction = () => _translationController.GetLanguageResourceValue("page-members-custom"),
                DescriptionFunction = () => _translationController.GetLanguageResourceValue("page-members-custom-description"),
                ParseContext = ParseUserContext
            });
        }

        private void ParseUserContext(PageContext context)
        {
            var userName = context.GetTokenValue("UserName");

            if (userName != null)
            {
                var usersApi = Apis.Get<IUsers>();
                string decodedUserName = PublicApi.Url.DecodeFileComponent(userName.ToString());
                var user = usersApi.Get(new UsersGetOptions() { Username = decodedUserName });

                ContextItem contextItem = null;

                if (user != null && !user.HasErrors())
                {
                    contextItem = new ContextItem()
                    {
                        TypeName = "User",
                        ApplicationId = user.ContentId,
                        ApplicationTypeId = usersApi.ContentTypeId,
                        ContainerId = user.ContentId,
                        ContainerTypeId = usersApi.ContentTypeId,
                        ContentId = user.ContentId,
                        ContentTypeId = usersApi.ContentTypeId,
                        Id = user.Id.ToString()
                    };
                }
                else
                {
                    if (usersApi.AccessingUser.IsSystemAccount.Value)
                    {
                        var url = Apis.Get<ICoreUrls>().LogIn(new CoreUrlLoginOptions() { ReturnToCurrentUrl = true });
                        HttpContext.Current.Response.Redirect(url);
                    }
                    else
                    {
                        throw new CustomException(String.Format(_translationController.GetLanguageResourceValue("UserNotFoundException"), decodedUserName));
                    }
                }

                if (contextItem != null)
                    context.ContextItems.Put(contextItem);
            }
        }

        Translation[] ITranslatablePlugin.DefaultTranslations
        {
            get
            {
                var t = new Translation("en-us");

                t.Set("page-members-custom", "Sample User Page");
                t.Set("page-members-custom-description", "Shows a page at the url members/{username}/custompage.");
                t.Set("UserNotFoundException", "User {0} not found.");

                return new Translation[] { t };
            }
        }

        public void SetController(ITranslatablePluginController controller)
        {
            _translationController = controller;
        }

        public string Description
        {
            get { return "Define a custom user page"; }
        }

        public void Initialize()
        {
        }

        public string Name
        {
            get { return "Custom User Page Example"; }
        }
    }

    public class CustomException : Exception, Telligent.Evolution.Extensibility.Version1.IUserRenderableException
    {
        public CustomException() { }
        public CustomException(string message) : base(message) { }

        public string GetUserRenderableMessage()
        {
            return this.Message;
        }
    }
}

In this example the Url parameter is defined as "members/{UserName}/custompage", the  new { UserName = @"^[a-zA-Z0-9\-\._]+$" } constraint has also been applied to the UserName variable.  The Url will only respond if the requested Url matches the format and constraints that are defined when adding the page.

The example also uses some of the options available in the PageDefinitionOptions parameter.  DefaultPageXml is used to define the factory default set of widgets for this page.  The TitleFunction and DescriptionFunction options determine the page's name and description when working with the page in the theme editing panels.  ParseContext defines the method that is used to examine the Url and determine what item are in context for this page.  

The ParseContext method in the example performs a few functions.  First we attempt to load the username from the URL.  If it's valid, we add that user to the page's ContextItems collection. This in turn enables other methods in the platform.  For instance, having a user in the ContextItems collection allows the $core_v2_user.Current velocity call to return that user.  If the user is not valid we either redirect the user to login to the site if they are not currently logged in or we throw an exception identifying the username to be invalid.

Defining Application Pages

The IApplicationNavigable Plugin type is used to extend existing applications (and groups) by adding new routed pages.  In addition to the base IPlugin members, IApplicationNavigable adds the following:

void RegisterUrls(IUrlController controller);

The RegisterUrls method provides a reference to the IUrlController.  The controller allows you to register urls with the platform.

Guid ApplicationTypeId { get; }

The ApplicationTypeId property specifies which application type will display the new page. 

Example 3: Blog Raw Page

This sample adds a url to a blog that is handled by an IHttpHandler.  The page defined in the sample would have the following URL pattern: http://community/{grouppath}/{b}/{blogappkey}/raw.

Fullscreen 5127.CustomBlogRawExample.cs Download
using System;
using System.Linq;
using System.Web;
using Telligent.Evolution.Extensibility;
using Telligent.Evolution.Extensibility.Api.Version1;
using Telligent.Evolution.Extensibility.Urls.Version1;

namespace Telligent.Evolution.Examples
{
    public class CustomBlogRawExample : IApplicationNavigable
    {
        Guid IApplicationNavigable.ApplicationTypeId
        {
            get { return Apis.Get<IBlogs>().ApplicationTypeId; }
        }

        void IApplicationNavigable.RegisterUrls(IUrlController controller)
        {
            controller.AddRaw("blog-raw", "{WeblogApp}/raw", null, null,
               (a, p) =>
               {
                   var handler = new CustomBlogRawHttpHandler();
                   handler.ProcessRequest(a.ApplicationInstance.Context);
               }, new RawDefinitionOptions() { ParseContext = ParseBlogContext });
        }

        private void ParseBlogContext(PageContext context)
        {
            var appKey = context.GetTokenValue("WeblogApp");
            var blogsApi = Apis.Get<IBlogs>();
            var groupsApi = Apis.Get<IGroups>();

            if (appKey != null)
            {
                var groupItem = context.ContextItems.GetAllContextItems().FirstOrDefault(a => a.ContentTypeId == groupsApi.ContentTypeId);
                if (groupItem != null)
                {
                    var blog = blogsApi.Get(new BlogsGetOptions() { GroupId = int.Parse(groupItem.Id), Key = appKey.ToString() });
                    if (blog != null)
                    {
                        var contextItem = new ContextItem()
                        {
                            TypeName = "Blog",
                            ApplicationId = blog.ApplicationId,
                            ApplicationTypeId = blogsApi.ApplicationTypeId,
                            ContainerId = blog.Group.ApplicationId,
                            ContainerTypeId = groupsApi.ContentTypeId,
                            ContentId = blog.ApplicationId,
                            ContentTypeId = blogsApi.ApplicationTypeId,
                            Id = blog.Id.ToString()
                        };

                        context.ContextItems.Put(contextItem);
                    }
                }
            }
        }

        public string Description
        {
            get { return "Define custom blog raw url"; }
        }

        public void Initialize()
        {
        }

        public string Name
        {
            get { return "Custom Blog Pages"; }
        }
    }

    public class CustomBlogRawHttpHandler : IHttpHandler
    {
        public bool IsReusable
        {
            get { return false; }
        }

        public void ProcessRequest(HttpContext context)
        {
            var blog =
                PublicApi.Url.CurrentContext.ContextItems.GetAllContextItems()
                    .FirstOrDefault(b => b.ContentTypeId == PublicApi.Blogs.ContentTypeId);

            if (blog != null)
            {
                var posts = Apis.Get<IBlogPosts>().List(new BlogPostsListOptions() { BlogId = int.Parse(blog.Id)} );
                foreach (var post in posts)
                    context.Response.Write(post.Title + "<br />");
            } 

            context.Response.End();
        }
    }
}

The URL is defined as {WeblogApp}/raw, since we are adding a page to the blog application, the portion of the URL up to and including the blog application identifier ('/b/') accounted for.  You are only required to define the portion of the url inside the group or application. 

What is the difference between adding a widget page and adding a raw page?

The IUrlController provides the option to add a widget page or a raw page.  A widget page is a themeable page that supports a widget-based layout.  Raw pages give complete control over the output when defining the Url.  The typical use case for raw pages are RSS Feeds, file downloads or Xml.

  • inavigable
  • IApplicationNavigable
  • Share
  • History
  • More
  • Cancel
Related
Recommended
  • Telligent
  • Professional Services
  • Submit a Support Ticket
  • Become a Partner
  • Request a Demo
  • Contact Us

About
Privacy Policy
Terms of use
Copyright 2024 Verint, Inc.
Powered by Verint Community