Wednesday, March 15, 2017

Get Child Count in Parent List SharePoint Lookup Field


I came across a requirement where I required the number of comments
 against a post in a child list (lstComments) maintained in the Parent list (lstPost).

Below is a very efficient way to achieve this


 using (SPSite site = new SPSite(webUrl))
            {
                using (SPWeb web = site.OpenWeb())
                {
                    SPList lstPost = web.Lists.TryGetList("Post");
                    SPList lstComments = web.Lists.TryGetList("Comments");

                    if (lstPost != null &&  lstComments != null )
                    {
                        SPField id= lstPost .Fields.TryGetFieldByStaticName("ID");
                        if (null != id)
                        {
                            // Create a PostID lookup field on the lstComments list.  
                            string PostIdName = lstComments .Fields.AddLookup("PostID", lstPost .ID, true);
                            SPFieldLookup PostIdField =
                                (SPFieldLookup)lstComments .Fields.GetFieldByInternalName(PostIdName );
                            PostIdField .LookupField = id.InternalName;
                            PostIdField .Update();
                            AddToDefaultView(lstComments , PostIdName );

                            // Create a CommentCount Lookup field to maintain child count in the lstPost list
                            string commentCountName = lstPost .Fields.AddLookup("CommentsCount", lstComments .ID, false);
                            SPFieldLookup commentCountField =
                                (SPFieldLookup)lstPost .Fields.GetFieldByInternalName(commentCountName );
                            commentCountField .LookupField = id.InternalName;
                            commentCountField .CountRelated = true;
                            commentCountField .Update();
                            AddToDefaultView(lstPost , commentCountName );
                        }
                    }
                }

            } 

Friday, February 10, 2017

SharePoint Distributed Cache Issue

All of a sudden my farm started throwing Distributed cache errors. My ULS filled with below log when I refreshed a page 
Unexpected Exception in SPDistributedCachePointerWrapper::InitializeDataCacheFactory for usage 'DistributedLogonTokenCache' - Exception 'Microsoft.ApplicationServer.Caching.DataCacheException: ErrorCode<ERRCA0009>:SubStatus<ES0001>:Cache referred to does not exist. Contact administrator or use the Cache administration tool to create a Cache.   
 at Microsoft.ApplicationServer.Caching.DataCache.ThrowException(ResponseBody respBody, RequestBody reqBody)   
 at Microsoft.ApplicationServer.Caching.DataCacheFactory.GetCacheProperties(RequestBody request, IClientChannel channel)   
 at Microsoft.ApplicationServer.Caching.DataCacheFactory.GetCache(String cacheName)   
 at Microsoft.SharePoint.DistributedCaching.SPDistributedCachePointerWrapper.InitializeDataCacheFactory()'.

I tried steps below and walla!

1) Go to Manage Services on Server in Central Administration and stop Distributed Cache on all Application Servers and WFEs

2) Open SharePoint Management Shell and run following commands

       a) Use-CacheCluster
       b) Get-CacheCluster | Select CacheName
Above commands should return list of 10 cache types 

CacheName            
---------          
DistributedAccessCache_<ur farm ID>
DistributedActivityFeedCache_<ur farm ID>
DistributedActivityFeedLMTCache_<ur farm ID>
DistributedBouncerCache_<ur farm ID>
DistributedDefaultCache_<ur farm ID>
DistributedLogonTokenCache_<ur farm ID>
DistributedSearchCache__<ur farm ID>
DistributedSecurityTrimmingCache_<ur farm ID>
DistributedServerToAppServerAccessTokenCache_<ur farm ID>
DistributedViewStateCache_<ur farm ID>

Incase you get nothing - you need to setup DistribtedCache again so move on to step 7

In case above list is returned move on to step 3

3) Run following command 
                   Remove-SPDistributedCacheServiceInstance

4) to check of the cache instance is removed successfully 
                   Get-Cache | Select CacheName
