Monday, October 18, 2021

Custom left navigation broken - Aug 21 Cumulative Updates SharePoint 2016

 

We have a SharePoint 2016 Publishing site with custom left navigation webpart rendering a treeview implemented using <asp:SiteMapDataSource />, <asp:TreeView /> and PortalSiteMapProvider. It was built during MOSS 2007 days, part of the custom site definitions, and carried over through the upgrades. It has been working great since.

I recently installed August 2021 CU and the treeview stopped rendering. Simple rendering "Error" and no exception thrown. 

I spent good amount of troubleshooting and changing the SiteMap providers in the web.config without much luck. The treeview is working fine with all other SiteMapProviders except our custom navigation provider. Looked into ULS found the below errors:

PortalSiteMapProvider was unable to fetch root node, request URL: /xxx/xxx/default.aspx, message: Object reference not set to an instance of an object., stack trace:   

 at Microsoft.SharePoint.Publishing.CacheManager.GetManager(SPSite site, Boolean useContextSite, Boolean allowContextSiteOptimization, Boolean refreshIfNoContext)    

 at Microsoft.SharePoint.Publishing.Navigation.PortalSiteMapProvider.get_ObjectFactory()    

 at Microsoft.SharePoint.Publishing.Navigation.PortalSiteMapProvider.GetRootNodeCore() 

Unable to access this sensitive property : CurrentSite from outer untrusted assembly:Microsoft.SharePoint.Publishing, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c. Trusted assembly list:

PortalSiteMapProvider was unable to fetch current node, request URL: /xxx/xxx/default.aspx, message: Object reference not set to an instance of an object., stack trace:   

 at Microsoft.SharePoint.Publishing.CacheManager.GetManager(SPSite site, Boolean useContextSite, Boolean allowContextSiteOptimization, Boolean refreshIfNoContext)    

 at Microsoft.SharePoint.Publishing.Navigation.PortalSiteMapProvider.get_ObjectFactory()    

 at Microsoft.SharePoint.Publishing.Navigation.PortalSiteMapProvider.get_CurrentNode()


Fix:

Add the following entries to the web.config in SharePoint Web application virtual directory. I had to add the custom navigation assembly entry and the Microsoft's own SharePoint Publishing assembly entry to resolve the issue. 

<SharePoint>
<SafeMode>
<AllowAccessSensitivePropertiesAssemblies>

<AllowAccessSensitivePropertiesAssemblies>

        <AllowAccessSensitivePropertiesAssembly Assembly="YourCustomSiteNavigation, Version=x.x.x.x, Culture=xxxxx, PublicKeyToken=xxxxxxxxx"/>

       <AllowAccessSensitivePropertiesAssembly Assembly="Microsoft.SharePoint.Publishing, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"/>

      </AllowAccessSensitivePropertiesAssemblies>


</AllowAccessSensitivePropertiesAssemblies>

</SafeMode>

</SharePoint>


Our environment is SharePoint 2016, so the Publishing DLL Version shown above is 16.0.0.0. Change the appropriate DLL version to match your SharePoint version, and the culture too, if different. 

Reference:

https://blog.stefan-gossner.com/2021/08/10/common-error-unable-to-access-this-sensitive-property-8gaol-logged-in-uls-after-installing-june-2021-cu-or-later/

https://support.microsoft.com/en-us/topic/user-code-might-be-blocked-when-third-party-assemblies-access-sensitive-properties-kb5004581-1883611f-2f0b-4280-8b38-909fdf4fd659

https://support.microsoft.com/help/5002002


Friday, August 4, 2017

Update content type workflow association approver through PowerShell


I had a requirement to update an approver on a SharePoint workflow which was setup on Document Content Type at the library level. The workflow has been there since SharePoint 2010 and we upgraded to 2013 around 3 years ago. This was an OOB workflow created in UI  (not through SPD) with single task approver with CC user added (see the XML snippet below)

