Monday, January 16, 2017

SharePoint documents under folders with names forbidden on window like "AUX" are not searchable

When we migrated documents from file share to SharePoint 2013 document libraries, users reported that some files are not searchable. When we looked at the search craw logs, we identified many “The object was not found.” Errors. After looking closely at these documents, we have noticed that they are all under folder named “AUX”. In another word, any document under folder named “AUX” will fail in the crawl and will not be searchable.




AUX is one of the folders that is forbidden on window and there are many other folders similar to it. We believe SharePoint may not be able to craw any documents under all of such window forbidden folders. However, we are not able to find any information from SharePoint side.

If you find documents are not searchable, you might need to verify if the documents are under such folder that is forbidden on window.

Friday, December 2, 2016

Auditing solutions deployed to SharePoint environments

With increasing SharePoint 2013 customizations with new app model, there are incidents that these customizations are not working correctly in production while they are working on non-production environments. As SharePoint architect, I’m working with the team to come up an deployment auditing process to ensure what we deployed is what we should deployed. This auditing process will reports the details of the customization components especially the version labels that has been beneficial for deployment verification and debugging. Here are some the auditing reports that have helped to eliminated any customization environment discrepancies.

1. Audit app deployed to certain site collection and the app details including the versions. Here is the powershell commands.

param([string]$siteUrl)

$snapin = Get-PSSnapin | Where-Object {$_.Name -eq 'Microsoft.SharePoint.Powershell'}
    if ($snapin -eq $null) {
      Add-PsSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
}

############################################################################################################################################
function ListApps([string] $siteUrl, [string]$reportName)
{
        $appInstances = Get-SPappinstance -web $siteUrl

        if($appInstances -ne $null)
        { 
                foreach ($eachAppInstance in $appInstances)
                {        
                    $title = $eachAppInstance.Title
                    $version = $eachAppInstance.App.VersionString
                    $AppPrincipalId = $eachAppInstance.AppPrincipalId
                    $Id = $eachAppInstance.Id

                    Write-Output "$title; $version; $Id; $AppPrincipalId"| Out-File $reportName -append 
    
                }
        }


}

############################################################################################################################################

ListApps https://sharepoint.mycompany.com/sites/criticalsite E:\Applist.txt


The result is like below and you could comapre the result across different environments. There are references you could use for different app API.



2. Audit any customized dlls and the versions. Here are some powershell commands.

This one will list ALL dlls inside the current directory recursively.

Get-ChildItem -Filter *.dll -Recurse | Select-Object -ExpandProperty VersionInfo


This one will list only the named dll.

Get-ChildItem -Filter *.dll -Recurse | Where-Object {$_.name -Match "mycompany.com.sp.application1.common.dll"} | Select-Object -ExpandProperty VersionInfo 



3. Audit all farm solutions and their status. Here are the powershell commands.

Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

# Get all Solutions deployed
Get-spsolution | select * |out-file c:\solution.txt

# Connect to the Farm
$SPfarm = [Microsoft.SharePoint.Administration.SPFarm]::get_Local()

# What Solution are we looking for?
$solution = "mycompany.com.sp.apps.workflows.wsp";

# Get the solutions
$currentSolution = $SPfarm.get_Solutions() | Where-Object { $_.DisplayName -eq $solution; }
$currentSolution


We are adding other auditing such as features, permission, configurations at this time and will share those in the future.

Friday, March 4, 2016

How to generate pfx certificate using cer certificate?

When we request SharePoint server to server trust certificates from the company, we are receiving the following two files.

Mycert.cer
Mycert.key

However, we do not receive the pfx file that required for SharePoint servers. We has been using different ways to construct the pfx file and I would like to summarize here in order for me to refer in the future.

There are different situations that we need to generate pfx certificate. The way to generate it will depends and I’ll show two different ways.

The first situation is  you have a private key with a .p7b certificate file and need to create a .pfx file.
You could use IIS server MMC UI to create the pfx file as described here.

The second is you have received both cer and kay file, you have to generate the pfx file from scratch. You could use the following command to generate the pfx file. You MUST put the key file with same name as cer file in the same directory as described here.

certutil -MergePFX Mycert.cer Mycert.pfx

The third situation is you have pfx file already imported to IIS but accidentally deleted. Now you only have the cer file but NO key file. Here is the way to generate the pfx file.

