Aug 07
Build Knowledge Base on SharePoint online

​Finally I've got the next my project - Knowledge Base. The goal of this project is to create a system for collecting and ordering articles which have helped me to solve tasks. I find it useful, as repetition of tasks may cause a long research on the Internet. To build this system I've decided to use my SharePoint Online and have set itself the conditions:

  • Minimal effort of work
  • Easy of use
  • Categorization

On the basis of the requirements I've chosen a simple SharePoint list and have customized its forms to auto populate title, description and url fields. One of the main part of the customization is a Bookmarklet which is an entry point for the adding content (see the picture to understand the whole process).


The user opens a list view of the Knowledge Base and adds bookmarklet link to the bookmark panel of a browser (1,2). Then the user read a page. If he decides to remember the page he can select a text (3) and use the bookmark (4). After this the newform.aspx page is opened with the prepopulated fields (5). The distinctive feature of this process is that the previously selected text is displayed in the description field.

It looks complicated, but the development takes half an hour. First of all, I've added two JavaScript files to the SharePoint Online.

  • The script which is loaded to the page after the bookmark has been clicked
    var desc = document.getSelection();
    var url = "https://sitename/Lists/Knowledge%20Base/NewForm.aspx?title="
+ encodeURI(encodeURI(document.title)) + "&description=" + encodeURI(encodeURI(document.getSelection()))
+ "&url=" + encodeURIComponent(encodeURIComponent(document.location.href));;
  • The script which is added to the newform.aspx