When I opened up workflow settings and in the "Change Workflow" page, I am not seeing plain "Approval" workflow template which is the actual workflow template used but not "Approval - SharePoint 2010". Also the text box is disabled/greyed out and the system isn't letting me change the template throwing the error prompt. Not sure if this is by design or a bug in SharePoint.  


Change workflow page -  Selection is disabled
System don't let you change the template

Anyways, I needed to update the workflow approver with a new employee because the existing one was leaving. When I figured I can't update through UI then I tried through SharePoint Designer which wasn't letting me do it either. So I have chosen PowerShell route to tweak the workflow association properties. 

Association Data in XML


PowerShell snippet.

Just retrieve the list content type's workflow association data which is an xml string and update the approver values.

             $web = Get-SPWeb "http://<SharePoint web URL>"                    
        $list = $web.Lists | Where-Object { $_.Title -eq 'List Title' }                       
        $ListWorkFlowAssns =  $list.WorkflowAssociations        
        foreach($ctype in $list.ContentTypes)
        {
            if ($ctype.Name -eq "Document")
            {                
                $wa = $ctype.WorkflowAssociations.GetAssociationByName("My Approval", $web.UICulture)
                if ($wa -ne $null)
                {                                                                                  
                    $parsedXml = [System.Xml.Linq.XElement]::Parse($wa.AssociationData)                
                    $nodes = $parsedXml.Descendants() | Where-Object {($_.Name.LocalName -eq "Reviewers")}                                    
                    $accountId = $nodes[0].Descendants() | Where-Object {($_.Name.LocalName -eq "AccountId")}
                    $displayName = $nodes[0].Descendants() | Where-Object {($_.Name.LocalName -eq "DisplayName")}
                    $accountId.SetValue("Domain\UserName") # replace value with the new approver AD username
                    $displayName.SetValue("User Full Name") # replace value with the new approver AD Full Name                 
                    $wa.AssociationData = $parsedXml.ToString()
                    $ctype.WorkflowAssociations.Update($wa)               
                    
                }               
            }            
        }

        $list.Update()




I made sure no current instances are running and no new instances are created while I am making these changes. 






Note: If you are following the same approach, please put additional checks and filters while updating. You don't want to update other content types mistakenly or workflow association properties that you are not intended. 

Monday, April 24, 2017

Attended SharePoint Fest DC 2017


Last week I attended the SharePoint conference in Washington DC- SharePoint Fest DC 2017. It has various tracks such ECM. Search, BI, Office 365, workflow, and development. I have chosen all the developer and implementation topics with the focus on Azure, Office 365 related to SharePoint. 




The development topics that I attended were touched on React, TypeScript, SPFx, SharPoint PnP. I had chance attend sessions from SharePoint's well known MVPs such as Joel Oleson, Asif Rehmani (remember SharePoint workflow vidoe's); few presenters were very young who seemed hard core javascripters. 

Here are the topics that I attended:
  • How to make use of All that’s included in Office 365 – By Asif Rehmani
  • SharePoint Frame work, Angular & Azure Functions: The modern SharePoint developer tool belt – By Sebastien Levert
  • Using Document Sets to implement Business Processes – By Tom Robbins
  • Not sure how you should REACT – By Ryan Schouten
  • Teams, Groups, SharePoint and Yammer….Oh My! – By Joel Oleson
  • Upgrading Legacy SharePoint Customizations to the Add-in Model – By Danny Jessee
  • SharePoint 2016 : What’s New and Why should I upgrade? – By Paul Stark
  • Supercharge your SharePoint Framework Webpart with React – By Eric Overfield
  • Extranets in SharePoint On Premises and Office 365 – By Peter Carson
  • Azure Active Directory (Azure AD) for Office 365 Developers – By Prashanth G Bhoyar

Overall, I liked the conference; came out with one aspiration: do more JavaScript, get on the cloud....

Thursday, January 26, 2017

SharePoint Custom WCF Service with Automatic Formatting