Upload the cer file to IIS as described in Microsoft support blog. Run the following command to restore the pfx file.

certutil -repairstore my "SerialNumber"

SerialNumber is the serial number that you find for the cer file uploaded.


Now you have the cert file for SharePoint server to use.

Friday, January 29, 2016

How to resolve SharePoint list display issue after applying January 2016 Microsoft Critical Security Patch MS16-004?

After applying January 2016  Microsoft Critical  Security Patch MS16-004 on January 12, we have run into SharePoint issue that some lists could not be displayed. The error message is “Unable to get property ‘replace’. See the screenshots.



After working with Microsoft support, we have identified two solutions.

1. The initial solution is to install the full SharePoint Server 2013 Jan 2016 CU and running configuration wizard. This cause significant concern on the server down time and regression testing. Some company may not have this option since they are on older version or SharePoint that could not be upgraded to this CU directly.  Because we do not have time to install full SharePoint Server 2013 Jan 2016 CU, we continue worked with Microsoft on any fixes.

2. On January 15, Microsoft published the official SEE communication on this issue and the fix.  “If you are looking for a minimal change to resolve the issue it you can just install the following fix which contains the missing msp file containing the localized files:

KB 3114508Download location: https://www.microsoft.com/en-us/download/details.aspx?id=50667 “. We are able to apply the fix and fix the list display issue.


In the past three years, we run into issues almost every time we apply monthly security patch that contains SharePoint features. Sometimes even security patch without SharePoint patch may cause issues. The previous issues we run into were August s4ecurity patch for the following two issues.



We were able to apply a workaround for issue #2 but are waiting the fix for issue #1 in Oct. 2015 CU. However, August, Oct, Nov, Dec 2015 CUs breaks the hybrid search.


We will track the SharePoint issues caused by monthly security patch closely in the future.

Tuesday, November 10, 2015

Strike through SharePoint 2013 document item based on its status using JS Link

We have a requirement to strike through SharePoint 2013 document item based on its status "Obsolete". If the obsolete is "yes", the column named "Part Number" should be strike through and highlighted as red as in the below screenshot.


The easiest way to implement this is to use SharePoint 2013 new feature JS Link. There are several good JS Link references to highlight a SharePoint list row and color list item with different color. You could refer my previous blog to configure the JS Link. If you add the following javascript as JS Link named Obsolete.js to the display web part, you will get the desired result.

(function () { 

    // Create object that have the context information about the field that we want to change it's output render  
    var priorityFiledContext = {}; 
    priorityFiledContext.Templates = {}; 
    priorityFiledContext.Templates.Fields = { 
        // Apply the new rendering for Obsolate field on List View 
        "Part_x0020_Number": { "View": obsolateFiledTemplate } 
    }; 

    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(priorityFiledContext); 

})(); 