var shnt_clr = shnt_clr || {};

    var self = this;
    this.getQueryStringParameter = function (param) {
        var params = document.URL.split("?")[1].split("&");
        var strParams = "";
        for (var i = 0; i < params.length; i = i + 1) {
            var singleParam = params[i].split("=");
            if (singleParam[0] == param) {
                return singleParam[1];
    this.init = function(ctx){
        if (ctx.ListSchema.Field[0].Name == 'Title'){
            var titleElement = document.querySelector('[id^="Title"][id$="TextField"]');
            titleElement.value = decodeURI(decodeURI(self.getQueryStringParameter('title')));
        if (ctx.ListSchema.Field[0].Name == 'Description'){
            var descElement = document.querySelector('[id^="Description"][id$="TextField_inplacerte"]');
            descElement.innerHTML = decodeURI(decodeURI(self.getQueryStringParameter('description')));
        if (ctx.ListSchema.Field[0].Name == 'URL'){
            var urlElement = document.querySelector('[id^="URL"][id$="UrlFieldUrl"]');
            urlElement.value = decodeURIComponent(decodeURIComponent(self.getQueryStringParameter('url')))
            var urlDescElement = document.querySelector('[id^="URL"][id$="UrlFieldDescription"]');
            urlDescElement.value = decodeURI(decodeURI(self.getQueryStringParameter('title')));

(function () {
    var overrideCtx = {};
    overrideCtx.OnPostRender = shnt_clr.init;


As can you see by the code the first script forms an URL which contains the page title, description and link as parameters and opens this URL in a new tab of the browser. For the script loading the user should use bookmaklet link which has been added to the list view of the knowledge base.

<a href="javascript:(function(){instacalc_script=document.createElement('SCRIPT');

The second script uses CSR for the field filling and have been added as JSLink of ListFormWebPart

<JSLink xmlns="">~site/SiteAssets/KnowledgeBaseForm.js</JSLink>

This simple code facilitates adding of the items to SharePoint Online and I must admit, I use it with enjoyment.

Jul 30
SharePoint fields in the front-end engines

One of the best new features for SharePoint 2013 is Client Side Rendering. It allows us to style SharePoint elements using JavaScript that provides several advantages for us:

  • Performance - rendering is performed on the client side
  • Cross-platform language - web developers are familiar with JavaScript
  • Flexibility - we can apply changes to a single field, entire view or form

These points tell that the field's rendering functions are completely moved to the front-end and we can use them to build complex interfaces based on usage of any JavaScript Temlate Engines. In troth, if you are doing research, you will find a lot of examples which describe how to use JavaScript to initialize OOTB controls. I brought this knowledge together and prepared the presentation with a demo for Belarus SharePoint User Group. This presentation contains a common approach to the use of knockout.js and no special interest, but it is necessary to understand the demo which explains how to initialize and work with the most complex fields:

  • Date time picker
  • People picker
  • Taxonomy picker
  • Custom picker

The sample code for the demo will help you to start your own front-end implementation quickly, so be free to find it on CodePlex.

Jun 16
Syntax Highlighter for SharePoint

I've decided to make a blog on SharePoint online and have faced with code formating issue. OOTB SharePoint controls provide possibility to insert the formatted text, but the function is not supported by all the browsers and the text formatting depends on a source which may lead to ugly look of the blog post. To bring the code to the general form you can use Ribbon. In this case you have to select each word and choose the color for it on the palette. It takes a lot of time, doesn't it? The real solution for this issue can be a third party plugin. I have searched on the Internet and have found SyntaxHighlighter. It is easy for deployment and usage - you should add script links to the master page.

<link href='' rel='stylesheet' type='text/css'/>
<link href='' rel='stylesheet' type='text/css'/>
<script src='' type='text/javascript'></script>
<script src='' type='text/javascript'></script>
<script src='' type='text/javascript'></script>
<script src='' type='text/javascript'></script>
<script src='' type='text/javascript'></script>
<script src='' type='text/javascript'></script>
<script src='' type='text/javascript'></script>
<script src='' type='text/javascript'></script>
<script src='' type='text/javascript'></script>
<script src='' type='text/javascript'></script>
<script src='' type='text/javascript'></script>
<script src='' type='text/javascript'></script>
<script src='' type='text/javascript'></script>
<script language='javascript'>
SyntaxHighlighter.config.bloggerMode = true;
SyntaxHighlighter.config.clipboardSwf = '';

Then you should wrap your code into one of two possible structures

<script type=&quot;syntaxhighlighter&quot; class=&quot;brush: csharp&quot;>
// Comment
public class Test {
public Test() {


<pre class="brush: csharp">
// Comment
public class Test {
public Test() {

After these two steps you can see the result on the page

// Comment
public class Test {
    public Test() {

That is really cool! But every day is not Sunday - first of all, to wrap your code you should use Edit Source button, find the text in the popup window and write structure. It can be difficult when there is a lot of text. Moreover, SharePoint uses <p> tag to shift the text to the next line. This tag is not ignored by SyntaxHighlighter.


I have not found the better plugin for SharePoint thus I had to pull my socks up and make my own plugin under SyntaxHighlighter. This plugin is a sandbox solution which solves the issues described above and can be found on CodePlex as Syntax Highlighter For SharePoint.

Apr 21
SharePoint Apps and custom domain

​If you develop provider or autohosted SharePoint Apps for the public site you deal with access tokens. They work perfectly until you decide to change the site domain to you own. In this case the access denied axception is thrown.

I have been searching solution for a long time and several days ago I was listening Artur Kukharevich's lecture at Belarus SharePoint User Group meetup. He told that SharePoint uses two sets of URLs for the public site:

  1. Internal
    • (host web)
    • (app web)
  2. External (public)
    • (host web)
    • (app web)

Artur explained that while the SharePoint Apps required internal URLs for the access token, in anonymous context they had external URLs only. Therefore developer should make a hack to retrieve correct params and one of the possibilities is to use authentication form. How does it work? We make an http request to the authentication form and use query string to retrieve replay address.

private static string ExtractOriginalUrl(Uri urlFromRequest, bool isHostWeb)
var url = urlFromRequest + (isHostWeb ? "/_layouts/15/Authenticate.aspx" : "");
    HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();

    var originalHostUrl = HttpUtility.ParseQueryString(response.ResponseUri.Query)["wreply"];
    if (string.IsNullOrEmpty(originalHostUrl))
     return string.Empty;
var index = originalHostUrl.IndexOf("_form", StringComparison.InvariantCultureIgnoreCase);
    if (index > 0)
     originalHostUrl = originalHostUrl.Substring(0, index - 1);

    var relativePathFromRequest = urlFromRequest.GetComponents(UriComponents.PathAndQuery, UriFormat.SafeUnescaped)
    var originalUrlServerPath = new Uri(originalHostUrl).GetComponents(UriComponents.SchemeAndServer, UriFormat.SafeUnescaped);

    return string.Format("{0}{1}", originalUrlServerPath, relativePathFromRequest);

private static void EmulateBrowserWebRequest(HttpWebRequest request)
request.Method = "HEAD";
    request.AllowAutoRedirect = true;

    request.Accept = "text/html, application/xhtml+xml, */*";
    request.UserAgent = "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)";

    request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip");
    request.AutomaticDecompression = DecompressionMethods.GZip;
    request.Headers.Add(HttpRequestHeader.AcceptLanguage, "en-US");

    request.Headers.Add(HttpRequestHeader.CacheControl, "max-age=0");

Using these methods we can retrieve internal URLs and correct access tokens.

_internalSPHostUrl = ExtractOriginalUrl(new Uri(SPHostUrl), true);

var lastIndex = SPAppWebUrl.LastIndexOf('/');
var appWebRelativeUrl = SPAppWebUrl.Substring(lastIndex);
_internalSPAppWebUrl = ExtractOriginalUrl(new Uri(_internalSPHostUrl + appWebRelativeUrl), false);

var uri = new Uri(_internalSPAppWebUrl);
var token=TokenHelper.GetAppOnlyAccessToken(TargetPrincipalName,uri.Authority,TokenHelper.GetRealmFromTargetUrl(uri));
using (ClientContext ctx = TokenHelper.GetClientContextWithAccessToken(_internalSPHostUrl, token.AccessToken))

I was trying to find another solution but I wasn't lucky. So if you have thoughts about this issue I will be glad to discuss them.

Special thanks to Artur, he helped me to write this post and provided the example which you can find here.
Mar 11
Posts with OOTB layouts on the home page
I decided to create my own developer blog on SharePoint online with minimal amount of efforts and one of the first thing that I wanted was to display my posts on home page. I added XSLTListViewWebPart to the page but it displayed list view which was not suitable for the main page of the site.

I found a web part that was called Blog Tools. It provided quick links for the blog management and selector for the OOTB layouts. It was nice, because I could use this web part for post's styling. One thing was bad. I could not hide Blog Tools from the user that had permissions to manage blog (the hidden property does not work) and it made the page ugly for them.

The only way that I saw was implementing of a custom page layout which displayed web parts in edit mode only. For this I coppied default layout and added hidden web part zone to the body
<div class="hidden-content">
<WebPartPages:WebPartZone runat="server" AllowPersonalization="false" FrameType="None" ID="HiddenZone"
Title="Hidden" Orientation="Vertical" QuickAdd-GroupNames="Default" QuickAdd-ShowListsAndLibraries="false"/>
Then I added needed styles to PlaceHolderAdditionalPageHead control
<style type="text/css">
<PublishingWebControls:EditModePanel runat="server">
    <style type="text/css">
I configured Blog Tools as I wanted and the next step was to make it work with post's list view. All I need was to set summary view in the web part settings of XSLTListViewWebPart.
Oct 07
SharePoint 2013 workflows in SharePoint-hosted app
When you develop a workflow for the SharePoint-hosted app, you should keep in mind a few things. First of all, If you use OOTB or your own web template for an app, in most cases you will see this exception

@"Error 1
CorrelationId: 9b943d19-b575-4c83-8b53-027ae89241b7
ErrorDetail: There was an error during the operation.
ErrorType: Configuration
ErrorTypeName: Configuration
ExceptionMessage: Operation is not valid due to the current state of the object.
Source: Common
SourceName: Common App Deployment

The MSDN tells:

Do not use the WebTemplate element in the app manifest to designate any of the built-in SharePoint site definition configurations as the app web's site type. We do not support using any of the built-in site definition configurations, other than APP#0, for app webs.

Thus, if you would like to include your workflow to SharePoint-hosted app, you have to use APP#0 template.

secondly, if you are not a citizen of USA, you may localize your app. It's simple while you do not work with the host web elements (like web parts). You can find the solution which uses the AddRelsToAppPackage application, but this application breaks an app package in case the app contains a workflow. You will see this exception:

Error occurred in deployment step 'Install app for SharePoint': File contains corrupted data.

Artur Kukharevich found out the problem. The AddRelsToAppPackage applicationuses ZipArchive class of .net framework which removes empty files from a zip file, but leaves a reference to the files in the zip definition.We used dotPeek to decompile AddRelsToAppPackage application, copied Main method to our new application and add a new line to empty files.

foreach (ZipArchiveEntry source in zipArchive.Entries)
     if (source.FullName.StartsWith("_rels/feature", StringComparison.OrdinalIgnoreCase) &&
source.FullName.EndsWith(".xml.rels", StringComparison.OrdinalIgnoreCase))

     else if (source.Length == 0)
           using (StreamWriter streamWriter = new StreamWriter(source.Open()))
     //end of fix.
This solution works fine for us, and, I hope, will work for you. Good luck!
May 22
Duplicate validation messages of a rich text box

​For some reason the SharePoint shows duplicate validation messages for a rich text box.


I haven't found solution on the Internet and had to create own fix. I found out that these validation messages have different markup.

<span class="ms-formvalidation">
    <span role="alert">You mus specify a value for this required field.</span>

<span class="ms-formvalidation" role="alert">You mus specify a value for this required field.</span>
After this I made a research and desided to hide second span
.ms-formvalidation[role="alert"] { display: none; }
Apr 01
Change default text of SmallSearchInputBox

Sometimes you have the requirements to change default text of a search box for one site collection in your farm. The good news for you - it can be done with delegate control. There is a declaration in the SharePoint:

<Elements xmlns="">
<Control Id="SmallSearchInputBox" Sequence="50" ControlClass="Microsoft.SharePoint.Portal.WebControls.SearchBoxEx"
ControlAssembly="Microsoft.Office.Server.Search, Version=, Culture=neutral,PublicKeyToken=71e9bce111e9429c">
<Property Name="GoImageUrl">/_layouts/images/gosearch15.png</Property>
<Property Name="GoImageUrlRTL">/_layouts/images/gosearchrtl15.png</Property>
<Property Name="GoImageActiveUrl">/_layouts/images/gosearchhover15.png</Property>
<Property Name="GoImageActiveUrlRTL">/_layouts/images/gosearchrtlhover15.png</Property>
<Property Name="DropDownMode">ShowDD</Property>
<Property Name="SearchResultPageURL">/_layouts/osssearchresults.aspx</Property>
<Property Name="ScopeDisplayGroupName"></Property>
<Property Name="FrameType">None</Property>
All you need is to create a feature and add a new delegate control declaration, copy the default declaration and add this line of code:
<Property Name="QueryPromptString">New default text</Property>

If you need to localize this string you can use Resources. For this you should use these steps:
  1. Add resources mapped folder to you project
  2. Add resources files for each culture
  3. Use $Resources taken in the control declaration
<Property Name="QueryPromptString">$Resources:filename,key</Property>
Now the search box displays text in the language that is default for the current web. But this solution does not work if the user can change UI culture and this text should be changed dynamicaly.


In this case my solution is to add a class to the project, inherit it from SearchBoxEx class
and override QueryPromptString property.
public classSearchBox : SearchBoxEx
public new string QueryPromptString
return base.QueryPromptString;
string fullKey = string.Format("$Resources:{0}", value);
base.QueryPromptString = SPUtility.GetLocalizedString(fullKey, null,
Then add these changes in the declaration of delegate control:
1. <Control ControlClass="LocalizedSearch.SearchBox"                        
ControlAssembly="LocalizedSearch, Version=, Culture=neutral, PublicKeyToken=71df3f77c17b7c69">

2. <Property Name="QueryPromptString">filename,key</Property>

I hope this topic will be helpful.
Dec 12
SharePoint 2013 Preview. Field templates issue.
I faced with issue on custom new form of a list. This form had controls going page postbacks. After each postback the fields of boolean and note types are cleared. My first thought was the ViewState of contols is disabled, I thought so because one of the recommendation of the best practices is to disable ViewState if it is possible. After a while I have found out that the ViewState is enabled in all needed controls, but I have also found that the user controls for the fields do not have any value. My research has led me to the article that has good explanation how to create your own field and how new field templates work. In this article I saw that fields use JSLink property to store information about js file for rendering templates. This file is clientforms.js which is located in C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\TEMPLATE\LAYOUTS.

Template for boolean field retrieves data from client context by GetFormContextForCurrentField method of SPClientTemplates.Utility object and then use this data to set value of a field.
var _myData = SPClientTemplates.Utility.GetFormContextForCurrentField(rCtx);
var _value = _myData.fieldValue != null ? _myData.fieldValue : '0';
var _checked = Boolean(Number(_value)) ? 'checked="checked"' : '';
The _myData.fieldValue was 0 each times as the templates called, thus I was suspecting that the problem in context initialization. But was wrong. I have found that there is a method to update control state on value changed event.
function OnValueChanged() {
if (_inputElt != null)
    _myData.updateControlValue(_myData.fieldName, GetCheckBoxValue());
This method is never invoked, because event binding is not correct.
AddEvtHandler(_inputElt, "onchange", GetCheckBoxValue());
It should be
AddEvtHandler(_inputElt, "onchange", OnValueChanged());
I modified AddEvtHandler, restarted IIS and refreshed the page. It solved a issue with boolean field.

After this I knew what should I looking for in template for note field. I opened template and didn't find event binding. I think that it doesn't exist because control that stores current text for note field is a div element. It's difficult to handle changes in it, thus I decided to write my ouwn and use on lose focus event for this purpose.

AddEvtHandler(_textAreaRte, "onblur", OnEnhancedRichTextValueChanged);

function OnEnhancedRichTextValueChanged() {
if (_textAreaRte != null)
    _myData.updateControlValue(_myData.fieldName, GetEnhancedRichTextControlValue());
You can look at my changes here, but I don't recommend you to use this approach because this file is OOTB file of SharePoint and it can be rewrited by SharePoint updates. Instead of it I recommend to use REST api or CSOM and jQuery to performe data on New/Edit form of a list without postbacks.
Apr 05
Cross Site Collection Navigation

Several days ago I thought how to show quick launch menu from a specific site. The main problem was in web application's structure. There was logical distinction between site collections. Some of them had to play a role of parent, other had to be its child. So, my task was to show menu from current site and its parent site collection.

SharePoint Server 2010 provides coolest functionality for the site navigation managment. If you activate Publishing feature, in Site Settings you can find a new menu which is called "Navigation" (Look and Feel section). There is an option that configures which items should be displayed in your current site navigation (quick launch menu). But this option works only with the webs that are in the same site collection.


In case of cross collection site navigation you should investigate how this feature works and how can you reuse this functionality in your approach.

First of all, lets look at the master page markup and find out how quick launch menu is rendered.

<Sharepoint:SPNavigationManager id="QuickLaunchNavigationManager" runat="server" ContainedControl="QuickLaunch"
QuickLaunchControlId="QuickLaunchMenu" EnableViewState="false" CssClass="ms-quicklaunch-navmgr">
        <SharePoint:DelegateControl runat="server" ControlId="QuickLaunchDataSource">
                <asp:SiteMapDataSource SiteMapProvider="SPNavigationProvider" ShowStartingNode="False"
id="QuickLaunchSiteMap" StartingNodeUrl="sid:1025" runat="server" />
        <SharePoint:UIVersionedContent UIVersion="3" runat="server">
                <SharePoint:AspMenu id="QuickLaunchMenu" runat="server" DataSourceId="QuickLaunchSiteMap"
Orientation="Vertical" StaticDisplayLevels="2" ItemWrap="true" SkipLinkText=""
MaximumDynamicDisplayLevels="0" StaticSubMenuIndent="0" CssClass="s4-die">
                        <asp:menuitemstyle CssClass="ms-navheader" />
                        <asp:menuitemstyle CssClass="ms-navitem" />
                        <asp:submenustyle CssClass="ms-navSubMenu1" />
                        <asp:submenustyle CssClass="ms-navSubMenu2" />
                        <asp:menuitemstyle CssClass="ms-selectednavheader" />
                        <asp:menuitemstyle CssClass="ms-selectednav" />
        <SharePoint:UIVersionedContent UIVersion="4" runat="server">
                <SharePoint:AspMenu id="V4QuickLaunchMenu" runat="server" EnableViewState="false" CssClass="s4-ql"
DataSourceId="QuickLaunchSiteMap" UseSimpleRendering="true"UseSeparateCss="false"
Orientation="Vertical" StaticDisplayLevels="2" MaximumDynamicDisplayLevels="0"
The most interesting part of this markup is a delegate control definition.
<SharePoint:DelegateControl runat="server" ControlId="QuickLaunchDataSource">
<asp:SiteMapDataSource SiteMapProvider="SPNavigationProvider" ShowStartingNode="False"
id="QuickLaunchSiteMap" StartingNodeUrl="sid:1025" runat="server" />
It means that the data source of quick launch menu can be changed by a feature. If you go to 14\TEMPLATE\FEATURES\Navigation\NavigationSiteSettings.xml, you can find that the Publising feature has a definition of QuickLaunchDataSource delegate control and this control is used as the data source for our menu.
<Control Id="QuickLaunchDataSource" Sequence="50" 
<Property Name="ID">QuickLaunchSiteMap</Property>
<Property Name="SiteMapProvider">CurrentNavigation</Property>
<Property Name="EnableViewState">false</Property>
<Property Name="StartFromCurrentNode">true</Property>
<Property Name="ShowStartingNode">false</Property>
<Property Name="TrimNonCurrentTypes">Heading</Property>
Now you know which markup and data source you should to reuse. But it is not pretty easy. The reason of this in PortalSiteMapDataSourceSwitch object. This object uses provider that is retrieves data which depends on HttpContext.Current. So if you wish to get quick launch menu from another site collection you should change current http context. Let's do it!

Open Visual Studion 2010 and choose Visual Web Part Template. Actually, we need to create a control that should be added to the master page, but in case of web part we can easily deploy it to any site for testing. Later we can delete this web part and leave only its user control.

As our control should display quick lanch navigation, open web part's control markup and copy code from master page that is represented in listing 1. If you deploy the solution and add the web part to a page you will see the quick launch navigation menu for current site.

Now we should change data source. As it is described before we should change http context and create an instance of PortalSiteMapDataSourceSwitch object in it. For this purpose we can create a following class:
public class ContextSwitcher: IDisposable
    private HttpContext _temp;
    private SPSite _site;
    private SPWeb _web;

    public ContextSwitcher(string url)
        _site = new SPSite(url);
        _web = _site.OpenWeb();
        _temp = HttpContext.Current;

        HttpRequest request = new HttpRequest("", _web.Url, "");
        request.Browser = new HttpBrowserCapabilities();
        HttpContext.Current = new HttpContext(request, new HttpResponse(new StringWriter()));
        HttpContext.Current.Items["HttpHandlerSPWeb"] = _web;

    public void Dispose()
        HttpContext.Current = _temp;
        if (_web != null) _web.Dispose();
        if (_site != null) _site.Dispose();
Then we can create method for data retrieving. In this method we should configure the data source as it was done in delegate control of publishing feature. But in our case we have a little shade. The PortalSiteMapDataSourceSwitch object is inherited from SiteMapDataSource that is a static class. This class is initialized on an application pool's start, thus you should invoke OnInit method by hand. The simplest way to do this is to create your own data source class, inherit this class from PortalSiteMapDataSourceSwitch and implement initialization method.
public class Source : PortalSiteMapDataSourceSwitch
    public void Initialize()
This method should be invoked when the settings for this data source are set.
private SiteMapDataSource GetCurrentNavigationSource()
    Source source = new Source();
    source.EnableViewState = false;
    source.StartFromCurrentNode = true;
    source.ShowStartingNode = false;
    source.TrimNonCurrentTypes = NodeTypes.Heading;
    source.SiteMapProvider = "CurrentNavigation";

return source; }
Now all preparations are done and we can bind quick launch navigation menu by our data source.
protected void Page_Load(object sender, EventArgs e)
    using (new ContextSwitcher(Url))

private void BindNavigation(Func <SiteMapDataSource> getSource)
    BindNavigation(QuickLaunchMenu, getSource);
    BindNavigation(V4QuickLaunchMenu, getSource);

private void BindNavigation(AspMenu menu, Func<SiteMapDataSource> getSource)
    if (menu != null)
        menu.DataSource = getSource.Invoke();
This approach is flexible, you can get navigation from any site of your web application by site url.