Recently I was writing a custom SharePoint WCF service for using in client side JavaScript libraries (jquery, angular) and C# server side call HttpWebRequest without worrying adding references and proxy classes. Majority of the articles I referred to were only showing JSON output; I wanted this service to provide both JSON and Xml data formats. If the requirement is to output both JSON and Xml formats, I found people writing two method calls:one for each JSON  and Xml. Also, I have seen articles where response was driven through method or query string parameter to get requirement format (WebMessageFormat.Xml, WebMessageFormat.Json) If I follow the former approach as shown below, the amount of code will grow twice the code that I actually need which is very inefficient and demand more maintenance. 

[ServiceContract]
interface IPersonService

    {
         [WebGet(UriTemplate = "person/{id}",  ResponseFormat = WebMessageFormat.Json)]
          Person GetPersonJSON(int id); //get JSON output

         [WebGet(UriTemplate = "person/{id}",  ResponseFormat = WebMessageFormat.Xml)]
          Person GetPersonXml(int id);  //get Xml output
    }

All I wanted was automatic formating based on some configuration or flag set through code. While searching for options. I found this technet article. helpful.
WCF Web HTTP Automatic and Explicit  Formatting options
https://msdn.microsoft.com/en-us/library/ee476510(v=vs.110).aspx

(snippet from technet)

Automatic Formatting

The WCF Web HTTP programming model allows you to dynamically determine the best format for a service operation to return its response in. Two methods for determining an appropriate format are supported: automatic and explicit.
When enabled, automatic formatting chooses the best format in which to return the response. It determines the best format by checking the following, in order:
  1. The media types in the request message’s Accept header.
  2. The content-type of the request message.
  3. The default format setting in the operation.
  4. The default format setting in the WebHttpBehavior
(/snippet from technet)

Solution:
  1. Added web.config file to my custom wcf custom service. 
  2. C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\isapi\<MyCustomWCFService>
  3. Added System.ServiceModel section as show below.
         <configuration>
     <system.serviceModel>
      <behaviors>  
        <endpointBehaviors>        

          <behavior>          

            <webHttp automaticFormatSelectionEnabled="true" />
          </behavior>
        </endpointBehaviors>
      </behaviors>
      </system.serviceModel>
    </configuration>

     
Have only service contract method.


[ServiceContract]
interface IPersonService
    {
         [WebGet(UriTemplate = "person/{id}")]
          Person GetPerson(int id);
   }

Now I can the call same method through jquery/ajax by specifying the ContentType or Accept Header and get the output format that I need. 

JavaScript - JSON Output 


function getPerson() {
            var serviceUri = _spPageContextInfo.webAbsoluteUrl" + "/_vti_bin/<MyCustomService>/PersonService.svc/person/" + id;
            $.ajax({
                type: "GET",
                contentType: "application/json",
                url: serviceUri,
                dataType: "json"
            }).done(function (data) {
                //do something here
            }).fail(function (error) {
            });

        }

JavaScript - Xml Output

function getPerson() {
            var serviceUri = _spPageContextInfo.webAbsoluteUrl" + "/_vti_bin/<MyCustomService>/PersonService.svc/person/" + id;
            $.ajax({
                type: "GET",
                contentType: "application/xml",
                url: serviceUri,
                dataType: "xml"
            }).done(function (data) {
                //do something here
            }).fail(function (error) {
            });

        }

Server Side C# - HttpWebRequest - JSON Output


HttpWebRequest endpointRequest = (HttpWebRequest)HttpWebRequest.Create(serviceUri);
endpointRequest.Method = "GET";
endpointRequest.Accept = "application/json;odata=verbose";



Server Side C# - HttpWebRequest - Xml Output


HttpWebRequest endpointRequest = (HttpWebRequest)HttpWebRequest.Create(serviceUri);
endpointRequest.Method = "GET";
endpointRequest.Accept = "application/xml;odata=verbose";

Friday, October 28, 2016

SharePoint 2013 Search Crawl


SharePoint 2013 Search crawls stuck

