Tuesday, March 30, 2010

Telerik Editor Issue When Overriding Page Render Method

Telerik RAD Editor is used in one SharePoint WCM site. To include Flash objects and scripts inside RAD Editor, I did following steps:
1. Add "<tool name='FlashManager' />" to Editor configuration file in C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\wpresources\RadEditorSharePoint\5.5.1.0__1f131a624888eeed\ToolsFile.xml. This ensures the flash manager icon is available in edit window. Options for adding this setting:
2. Update all RADEditor field controls in page layout from:
<telerik:RadHtmlField id="RadHtmlField1" FieldName="fieldName" runat="server" CssClass="telerikeditor" ></telerik:RadHtmlField>

To:

<telerik:RadHtmlField id="RadHtmlField1" FieldName="fieldName" runat="server" CssClass="telerikeditor" AllowScripts="true" AllowSpecialTags="true"></telerik:RadHtmlField>

This makes scripts and special tags (such as flash <object> tag) legal inside RADEditor.

But the scripts and flash content were not showing. The source html shows something like:
<pre style="display:none" id=RadEditorEncodedTag>....</pre>

I googled and couldn't see a fix about this issue. So I used reflector to find out how Telerik does under the hood. And I figured out that RAD Editor stores non-standard tags like flash objects and scripts in following format:
<pre style="display: none;" id="RadEditorEncodedTag">Base64codingObjects</pre>

RADEditor field Control will decode it during render cycle:
protected override void RenderFieldForDisplay(HtmlTextWriter output)
{
if (!string.IsNullOrEmpty((string) this.ItemFieldValue))
{
bool canCacheResults = true;
string html = HtmlEditorInternal.ConvertStorageFormatToViewFormat(
(string) this.ItemFieldValue, out canCacheResults);
output.Write(EditorTools.UnEscapeSpecialTags(html));
}
}
The problem is that Render Method is overridden in the custom page layouts, and this RenderFieldForDisplay is not invoked. I then added such decoding logic to the overridden Render method:
        protected override void Render(HtmlTextWriter writer)
{
//...
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
HtmlTextWriter ourWriter = new HtmlTextWriter(sw);
base.Render(ourWriter);
string writeString = EscapeRADEditorTags(sb.ToString());
Response.Write(writeString);
//...
}

private static string EscapeRADEditorTags(string html)
{
try
{
MatchEvaluator evaluator = new MatchEvaluator(DecodeMatchManually);
return Regex.Replace(html,
"<pre\\s+(style=\"display\\s*:none\"\\s*)?id=\"?RadEditorEncodedTag\"?[^>]*>([^<]+)</pre>",
evaluator, RegexOptions.ECMAScript | RegexOptions.Multiline | RegexOptions.IgnoreCase);
}
catch (Exception ex)
{
Logger.LogException(ex);
return html;
}
}
Everything works properly after this code change.

Monday, March 22, 2010

HttpModule Blocks SharePoint Designer Issue

A HttpModule is added to a SharePoint publishing site. Every thing works fine except that SharePoint designer is not able to open the SharePoint site. After tracing the html traffic, I noticed some communication patterns between SharePoint designer and the SharePoint site. So the workaround is to skip all HttpModule actions for those communications. Following code is added inside the HttpModule:
    if ( httpContext.Request.UserAgent.Contains("WebDAV") 
|| httpContext.Request.UserAgent.Contains("MS FrontPage")
|| httpContext.Request.Url.AbsoluteUri.Contains("_vti_"))
{
return;
}
Now SharePoint designer can open the site without any problem. But sometimes the check-out function inside SharePoint designer is disable for some reason. I can not figure out why that happens sometimes but not always.