this should return below error

Get-Cache : ErrorCode<ERRCMS0006>:SubStatus<ES0001>:Error while loading the
provider "SPDistributedCacheClusterProvider". Check HKEY_LOCAL_MACHINE ->
SOFTWARE\Microsoft\AppFabric\V1.0\Providers\AppFabricCaching ->
SPDistributedCacheClusterProvider....

5) Now add new instance of DistributedCacheService by running following command
                                  a) Add-SPDistributedCacheServiceInstance
                                 b)  Restart-CacheCluster
this should return below

HostName : CachePort                      Service Name             Service Status            Version
                                                                                       Info
--------------------                    ------------                    --------------         ----------
<host server name>:<port>      AppFabricCachingService            UP                           3
                                                                                      [3,3][1,3]

6) check if cache is available now:
                    Get-Cache | Select CacheName
should give output as below

CacheName            
---------          
DistributedAccessCache_<ur farm ID>
DistributedActivityFeedCache_<ur farm ID>
DistributedActivityFeedLMTCache_<ur farm ID>
DistributedBouncerCache_<ur farm ID>
DistributedDefaultCache_<ur farm ID>
DistributedLogonTokenCache_<ur farm ID>
DistributedSearchCache__<ur farm ID>
DistributedSecurityTrimmingCache_<ur farm ID>
DistributedServerToAppServerAccessTokenCache_<ur farm ID>
DistributedViewStateCache_<ur farm ID>


 7) No output on running step 2) indicates that you need to setup Distributed Cache altogether

to do so first determine your farm ID 
         Get-SPFarm | Select Id 
get the output and run the following command 
       New-Cache -CacheName DistributedLogonTokenCache__<ur farm ID>



8) check if cache is available now:
                    Get-Cache | Select CacheName
should give output as below

CacheName            
---------          
DistributedAccessCache_<ur farm ID>
DistributedActivityFeedCache_<ur farm ID>
DistributedActivityFeedLMTCache_<ur farm ID>
DistributedBouncerCache_<ur farm ID>
DistributedDefaultCache_<ur farm ID>
DistributedLogonTokenCache_<ur farm ID>
DistributedSearchCache__<ur farm ID>
DistributedSecurityTrimmingCache_<ur farm ID>
DistributedServerToAppServerAccessTokenCache_<ur farm ID>
DistributedViewStateCache_<ur farm ID>


 Hope this helps


Wednesday, June 1, 2016

FileNet SharePoint Integration - II

Here is my second post related to Implementing FileNet P8 API in SharePoint. In my previous post, I explained a bit about FileNet, FileNet P8 API and connecting to FileNet from C# application.

Here is how you can read a folder from FileNet, fetch its properties, fetch subfolders.

FileNet API allows you to get Folders / Files using Ids and Path. In my case, I used the path as those are configurable and can work in different scenarios.

  1. Connect to FileNet
  2. Fetch a Folder
  3. Fetch Subfolders from FileNet & Properties