The search crawls are getting hung for some reason. It all started recently. The crawls were stuck for hours and days if  not stopped manually. The farm that I work with would normally finish full crawls in less than 4-5 hours with around 300K size index in the largest content source. Strangely enough, when I kick off the crawl, the crawl is running fine with index count grows, however, I see no commits at the end (crawl never completes). Below are ULS errors I extracted. 

Search service events aei87 Warning A database error occurred. Source: .Net SqlClient Data Provider Code: 220 occurred 0 time(s) Description:  Error ordinal: 1 Message: Arithmetic overflow error for data type smallint, value = 32768., Class: 16, Number: 220, State: 1    at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)     at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)     at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)     at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)     at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds)     at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite)     at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite)     at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()     at Microsoft.Office.Server.Data.SqlSession.ExecuteNonQuery(SqlCommand command)     at Microsoft.Office.Server.Search.ManagedSqlSession.ExecuteNonQuery()

mssearch.exe (0x3D7C) 0x3384 SharePoint Server Search Crawler:Gatherer Plugin ac6s7 High ManagedSqlSession caught a SqlException executing the following command: 'proc_MSS_CommitTransactions'. Connection string was: 'Data Source=XXXXX;Initial Catalog=SSA_CrawlStoreDB;Integrated Security=True;Enlist=False;Pooling=True;Min Pool Size=0;Max Pool Size=100;Connect Timeout=15;Application Name=SharePoint[OWSTIMER][1][Search_Service_Application_CrawlStoreDB_299952a3060f4f628def625b742db001]'  Original exception message: 'Arithmetic overflow error for data type smallint, value = 32768.  Duplicate key was ignored.'  Stack trace '   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)     at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)     at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)     at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)     at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds)     at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite)     at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite)     at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()     at Microsoft.Office.Server.Data.SqlSession.ExecuteNonQuery(SqlCommand command)     at Microsoft.Office.Server.Search.ManagedSqlSession.ExecuteNonQuery()' SQL Errors:  Error ordinal: 1 Message: Arithmetic overflow error for data type smallint, value = 32768., Class: 16, Number: 220, State: 1  Error ordinal: 2 Message: Duplicate key was ignored., Class: 0, Number: 3604, State: 0

mssearch.exe (0x3D7C) 0x3384 SharePoint Server Search Crawler:Gatherer Plugin aau6c High CManagedSqlSession::ExecuteNonQuery m_ManagedSqlSession->ExecuteNonQuery fails with Error 0x80131904 Description 'Arithmetic overflow error for data type smallint, value = 32768.  Duplicate key was ignored.' Message 'Unknown error 0x80131904'  [gathersql.cxx:2243]  search\native\gather\server\gathersql.cxx

mssearch.exe (0x3D7C) 0x3384 SharePoint Server Search Crawler:Gatherer Plugin aau2i High CGatherer::CommitTransactions pSession->ExecuteNonQuery for proc_MSS_CommitTransactions failed with Error 0x80131904  [gatherobj.cxx:8212]  search\native\gather\server\gatherobj.cxx



#1 Actions Taken:


  • Reset Search Index

Index reset resulted the above errors go away. May be this is due to the reason that our full crawls were stuck on completing forever and every time we stop and initiate the crawl, a new full crawl kicks in and get stuck again. So with all this pile up, maybe the temp table sequences in proc_MSS_CommitTransactions procedure go out of smallint limit. Not sure if this theory is right but reset index definitely cleared the above errors but the crawls were getting stuck again with a new set of errors. See below.

mssearch.exe (0x0FA8)                     0x1644      SharePoint Server Search           Crawler:Gatherer Service            dsg6  Medium        CRobotThread::Thread failed to move file for docID 50093, URL sts4://site/siteurl=site1/subsite/siteid={0a3cf259-90dc-4abb-bf2e-15bb0d7275e7}/weburl=shared/webid={c54d4bd4-f6a4-4813-9aa8-927039e53575}/listid={20e29c27-f4dc-48fb-8528-8e0bcae2d450}/folderurl=/itemid=1211, Error 0x80070005. The transaction will be retried.  [robotthrd.cxx:4810]  search\native\gather\gthrsvc\robotthrd.cxx 54ad911a-fc69-4897-920d-f557c1cf9d53