// This function provides the rendering logic for list view 
function obsolateFiledTemplate(ctx) { 

    var title = ctx.CurrentItem[ctx.CurrentFieldSchema.Name]; 

var obsolate = ctx.CurrentItem.Obsolate;
console.log(obsolate);

      // Return html element with appropriate color based on priority value 
if (obsolate == "Yes")
{
return "<span style='color :#f00'>" + "<del>" + title + "</del>" + "</span>"; 
}
else{
return "<span style='color :#000000'>" + title + "</span>"; 
}


The following script will highlight the item to red when obsolete value is "Yes".


(function () {
    var overrideCtx = {};
    overrideCtx.Templates = {};
    overrideCtx.OnPostRender = {
        HighlightRowOverride
    };
    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
})();

function HighlightRowOverride(ctx) {

for (var i=0; i< ctx.ListData.Row.length; ++i){

var lid = GenerateIIDFromListItem(ctx, listItem);
var row = document.getElementById(iid);

if (listItem.Obsolate == "Yes") {
row.style.backgroundColor = "rgba(255, 0, 0, 0.5)";
}
}

ctx.skipNextAnimation = true;

}

You will see this implementation is very flexible and we could use this for many other different implementations.

If you need to strike through the Document Name field, you would look at the field using view source. Here is the field definition.

{"Name": LinkFilename",
"FieldType": "Computed",
"RealFieldName": "FileLeafRef",
"DisplayName": "Name",
"ID": "5cc6dc79-3710-4374-b433-61cb4a686c12",
"ClassInfo": "Menu",
"Type": "Computed",
"Filterable": "FALSE",
"listItemMenu": "TRUE",
"CalloutMenu": "TRUE",
"AllowGridEditing": "TRUE"}


You can change the two line of the javascript.

    priorityFiledContext.Templates.Fields = {
        "LinkFilename": { "View": obsolateFiledTemplate }
    };

 var title = ctx.CurrentItem.FileLeafRef;

Please note that you could use powershell or server side API to automatically set the JSLink to the webpart if there are many lists or libraries you need to configure.

Friday, November 6, 2015

Use JSLink to auto populate the SharePoint item field without server side code like custom field

Recently we have a requirement to automatically generate a unique number string for one field called “Part Number” for many SharePoint Document libraries. This unique number string would need to follow some business logic like below.



There are several ways we could implement this. One of the old school method is to implement the field as custom field with business logic to generate unique number string. However, we had several custom fields on SharePoint that caused SharePoint upgrade complexity. In this blog, we will use a new client side implementation JSLink that will not have any server side component. In this way, the solution will be potable and the upgrade will be extremely simple.

The first step is to write a JSLink script named PartNum.js to replace the out of box “Part Number” text field behavior. You would need to find out the field internal name using the way published here. The internal field name for “Part Number” is “Part_x0020_Number“ in our case.  The script will look like below. You would need to update the guid() function with real business logic.

(function () {
    var overrideCtx = {};
    overrideCtx.Templates = {};
    overrideCtx.Templates.Fields = {
        'Part_x0020_Number': { 'NewForm': renderTitle, 'EditForm': renderTitle }
    };
    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
})();

function renderTitle(ctx) {

var formCtx = SPClientTemplates.Utility.GetFormContextForCurrentField(ctx);

RegisterCallBacks(formCtx);

        var fieldVal = ctx.CurrentFieldValue ? ctx.CurrentFieldValue.toString() : null;
       
        if(fieldVal) { 
var html = '<div>';
html += '<input id="uniquePartNum" type="text" value=' + fieldVal + '>';
html += '</input>';
html += '</div>';
return html;
}
else{
var newGUID = guid();
var html = '<div>';
html += '<input id="uniquePartNum" type="text" value=' + newGUID + '>';
html += '</input>';
html += '</div>';
return html;  
}
}

//registers call back functions from SharePoint
function RegisterCallBacks(formCtx) {
                //This is what happens when the user clicks save\submit
                formCtx.registerGetValueCallback(formCtx.fieldName, function () {
                                //get the choosen value from the select element
                                var e = document.getElementById("uniquePartNum");
                                return  e.value;
                });
}

// Generate GUID
function guid() {
  function s4() {
    return Math.floor((1 + Math.random()) * 0x10000)
      .toString(16)
      .substring(1);
  }
  return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
    s4() + '-' + s4() + s4() + s4();
}

The second step is to open SharePoint Designer and go to your SiteAssets library, drop PartNum.js there.

The third step is to configure the document item edit form to use this script. Go to your document library and from your library settings ribbon choose ‘Form Web Parts > Default Edit Form’. Edit the webpart. Then add the script to the JS Link field.






Now if you save the changes, you will see the “Part Number” field will be automatically populated with GUID. You could modify the script to generate the string based on your business requirement.

Since Microsoft have changed the development direction for SharePoint 2013 and 2016, you should always think about SharePoint add-in approach instead of server side solution. There are more samples from Microsoft you could refer here.

Friday, October 2, 2015

Debug SharePoint JavaScript issue with web services

If you are using JavaScript calling web services on SharePoint site,  you might see web pages as “Loading…” without the results. The following site has three ContentQuery webpart and all displayed as “Loading…”.



The quick way to debug this is to use Chrome and click More Tools -> Developer Tools. Click console and you might be able to find out the “500” exception as below.



Another quick way to what exactly is the issue, you could call the web service like http://spsbx08/sites/DocCenter/_vti_bin/client.svc in this case to see the real error.

Memory gates checking failed because the free memory (214859776 bytes) is less than 5% of total memory. As a result, the service will not be available for incoming requests. To resolve this, either reduce the load on the machine or adjust the value of minFreeMemoryPercentageToActivateService on the serviceHostingEnvironment config element.

In this case, the issue is the search services are taking too much memory on the server. We could restrict the service not to take too much memory or bounce the server as short term solution.