1. Connect to FileNet:
public static IObjectStore Connect()
{
  try
  {
   // Set connection parameters; substitute for the placeholders.
   string uri =  GetConfigValue("FileNetServerURL");
   //"http://filenetserverurl:9082/wsi/FNCEWS40MTOM/"; 
      string username = GetConfigValue("FileNetServerAdmin"); //"P8Admin";
   string password = GetConfigValue("FileNetServerAdminPassword"); //"Password";
   string objectstorename = GetConfigValue("FileNetObjectStore");//ECMStore
   // Get client context.
   IConnection conn = Factory.Connection.GetConnection(uri);
   // UsernameToken 
   UsernameCredentials creds = new UsernameCredentials(username, password);
   ClientContext.SetProcessCredentials(creds);
     // Get default domain.
   IDomain domain = Factory.Domain.FetchInstance(conn, null, null);
   // Get object stores for domain.
   IObjectStore os = Factory.ObjectStore.FetchInstance(domain, objectstorename, null);
   return os;
 }
 catch (Exception ex)
 {   
  return null;
 }
}
2. Get Folder By Path:
   private static PropertyFilter PFFolder;
   public static string GetFolderIDFromPath(string path, string siteUrl=null )
            {
                try
                {

                PFFolder = new PropertyFilter();
                PFFolder.AddIncludeProperty(new FilterElement(null, null, null, PropertyNames.ID  , null)); 
//property that is not fetched directly can be fetched using a property filter
  IObjectStore os = Connect(siteUrl); // returns IObjectStore from Connect Method, check connect method
                    IFolder ifolder = Factory.Folder.FetchInstance(os, path,PFFolder );
                    return ifolder.Id.ToString ();
                }
                catch (EngineRuntimeException ex)
                {
             LogError(ex, " GetFolderIDFromPath("+path+")", siteUrl);
                    return null;
                }
            }

3. Fetch Sub-folders from FileNet:
   public static List<FileNetFolder> GetAllFolders(string folderpath, bool includeContent, string siteUrl = null)
            {
                List<FileNetFolder> allFolders = new List<FileNetFolder>();
                try
                {
                    IObjectStore os = Connect(siteUrl );
                    IFolder folder = Factory.Folder.GetInstance(os, ClassNames.FOLDER, folderpath);
                    IFolderSet subFolders = folder.SubFolders;
                    for (IEnumerator iterator = subFolders.GetEnumerator(); iterator.MoveNext(); )
                    {
                        IFolder subFolder = (IFolder)iterator.Current;
                        FileNetFolder newSubFolder = new FileNetFolder();
                        newSubFolder.Title = subFolder.FolderName;
// fetch OOB Properties
                        newSubFolder.TitleEn = Convert.ToString(subFolder.Properties["TitleEn"]); 
//Fetch Custom properties of a folder
                        newSubFolder.folderId = Convert.ToString(subFolder.Id);
                        allFolders.Add(newSubFolder);
                    }
                }
                catch (Exception ex)
                {
                    LogError(ex, "GetAllFolders()", siteUrl);
                  
                }
                return allFolders;

            } 


I have used the property filter while fetching properties of a folder. A property filter adds properties that are not directly received when fetching/getting a folder. such properties can be added to a property Filter add retrieved while fetching/getting a folder/file. 

Example:

private static PropertyFilter PFFolder; 
PFFolder = new PropertyFilter();
                PFFolder.AddIncludeProperty(new FilterElement(null, null, null, PropertyNames.ID  , null));

   IFolder ifolder = Factory.Folder.FetchInstance(os, path,PFFolder ); 

Tuesday, May 31, 2016

SharePoint User Profile Service Application Provisioning Issues


SharePoint User Profile Service Application Provisioning Issues
Quick Fix: 

$sync_db = "Sync DB"
$ups_service_app_name = "User Profile Service Application"

net stop sptimerv4
$syncdb=Get-SPDatabase | where {$_.Name -eq $sync_db}
$syncdb.Unprovision()
$syncdb.Status='Offline'
$ups = Get-SPServiceApplication  | where {$_.Displayname -eq $ups_service_app_name }
$ups.ResetSynchronizationMachine()
$ups.ResetSynchronizationDatabase()
$syncdb.Provision()
net start sptimerv4


------------------------------------------------------------------------------------------------------------------------------
 Get-SPServiceInstance | where {$_.TypeName -eq "User Profile Synchronization Service"}

User Profile Synchronization ... Online   ID of the service instance  1
User Profile Synchronization ... Provi...  ID of the service instance 2

$abc=Get-SPServiceInstance | where {$_.Id -eq "ID of the service instance 2"}
Stop-SPServiceInstance | where {$_.Id -eq "ID of the service instance 2"} 