#2 Actions Taken:


  • Add Antivirus exclusions (if not already added) on all SharePoint servers.
  • Reboot the servers


Result: Crawls completed as expected. The issue is resolved. 

Saturday, January 23, 2016

JQuery and SP Modal Dialog HTML option



SharePoint SP Modal Dialog accepts either URL or html in the dialog options. The below code snippets show how to create HTML DOM elements using JQuery and pass the container HTML for rendering in the dialog. I chose this option because creating DOM elements with styles and binding them with events using JQuery is easy as compared to plain JavaScript. Using this approach we can create dynamic forms to post/get ajax requests through modal dialogs. 

<script type='text/javascript'>

//Container DIV
var container = $("<div/>").css({
        'width': '80%',
        'margin': '10px 5px 10px 20px',
        'border': '1px solid #808080',
        'padding': '10px 10px 10px 10px'
    });

//Text area for entering comments
var txtcomments = $("<textarea/>",

        { id: 'txtComments', rows: '5', cols: '50' }).css({ 'display': 'block' });


//Button added to DIV
var btn = $("<input/>", { type: 'button', value: 'Save' })
.css({
   'height': '30px',
   'width': '100px',
   'display': 'inline-block',
   'padding-right': '10px'
});

//attach button click event
btn.on("click",

        function () {
        //call ajax or WebMethod and submit data to server
        });

//Spacer DIV
var spacer = $("<div/>").css({ 'height': '30px', 'display': 'block' });

//Append all individual DOM elements to container DIV
container.append(txtcomments)
         .append(btn)
         .append(spacer);

//Dialog options
//key thing is container.get(0) which gives actual DOM element 
var dlgOptions = {
        title: "Form Dialog",
        html: container.get(0), //this is important
        width: 600,
        height: 300,
        dialogReturnValueCallback: function (result, retVal) {  //call back to refresh calling page (parent window)         
            SP.UI.ModalDialog.RefreshPage(SP.UI.DialogResult.OK);
        }
    };

//Once all values are set, on onclick event (client side) of a button call
function onClientButtonClick(){
  SP.SOD.execute('sp.ui.dialog.js', 'SP.UI.ModalDialog.showModalDialog', dlgOptions);
}
</script>

<!-- HTML Source -->
<!-- this button opens modal dialog -->
<input type='button' onclick='return onClientButtonClick();return false;' value='Open Dialog' style='width:120px' />

References
https://msdn.microsoft.com/en-us/library/office/ff410058(v=office.14).aspx
https://api.jquery.com/get/



Thursday, June 5, 2014

PSConfig stuck - SharePoint 2013 Server Service Pack 1 installation



Last week I was installing SharePoint 2013 Service Pack 1 on production environment at my workplace. The environment has 2 WFE, 2 APP, 1 DB Server.

Used the script provided by Russ Maxwell from this site below to save time on installation. Thanks Russ.
http://blogs.msdn.com/b/russmax/archive/2013/04/01/why-sharepoint-2013-cumulative-update-takes-5-hours-to-install.aspx

Installation went well and while running PSConfig Wizard on one of the app server, the process got stuck for an hour or so on Step 9 of 10. I sensed something wrong as other servers finished within less than 20 minutes. So killed the PSConfig process in Task Manager and restarted again, no luck, same hang.
Googled for some time and found this link about registry permissions
https://techsps.wordpress.com/2013/11/26/psconfig-stuck-at-10-00/

Assuming the reason for hang could be, process must be waiting on something. So checked the permissions on app and web servers. Found that, the app server (non central admin server) which is having the issue, missing permission for WSS_Restricted_WPG_V4 on the below registry:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\15.0\Secure

Gave the same permission (Full Control) as other servers and ran the PSConfig again. It finished successfully within less than 10 minutes.

Hope it helps if anyone is having the same issue.