SharePoint : Document ID link redirection fails for some file types (like png, jpg, mpp, etc)

In one of the application, we are using Document ID for permalink in document libraries. We are storing documents of different file types (like docx, xlsx, pdf, png, jpg, jpeg, etc) in document library. SharePoint search is set up in our server which crawls the data every half an hour.

Case 1 :

When any document (of type docx, xlsx, pdf) is added in document library, unique Document ID generated for document. When I clicked on that link, that document is either opened (if client application installed like pdf, office application) or downloaded.

Case 2 :

But when I added documents of file types png, jpg, jpeg or mpp in document library and clicked on Document ID, it works same as Case 1. After half an hour search crawls the site. When I clicked again on Document ID link, it opens the display form of that document instead of opening or downloading the document. But the Case 1 is still working even after crawling happens.

I search for the issue in internet and found below article in msdn :

Document ID Lookup Behavior

 SharePoint Server 2010 takes a two-part approach when the document ID service looks up document IDs to provide the best balance of document IDs that work immediately and those that work across broad scopes:
  • Search. Find an item across any location that belongs to the current search scope. Search generally performs better as a cross-list query. However, search is only as reliable as its last index. Therefore, if an item was added but has not yet been indexed by search, it does not appear in search results. Additionally, if an item was moved since the last time it was indexed by search, then the old (and now broken) URL appears in search results.
  • Lookup specific to the ID provider. When an item cannot be retrieved by using search (for example, if it has not been indexed yet), SharePoint Server 2010 calls back to the document ID provider and allows it to use its own lookup logic. This enables providers who want to use IDs that work before search indexing is run on the last items to look them up. The provider determines whether to perform lookups in this way and what the most effective logic is for doing so.

After reading above statement it clear that SharePoint Search is not properly indexing the document of file types png, jpg, jpeg, mpp.

You can read below article to know more about default File Types supported  by SharePoint Search :

SharePoint Search 2013 File Types

Solution

To solve this issue, we have to go SharePoint server and follow below steps:

  1. Open Central Administration -> Application Management .
  2. Click on “Manage service applications
  3. Open Search Service Application
  4. On left section, under Crawling section click on File Types. Here you will see all file types which SharePoint Search understands and crawled properly.
  5. Click on “New File Type” and add all extensions one by one without any dot.
  6. Now click on Content Sources and start Full Crawl on your content source which is created for your web application.
  7. Once Full Crawl completed, check those documents which are failed to open earlier. When you clicked again on Document ID link, they will work as expected without redirecting to display form.

Note : Repeat above steps for other file types which are facing similar issue.

References : 

https://msdn.microsoft.com/en-us/library/office/ee559302(v=office.14).aspx

SharePoint : Powershell snippet to upgrade sandbox solution

In previous article Upgrade SharePoint Sandbox Solution, we have explained how to upgrade the sandbox solution so that necessary changes must reflected properly. To upgrade the solution, do not deploy it from Visual Studio because it will retract the previous activated solution from solutions gallery and add new one.

You can use below powershell snippet, which will upgrade the existing sandbox solution with new one. Since solution package (*.wsp) have same solution id even if we rename them. So here we are finding the already activated sandbox solution in solution gallery from new solution package.


function Update-SPUserSolutons
{
		param($solutionFolderPath, $siteUrl)
		
		$files = Get-ChildItem -Path $solutionFolderPath -Recurse -File
		foreach ($file in $files)
		{
			if($(Get-SPUserSolution -Site $siteUrl -Identity $file.Name -ErrorAction SilentlyContinue) -eq $null)
			{
				Add-SPUserSolution -Site $siteUrl -LiteralPath $file.Fullname
                                # Get already activated solution from solution gallery
				$solutionName = Get-SPUserSolutionId -siteUrl $siteUrl -name $file.Name
				write-host "Upgrading solution $solutionName to $file.Name"
				Update-SPUserSolution -Identity $solutionName -Site $siteUrl -ToSolution $file.Name
				write-host "$file.Name upgraded"				
			}
		}
}

function Get-SPUserSolutionId
{
		param($siteUrl, $name)
		
		$newSolution = Get-SPUserSolution -Site $siteUrl -Identity $name;
		
		$solution = Get-SPUserSolution -Site $siteUrl |?{$_.SolutionId -eq $newSolution.SolutionId -and $_.Status -eq "Activated"}|select -first 1
		return $solution.Name;
}