and the lifesaver Reset SharePoint Cache: reference:  (http://saadiyadad.blogspot.com/2014/03/reset-SharePoint-config-cache.html) did the magic


FileNet SharePoint Integration - I

Hi Readers,
I had been away for a while and now planning to write some post based on the work I have been doing in this period. My upcoming post will be related to SharePoint 2013 development, workflows, SharePoint tweaks and fixes and majorly FileNet integration to SharePoint 2013 using FileNet P8 API and FileNet Connector for SharePoint. All my posts will be in the context of Integration of FileNet to SharePoint. You can get complete information on FileNet at IBM Support Knowledge Center.
Let's start with the introduction to FileNet and some basic operations using FileNet P8 API:
  • Introduction to FileNet Content Manager
  • FileNet P8 API Basic Concepts 
  • Connect to FileNet Repository
  • A single repository for enterprise content to provide centralized access and better control.
  • Document management services and application development support to streamline content management and delivery.
  • Delivery of active content in motion for improved business value and reduced costs.
  • Integration with Microsoft SharePoint and Microsoft Office to help increase productivity.
  • Social collaboration and mobile computing support to use the latest technologies in your enterprise content management (ECM) environment." Source: IBM
Documents
Folders
Custom Objects
  •  Example  HTTP://<your FileNet server URL>:<port>/wsi/FNCEWS40MTOM/
  • P8Administrator
  • ECM
      try
      {
       string uri =  GetConfigValue("FileNetServerURL");
          string username = GetConfigValue("FileNetServerAdmin"); 
    //"P8Administrator";
       string password = GetConfigValue("FileNetServerAdminPassword");
     //"Password";
       string objectstorename = GetConfigValue("FileNetObjectStore");
    //ECMStore
       // Get client context.
       IConnection conn = Factory.Connection.GetConnection(uri);
      
     // UsernameToken 
       UsernameCredentials creds = new UsernameCredentials(username, password);
       ClientContext.SetProcessCredentials(creds);
      
       // Get default domain.
       IDomain domain = Factory.Domain.FetchInstance(conn, null, null);
       // Get object stores for domain.
       IObjectStore os = Factory.ObjectStore.FetchInstance(domain, objectstorename, null);
       return os;
     }
     catch (Exception ex)
     { 
      return null;
     }

Introduction to FileNet Content Manager:
"Document management with IBM® FileNet® Content Manager helps you meet the growing challenge of managing enterprise content with greater speed, efficiency, and accuracy. FileNet Content Manager is a document management engine that combines enterprise content, security and storage features with ready-to-use workflow and process management capabilities.
FileNet Content Manager features include:

FileNet P8 API Basic Concepts:
 FileNet provides an extensive API for Java and C# to programmatically handle operations in FileNet Content Manager. P8 API allows applications to interact to FileNet for CRUD operations as well as Management of properties, classes, subscriptions, Permissions etc. 
  
The .NET framework-based API provides a .NET framework-based Common Language Runtime (CLR)-compliant API for accessing the full capability of Content Engine. The API accepts username and password credentials for authentication. The .NET framework-based API works only with the WSI Listener.
Following are some basic concepts of FileNet Content Manager.

Object Store:
Refers to the FileNet repository. All documents, folders, custom objects are referred to as objects in FileNet so Object store is actually a container for those objects. Every object store has a database that can comprise one or more storage areas. Objects in FileNet are further classified into versionable and non-versionable objects 

Documents are versionable objects and have metadata. A document contains content elements. A file of any type is an example of a document.

A folder is a container of objects(documents, folders etc. ). It is a non-versionable object and has metadata.

Custom objects are non-versionable objects that can contain metadata but no content. you can relate them to a database table row.

Connect to FileNet Repository:
Following is a sequence of how you can interact with FileNet through P8 API.
 You require FileNet repository details as mentioned below to connect to FileNet Content Manager through API

1. FileNet Repository URL:
2. Administrator User Name:
3. Administrator Password: 
4.  Object Store Name: 

Code Example to Connect to FileNet is as Follows:

public static IObjectStore Connect()
   // Set connection parameters; substitute for the placeholders.
   //"http://filenetserverurl:9082/wsi/FNCEWS40MTOM/";
}


