December 18, 2013

Expand SPTreeView Node Automatically When Selected


Before:
After:


The standard behavior of SharePoint tree view control (SPTreeView) is that when you select a folder node it will not expand its children nodes. You must click the expand icon [+] in order to show the sub folders. Also, that is not exclusive, so when you click the expand [+] icons of another node folder, the tree will show it's children without collapsing the previous node folder.


The objective:

I wanted to customize the tree view navigation to combine the functionality of clicking the node title and clicking the expand icon so that user can expand nodes with less hassle. The user should only click a node folder title and the tree will automatically expand to show child nodes while other nodes will collapse.


How:

I'll use JQuery. The idea is when a node title is clicked then a post back occurs and there will be a RootFolder parameter in page Url indicating selected folder node, so we will call the javascript function associated with its exapnd [+] icon.

This is the markup for the SPTreeView in the page:

<SharePoint:SPHierarchyDataSourceControl id="doclibDataSource" runat="server" RootListId="a65a6e37-de92-496a-b896-5b976dff7b61"
RootWebId="277d98b7-be33-451f-9ed8-6691a5a72736" ShowFolderChildren="true" EnableViewState="false">

</SharePoint:SPHierarchyDataSourceControl>
<SharePoint:SPRememberScroll runat="server" id="TreeViewRememberScrollV4" onscroll="javascript:_spRecordScrollPositions(this);" style="overflow: auto">
<SharePoint:SPTreeView ID="doclibtreeview" runat="server" DataSourceID="doclibDataSource" EnableViewState="false" ExpandDepth="1" SelectedNodeStyle-CssClass="SelectedItemStyle">
</SharePoint:SPTreeView>
</SharePoint:SPRememberScroll>


Inject the following script in the master page or in CEWP. I added the SelectedItemStyle CSS style to make selected nodes more visible.


<style>
.SelectedItemStyle {
BORDER-TOP: 1px dotted; BORDER-RIGHT: 1px dotted; BORDER-BOTTOM: 1px dotted; BORDER-LEFT: 1px dotted; BACKGROUND-COLOR: #dddddd
}</style>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>

<script>

_spBodyOnLoadFunctionNames.push("customIBRTreeNav");

function customIBRTreeNav(){
var SelectedFolder = unescape(getUrlParameter('RootFolder'));
var ItemTitle = SelectedFolder.substring(SelectedFolder.lastIndexOf("/") + 1);
var LinkItem = jQuery('a[title="' + ItemTitle + '"]:not(:has(img))');
var IconItem = LinkItem.closest('td').prev('td').prev('td').find('a');// [+] & [-] icon
var IconItemHref = IconItem.attr("href");
var CustomTreeViewPopulate = new Function(IconItemHref); // create the function from string
CustomTreeViewPopulate.call(this);
}

function getUrlParameter(name)
{
  name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
  var regexS = "[\\?&]"+name+"=([^&#]*)";
  var regex = new RegExp( regexS );
  var results = regex.exec( window.location.href );
  if( results == null )
    return "";
  else
    return results[1];
}</script>


Note: remember to set the ExpandDepth parameter to value of '1' in the SPTreeView control. 
This is necessary to get the intended functionality. I didn't have time to implement the logic when ExpandDepth is 2 or more.. maybe later!


December 6, 2013

Issue: Starting a service crashes SharePoint site with unknown error


Issue:

After you stop a service (such as User Profile Synchronization or Search service) and try to start it again in Central Administration, the SharePoint 2010 site pages will crash with an unknown error.



Analysis:

Prior to the issue, the password was changed for the services account in SharePoint. However all services were working.

Searching the cascading numerous errors in ULS to find the root cause kept my head spinning for hours. I knew that issue was because of the password change in services account but couldn't spot where is the start point to fix.
Some of the error messages I found in IIS log:
- "Application pool 15f65d1adf954fa68aee81f7bcb9cec8 has been disabled. Windows Process Activation Service (WAS) encountered a failure when it started a worker process to serve the application pool."
- Another message is that the account may need batch logon permissions.

 then I had a clear image of what happened:

  1. The service (User Profile Synchronization service or Search service) tries to start
  2. Service fails to start because its application pool in IIS could not login 
  3. Since its application pool is down, it will bring down all the services that are running on it. If User Profile service is working on this application pool then it will stop. Also if Metadata service is working on this application pool then it will stop, and bring down the Profile service as well since User Profile depends on Metadata.
  4. All content on SharePoint pages (such as pages, web parts,..) requires a valid user login to display according to user permissions. Since User Profile service is down, current user cannot be verified and SharePoint shows unknown error.

I already made sure that that the service account has the necessary permissions and that services and service applications are setup correctly on CA. Also the application pool account is using the correct password.
Well, it didn't work! Every time I try to start the application pool in IIS it stops after couple of seconds. Agrrrrrr...

It appeared that the faulty application pool "15f65d1adf954fa68aee81f7bcb9cec8" in IIS becomes corrupted object and will not work.



Solution:

Relocate applications that are on corrupted application pool into another one with exact same settings.
First, make a backup for WFE and APP servers.
Depending on your current configurations, make the following changes in IIS in WFE and APP servers:

  1.      Create new AppPool “MetadataCustomAppPool” as copy of the corrupt AppPool but using new password  for service account
  2.      Move “metadata” and “Profile” applications from corrupt AppPool to   “MetadataCustomAppPool” AppPool.  This is useful when other service is down (and     subsequently its AppPool is down too), it will not affect the Metadata/User Profile and the   SharePoint site will continue to work.
  3.     If other service applications are in corrupt AppPool, then you can relocate them into MetaDataCustomAppPool or create a new AppPool for them as appropriate.
  4.      Restart IIS