Content Editor WebPart ControlAdapter

4 minute read

One of our clients had a internet facing website. With this website we had a number of problems because it was deployed to our Internet facing farm with Content Deployment. The problem we had was that the Content Editor Web Part (for the rest of this article I will name it CEWP) does not allow relative URLs but saves the complete URL.

So the Internet site had many URLs in the content editor part the referenced to the internal address that you could not access from the internet. Till a few weeks ago we did not have a solution to this problem till i read a blog post (here). They created a Control Adapter that is run when the content editor web part is on a certain page. I have chosen to write out my complete solution because I found that the other post could have been written with more details on how to create it and how to implement it.

The Control Adapter replaces the URLs of the internal site in the CEWP with "/"  so that it displays a relative URL so that you can use the link on the internet. So what do you need for this solution:

  • A feature for adding a link to Central Administration and also places a browser file in the App_Browser Directory for a certain web application.
  • A application page for saving the URL that has to be saved in the web application properties.
  • A browser file to set the Control Adapter.

First lets make the browser file to set the Control Adapter to the CEWP:

<browsers>
    <browser refID="Default">
        <controlAdapters>
            <adapter controlType="Microsoft.SharePoint.WebPartPages.ContentEditorWebPart" adapterType="CEWPFIX.SharePoint.CEWPFIXAdapter, CEWPFIX.SharePoint, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1e8dcda25bf26f8e" />
        </controlAdapters>
    </browser>
</browsers>

What you do in the browser file is that you assign a Adapter to the Microsoft.SharePoint.WebPartPages.ContentEditorWebPart and that is the CEWPFIXAdapter in the example above.

The next step is to make the Control Adapter. So we created a class file and inherit from the System.Web.UI.Adapters.

using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.Adapters;
using System.IO;
using System.Text.RegularExpressions;
using Microsoft.SharePoint.Administration;
using System.Web.Caching;
using Microsoft.SharePoint;
namespace CEWPFIX.SharePoint
{
    /// <summary> 
    /// ControlAdapter for the Content Editor WebPart 
    /// </summary> 
 ControlAdapter
    {
        /// <summary> 
        /// Constant string for the creation of the cache object 
        /// </summary> 
        private const string AlternateUrls = "AlternateUrls";
        /// <summary> 
        /// Key for the webapplication property 
        /// </summary> 
        private const string FilterUrl = "FilterUrls";
        /// <summary> 
        /// Override the render function off the CEWP 
        /// </summary> 
        /// <param name="writer">HtmlTextWriter write</param> 
        protected override void Render(HtmlTextWriter writer)
        {
            //Create a new stringbuilder 
            StringBuilder sb = new StringBuilder();
            //create a HtmlTextWriter 
            HtmlTextWriter htw = new HtmlTextWriter(new StringWriter(sb));
            //Preform the base Render Method 
            base.Render(htw);
            //Get the output string 
            string output = sb.ToString();
            //Create a list with the alternate access urls 
            List<Uri> alternateUrls = GetAlternateUrls();
            //Read out the list with alternate access urls 
            foreach (Uri alternateUrl in alternateUrls)
            {
                //Replace the url's with / 
                output = output.Replace(alternateUrl.ToString(), "/");
            }
            //write the output to the page 
            writer.Write(output);
        }
        /// <summary> 
        /// Method for retrieving the Alternate Access Urls of retrieving them from the Cache 
        /// </summary> 
        /// <returns></returns> 
        private List<Uri> GetAlternateUrls()
        {
            //Try to retrieve the list from the cache 
            List<Uri> alternateUrls = (List<Uri>)HttpContext.Current.Cache[AlternateUrls];
            //Make sure anonymous users can access the web application properties 
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                //If the list is null recreate the list en put it in the chache 
                if (alternateUrls == null)
                {
                    //Create a new list object 
                    alternateUrls = new List<Uri>();
                    //Retrieve the WebApplication object 
                    SPWebApplication webApp = SPWebApplication.Lookup(HttpContext.Current.Request.Url);
                    if (webApp.Properties.ContainsKey(FilterUrl))
                    {
                        string[] urls = webApp.Properties[FilterUrl].ToString().Split(new char[] { ';' });
                        foreach (string str in urls)
                        {
                            try
                            {
                                Uri url = new Uri(str);
                                alternateUrls.Add(url);
                            }
                            catch (Exception ex)
                            {
                                new ExceptionHandler("Something went wrong while creating a uri in the CEWPFIXAdapter", ex);
                            }
                        }
                    }
                    //Add the list to the cache 
                    HttpContext.Current.Cache.Add(AlternateUrls, alternateUrls, null, DateTime.Now.AddHours(12), Cache.NoSlidingExpiration, CacheItemPriority.Normal, null);
                }
            });
            //return the list with the urls 
            return alternateUrls;
        }
    }
}

This code will make sure the URLs will get the right format.