Note: You must install Microsoft WSE to connect to FileNet on Windows Server 2008 R2, Win Server 2012 if FileNet server URL starts with HTTP:// else it will fail to connect since WCF only supports https:// connections

Wednesday, April 30, 2014

PWA Eventing Service. Exception : System.Runtime.Remoting.RemotingException: Failed to connect to an IPC Port: The system cannot find the file specified.

SCENARIO:
When a custom event handler is configured on PWA server the eventing service fails and timesheet events go into error state.
I developed Server-side event handlers for Project Server Timesheet Approval Cycle to send emails to timesheet writer and approvers. This included an assembly that calls PSI web services to interact with PWA that is registered in GAC and basicHttpBinding timeout changes to cater timout issues occuring while reading web service response.

The solution  I provided was successfully tested and verified on UAT environment and deployed to Production server and here starts the issue...

ISSUE:
    After registering the Event handlers to PWA the following error starts prompting. All the timesheets started giving error  and queued.   When cancelled from the queue the timesheet showed submitted state because they update the Published DB but didnot reflect in Reporting DB.
1.   “Couldn't validate configuration on eventing service: Exception: System.Runtime.Remoting.RemotingException: Failed to connect to an IPC Port: The system cannot find the file specified.  
2.   “Standard Information:PSI Entry Point:   Project User: DOMAIN\User  Correlation Id: 1dcd87ae-9345-4733-b950-f8443ebb3fcb  PWA Site URL: http://site/PWA  SSP Name: Project Server PWA_ServiceApp  PSError: NoError (0) Queue unable to interact with SQL. Queue type (Project Queue, Timesheet Queue etc): TimesheetQ Exception: Microsoft.Office.Project.Server.BusinessLayer.Queue.QueueSqlException: CompleteGroup failed ---> System.Data.SqlClient.SqlException: Could not allocate space for object 'dbo.MSP_QUEUE_TIMESHEET_GROUP_ARCHIVE'.'CL_MSP_QUEUE_TIMESHEET_GROUP_ARCHIVE' in database 'ProjectServer_Published' because the 'PRIMARY' filegroup is full. Create disk space by deleting unneeded files, dropping objects in the filegroup, adding additional files to the filegroup, or setting autogrowth on for existing files in the filegroup.   
3.   Error is: GeneralActionCanceledBecauseServerEventServiceProblem. Details: Attributes:  TimesheetReviewed  . Standard Information: PSI Entry Point:   Project User:DOMAIN\User  Correlation Id: 443945d0-741a-4eb2-99bf-4c2ba50e6365  PWA Site URL: http://site/PWA   SSP Name: Project Server PWA_ServiceApp  PSError: GeneralActionCanceledBecauseServerEventServiceProblem (22002)
After rolling back all the changes and unregistering the assembly from PWA   the IPC remote call error still prompted on every event call. Like if I delete , recall ,submit, approve or reject a timesheet
In the logs it shows in following order.
1.       Attempts to call IPC
2.       Throws error for number of retries attempted with following logs.
1.   ServerEventManager: Reconfiguring events 
2.   This occurs on every timesheet event i.e: submit, recall, delete, reviewed even after rolling back the deployment from Production server As shown in the log  below.  “Error during farm configuration change. Exception : System.Runtime.Remoting.RemotingException: Failed to connect to an IPC Port: The system cannot find the file specified. 

Resolution: 
 Most of the issues like thi are due to Firewall blocking IPC connections.
to resolve this issue you need to change the User account settings to minimum.


  • Go to Start   ---------->  Control Panel  ---------->  User Accounts  
  •  Change User Account Setting ----------------> Set the settings to never notify ----> Press OK

    • Restart the server if prompted.
    • Deploy the provided assembly and register the event handlers to PWA
    • Test It
    Issue Resolved :)