#Call below function to upgrade solution
Update-SPUserSolutons -solutionFolderPath "E:\SandboxSolution\" -siteUrl "http:\\your-sitecollection-url" 

Note : In solutionFolderPath parameter, provide the folder path where you have placed your wsp. Make sure you have only wsp packages in that folder.

SharePoint : Get User’s login name from claims encoded value

There are sometimes scenarios where we have to get user’s login name and we have only claims encoded value (like this i:0#.w|domain\username or i:0#.f|membershipprovider|abc.xyz@comp.com). In SharePoint 2013 / 2010, there is SPClaimProviderManager class available which can decode the claims and provide user’s login name.

I have created a method, which accepts claims encoded value as parameter and returns user’s login name (only if claims are resolved properly).

private string GetUsernameFromClaim(string claimsEncodedUsername)
{
 try
 {
 SPClaimProviderManager mgr = SPClaimProviderManager.Local;
 if (mgr != null)
 {
 if (SPClaimProviderManager.IsEncodedClaim(claimsEncodedUsername))
 {
 // return the normal domain\username without any claims identification data
 return mgr.DecodeClaim(claimsEncodedUsername).Value;
 }
 }
 }
 catch (Exception ex)
 {
 return claimsEncodedUsername; // Or just return the original username.
 }

 // Return the original username value if it couldn't be resolved as a claims username
 return claimsEncodedUsername;
}

Note : Add namespace “Microsoft.SharePoint.Administration.Claims” to use above class.

Issue in SharePoint Folder name with apostrophe ( ` ) and Launch Dialog property of List / Library

In SharePoint list / library items are created for storing the data. Generally user wants a granular structure for maintaining data and for this they creates folder and place their items. Now, if “Launch Dialog” box property is set to “Yes” for this list / library, then details are shown in dialog box. Now if folder name contains apostrophe ( ‘ ) then JavaScript fails in SharePoint and dialog box will not open for all items which are placed inside that folder.

In SharePoint, certain characters are not accepted while creating folder names : ~ ” # % & * : < > ? / \ { | }.
But apostrophe ( ‘ ) is accepted by SharePoint in folder name, and above mentioned issue will applicable only when launch dialog property of list / library is enabled.

If dialog box of items are not opening properly, then look for all parent folders of that item and check whether those folder contains apostrophe ( ‘ ) or not. If yes, then rename that folder name by removing apostrophe.

Read user claims information in SharePoint 2013

In this article, we will see how to read user claims in SharePoint 2013. For this I have prepared one httphandler, which will read the claims information of current logged in user (authentication type windows, forms or third party trusted provider).

using Microsoft.IdentityModel.Claims;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration.Claims;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace SSONamespace
{
    class SSOAuthenticationExample : IHttpModule
    {
        public void Init(HttpApplication context)
        {
            context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute);
        }

        void context_PreRequestHandlerExecute(object sender, EventArgs e)
        {            
            string requestUrl = HttpContext.Current.Request.Url.ToString();
            IClaimsIdentity ci = (IClaimsIdentity)HttpContext.Current.User.Identity;
            List<Claim> claimCollection = ci.Claims.OfType<Claim>().Select(x => x).ToList();

	/*Uncomment these lines to see all claims entries */
            //string text = string.Empty;
            //foreach (Claim item in ci.Claims)
            //{
            //    text += item.ClaimType + " : " + item.Value + " | ";
            //}

            //System.IO.File.WriteAllText(@"C:\SSOClaims.txt", text);
		
		//fetch information from claims
            string userName = claimCollection.Where(x => x.ClaimType.ToLower().Contains("userid")).Select(y => y.Value).FirstOrDefault();
         }

        public void Dispose() { }

    }
}

Now deploy this code and add below entry in web.config file of web application :

<system.web>
  <httpModules>
    <add name="SSONamespaceModule" type="SSONamespace.SSOAuthenticationExample , SSONamespace, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3af8d8e2f9e8b6c3"  precondition="integratedmode" />
  </httpModules>
</system.web>

Note : Replace PublicKeyToken value from your own project’s PublicKeyToken