Monday, March 17, 2014

Reset SharePoint Config Cache

  The   path for the Configuration Cache under Windows Server 2008 is: C:\ProgramData\Microsoft\SharePoint\Config\<GUID>


Stop the Timer service. To do this, follow these steps:
1.      Click Start, point to Administrative Tools, and then click Services.
2.      Right-click SharePoint 2010 Timer, and then click Stop.
3.      Close the Services console.
4.      On the computer that is running Microsoft SharePoint Server 2010 and on which the Central Administration site is hosted, click Start, click Run, type explorer, and then press ENTER.
5.      In Windows Explorer, locate and then double-click the following folder: C:\ProgramData\Microsoft\SharePoint\Config\GUID
Notes
1.      The GUID placeholder specifies the GUID folder. There may be more than one of these.
2.      The ProgramData folder may be hidden. To view the hidden folder, follow these steps:
·         On the Tools menu, click Folder Options.
·         Click the View tab.
·         In the Advanced settings list, click Show hidden files and folders under Hidden files and folders and then click OK.
3.      (You can also simply type this directly in the path if you do not want to show hidden files and folders.)
4.      Back up the Cache.ini file. (Make a copy of it. DO NOT DELETE THIS FILE, Only the XML files in the next step)
5.      Delete all the XML configuration files in the GUID folder (DO NOT DELETE THE FOLDER). Do this so that you can verify that the GUID folders content is replaced by new XML configuration files when the cache is rebuilt.
Note When you empty the configuration cache in the GUID folder, make sure that you DO NOT DELETE THE GUID FOLDER AND THE CACHE.ini file that is located in the GUID folder.
If Cache .ini is Missing
6.      Double-click the Cache.ini file.
7.      On the Edit menu, click Select All.
8.      On the Edit menu, click Delete.
9.      Type 1, and then click Save on the File menu. (Basically, when you are done, the only text in the config.ini file should be the number 1)
10.  On the File menu, click Exit.
11.  Start the Timer service. To do this, follow these steps:
·         Click Start, point to Administrative Tools, and then click Services.
·         Right-click SharePoint 2010 Timer, and then click Start.
·         Close the Services console.
12.  Note The file system cache is re-created after you perform this procedure. Make sure that you perform this procedure on all servers in the server farm.
13.  Make sure that the Cache.ini file in the GUID folder now contains its previous value. For example, make sure that the value of the Cache.ini file is not 1.
14.  Check in the GUID folder to make sure that the XML files are repopulating. This may take a bit of time.


  If Cache.ini is missing under   “C:\ProgramData\Microsoft\SharePoint\Config\” or is deleted by mistake, perform the following Steps:
Now the mission is to get my Timer Job up and functioning. So I took the back-door approach to create GUID folder with Cache.ini file. Here are the steps I performed to get the config GUID of SharePoint.
1.      Stop the SharePoint 2010 Timer process.
1.      Open Windows Registry Editor
2.      Locate the ConfigDB key. Usually, it must be in this place if you are using SharePoint 2010.[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\14.0\Secure\ConfigDB]
3.      You will see String Values entries for
4.      DSN: Connection string for your configuration database.
5.      Id: GUID of SharePoint configuration database. Copy this GUID.
6.      Goto C:\ProgramData\Microsoft\SharePoint\Config\ folder. (ProgramData folder is hidden, make sure change windows folder options to make it visible to you)
7.      Create a folder and name it as the GUID (that you just copied from Registry).
8.      Go into this folder, create a text file and name it as Cache.ini.
9.      Now edit this Cache.inikey in value 1 Save and close the file.
10.  Start the SharePoint 2010 Timer process.
11.  Do an IIS RESET
12.  Now check all your application pools are up and running. Otherwise, start them manually.