Search This Blog

Wednesday, October 14, 2015

SharePoint Crawl DB size increasing @20GB per day


Recently, one of my SharePoint farms faced an issue where the volume utilization of DB server (SharePoint crawl database) went upto 99% within 10 days.

Analysis:
- Looking at the crawl DB log in SharePoint, the incremental crawl was running every 1.5 hours with 0 success and 100% failures.

- There were about 961K errors with each incremental crawl scheduled at every 2 hours.









- There is a temporary folder that Crawl uses to place files temporarily on the server. The path is C:\Users\"SPAdminAccount"\AppData\Local\Temp\gthrsvc_OSearch14\

- I found out that this temporary folder was somehow missing / deleted.

Solution:

On creating the above mentioned folder manually, the success rate of crawl went high and there were very less failures (as expected)









Post this, the space utilization went about 10 MB a day which is expected during crawl.

Wednesday, October 7, 2015

SharePoint detect when crawl account is accessing your page


Many a times we put some code in our SharePoint pages to add an entry in a list, whenever  a particular page is accessed. This is usually done for getting the page visit count or to keep the record of the latest visited page/document per user. However you may not want to add entries for the search account when it performs a crawl of your content source as this could cause serious performance issues; as we faced, since we were having multiple site collections and in those site collections we had our custom document set home pages implementing the same logic of updating a list whenever the page is accessed.

In order to fix this, I had to detect that whether the page is being accessed by normal user or by the SharePoint Crawl account. The best way I found to detect the page access is using "User-Agent". When the Crawl accesses the page, it adds following string as user agent in Request headers:

MS Search 6.0 Robot
User-Agent: Mozilla/4.0 (compatible; MSIE 4.01; Windows NT; MS Search 6.0 Robot)

I was simply able to detect whether the page is accessed by normal user or SharePoint Crawl by checking the following value:

if (!HttpContext.Current.Request.UserAgent.Contains(“MS Search 6.0 Robot))
        {
          //Add your logic to add/update the list
        }

This works for both SharePoint 2010 as well as 2013 since the Robots tag value is same for both the versions.


Monday, August 24, 2015

Enable or Disable Grid Sorting in Dynamics CRM 2011, CRM 2013 and CRM 2015


Just got the task to disable the associated grid sorting in Dynamics CRM 2013




So i looked at the OOB CRM features to achieve this but found there is no option available to disable/enable the grid sorting :(


Then i extracted an unmanaged solution which includes the required entity and modified the "customizations.xml" as shown below.


Don't get confuse you just need to find the <savedqueries> in XML and then search for the required view for which you want to disable the sorting and add the disableSorting="1" attribute to the particular cell.

After updating XML save it and import that back to CRM and you will notice now sorting is disabled for the particular column.




and if you want to enable sorting again then you will need to update disableSorting="0" or remove the attribute by following the same procedure.



Monday, August 17, 2015

SharePoint Increase search result items limit of Content Search Web Part by using javascript




SharePoint Content Search Web Part allow to show search results upto 50 Items per page.
Out Of The Box you cant allow it to show more than 50 Items per page.

But there may be situations with business needs where you need to override this behavior.
So here is javascript snippet which overrides this behavior and allows more than 50 items in search result.

How to use :

1. Add a Script Editor web part on the same page where Content Search web part is present.
2. Paste the following script and change the maxItems value as per your needs.
3. The script grabs the 2 SharePoint search objects ContentBySerach and DataProvider and overrides it default value to show more than 50 items.



<script type="text/javascript">

var $ocreate = null, maxItems = 100;

Sys.Application.add_init(function() {
$ocreate = $create; $create = updateResultCountCreate;
});

function updateResultCountCreate(a,b){
var ps = Array.prototype.slice.call(arguments, 0);
if(a == Srch.ContentBySearch) b.numberOfItems = maxItems;
if(a == Srch.DataProvider) b.resultsPerPage = maxItems;
$ocreate.apply(this,ps);
}
</script>

  

Friday, August 7, 2015

Change the size of Promoted Links in SharePoint using jquery


A simple way to change size of Promoted Links in SharePoint using Jquery. Copy below code to your common script file that is attache to master page and call TP_PromotedLink function by adding script editor to your web page where promoted links web part is attache.

TP_PromotedLink = function (imageSize, numberOfImage){
var  value; 
$(window).load(function() {
updatePromotedLink();
$('.ms-tileview-tile-root').mouseover(function() {
$(this).find('.ms-tileview-tile-detailsBox').removeClass('promo1');
$(this).find('.ms-tileview-tile-detailsBox').addClass('promo');
});
$('.ms-tileview-tile-root').mouseout(function() {
$(this).find('.ms-tileview-tile-detailsBox').removeClass('promo');
$(this).find('.ms-tileview-tile-detailsBox').addClass('promo1');
});
$('.ms-tileview-tile-detailsBox').mouseover(function() {
$(this).removeClass('promo1');
$(this).addClass('promo');
});
$('.ms-tileview-tile-detailsBox').mouseout(function() {
$(this).removeClass('promo');
$(this).addClass('promo1');
});


});

function updatePromotedLink(){
value =imageSize;
$("<style type='text/css'> .promo1{ top : "+value+"px !important} </style>").appendTo("head");
$("<style type='text/css'> .promo{ top :0px !important} </style>").appendTo("head");
$("<style type='text/css'> div.ms-tileview-tile-titleTextMediumCollapsed{  background: rgba(0, 98, 144, 0.8); font-size: 12px; line-height: 16px;  padding-left: 3px; position: absolute;} </style>").appendTo("head");
var body_width = (imageSize+10) * numberOfImage;
var title_width = imageSize+10;
var title_top = - imageSize/4;
$('.ms-promlink-header').css('visibility', 'hidden');
$('div.ms-promlink-body').width(body_width);

$('div.ms-tileview-tile-root').width(title_width, 'important');
$('div.ms-tileview-tile-root').height(title_width, 'important');
$('div.ms-tileview-tile-content').width(imageSize, 'important');
$('div.ms-tileview-tile-content').height(imageSize, 'important');
$('div.ms-tileview-tile-detailsBox').height(imageSize, 'important');
$('div.ms-tileview-tile-detailsBox > a').width(imageSize, 'important');
$('div.ms-tileview-tile-content > a').height(imageSize, 'important');

$('div.ms-tileview-tile-content').width(imageSize, 'important');
$('ul.ms-tileview-tile-detailsListMedium').height(imageSize, 'important');
$('ul.ms-tileview-tile-detailsListMedium').width(imageSize, 'important');
$('div.ms-tileview-tile-titleTextMediumCollapsed').css('min-width', imageSize);


$('.ms-positionRelative').each(function(){
if($(this).parent().parent().hasClass('ms-tileview-tile-content')){
$(this).height(imageSize,'important');
$(this).css('position','static','important');
}
});

$('div.ms-tileview-tile-titleTextMediumCollapsed').css('min-height', -title_top);
$('div.ms-tileview-tile-titleTextMediumCollapsed').css('top', title_top);

$('.ms-tileview-tile-detailsBox').width(imageSize)
$('.ms-tileview-tile-detailsBox').css('top',imageSize,'important');

$('ul.ms-tileview-tile-detailsListMedium').css('padding','0');

}
}



TP_PromotedLink accept two parameter

1.  imageSize : This is size of image in promoted link. If you want an image of size 150 X 150 than pass 150 as a parameter.

2. numberOfImage : This is for number of image you want to display in one row. If you pass 3 than in a row only 3 image of promoted link are display.

Like below image i add script editor in which i call TP_PromotedLink(150,3); 

than my promoted link is change according to that size




Wednesday, August 5, 2015

SharePoint 2013 online provider hosted Apps setup and creation

SharePoint Central Admin Prerequisites

SharePoint you must have the following service applications provisioned and started:


  1. Subscription Service Application with proxy
  2. Subscription Settings Service instance started
  3. Application Management Service Application and proxy
  4. App Management Service instance started
  5. Must have User Profile Service started

Prerequisite (Need to check if we need to setup ADFS on INT environment?)

  1. SharePoint 2013 server is ready with apps configured
  2. ADFS 3.0 server is ready with realm set to SharePoint.
  3. ADFS is registered with SharePoint as a trusted identity provider.
  4. ADFS 3.0 server is ready with realm set to asp.net provider hosted app
  5. Server is ready for hosting asp.net provider hosted app.
  6. Load balancer configured for provider hosted web application
  7. Certificate is available in private, public part along with password.


Step 1: Create a Certificate

  1. In the development environment you can use a self-signed certificate, but you would need a commercial certificate when you publish your Apps to store. So we will create a self-signed one. In the IIS manager, click on Server Certificates.


  2. Click on Create Self Signed Certificate


  3. Enter some meaningful name like HighTrustCert and Click on Ok.


  4. Now we need to export the personal exchange format (.pfx) file. Right Click on the Certificate in IIS click on Export and provide an accessible location. Also enter the password that you want to use and Click on Ok




  5. Next, double click on the Certificate in IIS. Click on Details tab and click on Copy to File.


  6. Now you should see the Certificate Export Wizard (remember earlier we exported the .pfx file). The first screen elucidate the significance of what we are doing. Keep Clicking Next across the three screens. Below screenshots demonstrate the same. I keep all the default options. Just one thing to mark that now we are now exporting the .cer file. I choose the same location. Click on Save.





  7. And finally, click on Finish. You should see you the message “The export was successful”.

Step 2: Run Windows PowerShell cmdlets to set up trusted security token service




  1. Run SharePoint 2013 Management Shell as administrator. First thing first, you need an Issuer ID. An important point, it has to be Lowercase only.

    Create a GUID with Visual Studio. Make sure all letters are lowercase. For e.g. 7591c7a2-cc56-40ef-8f71-20a4d8450ed7
  2. Run the below PowerShell cmdlets to create trusted security token service.
    $publicCertPath = "D:\Certificate\WB_EBiz_WFACert.cer"
    $appId = "7591c7a2-cc56-40ef-8f71-20a4d8450ed7"
    $spurl = "http://wbgmsspsnd017/sites/EBiz"
    $spweb = Get-SPWeb $spurl
    $realm = Get-SPAuthenticationRealm -ServiceContext $spweb.Site
    $certificate = Get-PfxCertificate $publicCertPath
    $fullAppIdentifier = $appId + '@' + $realm
    New-SPTrustedSecurityTokenIssuer -Name "WB EBiz WFA App" -Certificate $certificate -RegisteredIssuerName $fullAppIdentifier
    $appPrincipal = Register-SPAppPrincipal -NameIdentifier $fullAppIdentifier -Site $spweb -DisplayName "WB EBiz WFA App"

    This will add certificate to both Personal Store and Trusted Root Certification Authorities store in mmc. To verify, go to your Trusted Root Certification Authorities Store and you should see your Certificate there
    Significance / additional info of the cmdlets
    issuerID : assigning the GUID generated in the previous step
    publicCertPath : path where I saved my .cer file.
    web : your Developer site URL
    realm : should be the same as your farm ID

    New-SPTrustedSecurityTokenIssuer : Just a tip, when you use the Name parameter it can be helpful to include a readable name, such as “High Trust App” or “Contoso S2S apps” instead of the issuer ID.

    IsTrustBroker: this flag ensures that you can use the same certificate for other apps as well. If you don’t include this, you might receive “The issuer of the token is not a trusted issuer" error.

    So we have two possible approaches each having their own pros and cons .i.e. use the same certificate shared by multiple apps Or use a separate certificate for each app. Read additional details at Guidelines for using certificates in high-trust apps for SharePoint 2013
    iisreset : to ensure the Issuer becomes valid, else it takes 24 hours.

    Additionally you can turn off the https requirements using below PowerShell cmdlets. But ensure to turn it on by changing $true to $false in the second cmdlet below.
    $serviceConfig = Get-SPSecurityTokenServiceConfig
    $serviceConfig.AllowOAuthOverHttp = $true
    $serviceConfig.Update()

    Refer to the screenshot below of for the complete steps:




Step 3: Create a Simple “High Trust” Provider Hosted App using Visual Studio 2012 (DEVELOPMENT)




  1. Click New Project -> App for SharePoint 2013



  2. Select ASP.NET MVC web app



  3. Now select the PFX certificate generated in the last step. Provide password and Issuer ID



  4. This will create a new MVC project.



  5. Now Visual studio created two projects with in the same solution. MVCApp1 is the SharePoint App and MVCApp1Web is the remote webapp. Only artifact of the MVCApp1 is the appmanifest.xml. This is similar to what feature.xml to WSP. We provide the version, permission and startpage details of the app.



  6. Make sure Windows authentication is enabled for web project, and check other settings as well.



  • Now you can directly debug the app by pressing f5. Now login to app using your windows credentials and trust the app. This will lead to sample app hosted from VS2013 if all the settings are right.



Step 4: Create App Domain and Set for SharePoint (DEPLOYMENT)

Configure App Domain

  1. Create App Catalog site – new site from going in Central Admin – Apps – Manage App Catalog, Create new site collection

Configure App URLs

  1. If you get a message - The Subscription Settings service and corresponding application and proxy needs to be running in order to make changes to these settings.
    Run the belowPS script to create new service application for subscription service... Though service is already running but service application is missing

    $account = Get-SPManagedAccount "WB\spm13devep1"
    $appPool = New-SPServiceApplicationPool -Name SubscriptionServiceAppPool -Account $account
    $serviceApp = New-SPSubscriptionSettingsServiceApplication -ApplicationPool $appPool -name "Subscription Settings Service Application" -DatabaseName "SP2013INT-SubscriptionSettingsDB"
    $serviceAppProxy = New-SPSubscriptionSettingsServiceApplicationProxy -ServiceApplication $serviceApp
    Then try again

Step 5: IIS Site Creation (DEPLOYMENT)


  1. App Catalog Server (IIS) Configuration
    1. Copy the Personal Information Exchange (.pfx) and published files into the app catalog server.
    2. Enable the required features (refer the below screenshot) through “Add Roles and Features” in Server Manager.
    3. Import the Certificate, IIS -> Server Certificates -> then click “Import” link in the right top.
    4. Create a Folder for place the web app published files (ex. C:\inetpub\wwwroot\eBizApps )
    5. Create a Website in IIS.  Right click in “Sites” then choose “Add Website”.
    6. In the “Add Website” window, enter the proper site name, select the physical path (C:\inetpub\wwwroot\eBizApps) and then click “OK” button.
    7. Select the site name (ex. eBizApps), click the “Bindings” link in right side. 
    8. In the Site Bindings window, Click “Add” button”
    9. In the Add Site Binding window, select the Type as “https” and then select the SSL certificate. And then click “OK” button
    10. Browse this site using Internet Explorer.  The site will open.
  2. Once created, create SSL binding also
    Click Bindings on right side
    So we should have 2 bindings now
    This website is empty now we need to deploy content from code (11 machine) to 08 machine which is here
    Deployment involves App deployment and Website deployment
    App Deployment: Before publishing the app, a new client ID for the App should be generated form the app site. SharePoint uses this client ID to validate the App file while installing. Navigate to appregnew.aspx
    Navigate to https://sp2013.gsi.local/sites/apps/ and generate AppId
    So we might get a result like this when hit create button
    The app identifier has been successfully created.
  3. The App Domain is the domain name set on the remote web application server’s IIS Site that will be hosting this app.
    App Id:    1b395959-b36f-47b3-84dc-f695d3a6a585   -- this is APP/ CLIENT ID
    App Secret:    Cf6n+YWaBJ8bDIqJp656J76IoJNPcNh+C3H99Ob0i/U=
    Title:    EBizWFA
    App Domain:    wbgmsspsnd008
    Redirect URI:    
    Right click the solution and click publish and select Package the app. And enter the client ID and the remote site URL.
    This wizard will generate a package
    Take this package on 08 machine where IIS is. And run this command
    Now IIS website should have all the content. Web project has been deployed
    Make changes to web config file specific to environment.

Step 6: Package SharePoint App


Update clientId in App Manifest file.
Check for correct permissions assigned in AppManifest file. – Web (Full control)
Target url should be of the site to be deployed
Click Finish and this will publish the file in the bin\debug folder under “app.publish” folder
On opening the .app file with good old WINRAR all the resources can be extracted out. And verify appmanifest.xml .

Step 7: Add app to App Catalog

For an app to be consumed, it must be added to an app catalog.

  1. Navigate to the app catalog and select Apps for SharePoint 
  2. Select New App and upload the .app file produced from the last set of steps



Step 8: Add app to site


  1. Access a team site and selected site contents and clicked Add App.
  2. Click on it and click Trust It . Note: If it errors on this step and you’re logged in as the system account, try again using a non-system account.
  3. After install, test by clicking on the app.

    Redirect should work!

Monday, August 3, 2015

SharePoint TRIM field values before submit

A simple way to implement TRIM on all the Text fields inside SharePoint site is to make use of SharePoint OOTB javascript function named "PreSaveAction()". 

function PreSaveAction()    
{
 return true;
}

This function is called before the data is Added/Updated inside a SharePoint List. This function needs to return a true value so that further events are processed. If you return false from this function, then further execution would be stopped and data won't be saved. Since we are concerned only in replacing the original values with the trimmed ones, we will always return true from this function. 

To do this, just add the below code in a javascript file and link that js file to your master page. Alternatively you can also make use of Content Editor Web part to embed it in a page (if you want it to scope this to a specific list/library) .

function PreSaveAction() {
    try {
        $("input[Type='Text']").each(function () {
            $(this).val($.trim($(this).val()));
        });
        return true;
    }
    catch (e) {
    }
    return true;

}


Monday, July 27, 2015

Create List View using SharePoint REST API


function createView(ListName, query )
{

var bodyContent = "{ '__metadata': { 'type': 'SP.View' }, 'Title': 'View Name', 'PersonalView': true, 'ViewQuery':'" + query + "' }";

var viewUrl = _spPageContextInfo.webAbsoluteUrl + "/_api/lists/getbytitle('"+ListName+"')/views"

 var executor;  executor = new SP.RequestExecutor(_spPageContextInfo.webAbsoluteUrl);  executor.executeAsync({ url: viewUrl,

method: "POST",

body: bodyContent,

headers: { 

"accept": "application/json;odata=verbose",

"content-type": "application/json;odata=verbose"

},

success: function (results) { alert("View Created.") },

error: function (error) { alert("Error in view creation.") }

});

}

Call this function you have to pass two parameter ListName and query.
ListName : This is name of list in which you want to create view.

Query : You have to pass CAML Query base on which filter is set and your view is created. Like

 '<Where><Eq><FieldRef Name=\"'Title'\" /><Value Type=\"Text\">' + TitleVar +'</Value></Eq</Where>';




You can customize your view but adding more attribute in body.

This code create a personal view because i set 'PersonalView' : true. If you want to create public view than set it to false. 

var bodyContent = "{ '__metadata': { 'type': 'SP.View' }, 'Title': 'View Name', 'PersonalView': true, 'ViewQuery':'" + query + "' }";


For more detail check https://msdn.microsoft.com/en-us/library/office/dn531433.aspx#bk_View

Note : 

1. Please make sure that you have loaded SP.RequestExecutor.js script file. To load script file

var scriptbase = _spPageContextInfo.webAbsoluteUrl+ "/_layouts/15/";

$.getScript(scriptbase + "SP.RequestExecutor.js", yourFunctionName);


2. You have proper permission to create views.

SharePoint CRUD Operations on ListItem PropertyBag

# Initialize the SharePoint PowerShell environment
Add-PSSnapIn "Microsoft.SharePoint.Powershell" -ErrorAction:SilentlyContinue



# Function to perform add , delete , view and update operation on list item properties
# Parameters :
# -- ItemBagKey : Name of property of list item
# -- Operation : Type of operation  "ADD" , "UPDATE" , "DELETE" , "VIEW"
# -- NewValue : Value for the item property 
# -- Item : List item to operate upon 


Function UpdateKey{
      param([string]$ItemBagKey,[string]$Operation,[string]$NewValue,[Microsoft.SharePoint.SPListItem]$item)
      if($Operation -eq "ADD"# If we are adding property to item.
      {
            if($item.Properties.ContainsKey($ItemBagKey))
            {
                  Write-Host "Key already found in item bag." -ForegroundColor Yellow;
                  $item.Properties[$ItemBagKey] = $NewValue;
                  $item.SystemUpdate($false);
                  Write-Host "Key update with new value : "  $NewValue - ForegroundColor Green;
            }
            else
            {
                  Write-Host "Key not found in item bag." -ForegroundColor Yellow;
                  $item.Properties.Add($ItemBagKey,$NewValue);
                  $item.SystemUpdate($false);
                  Write-Host "Key added with value : "  $NewValue -ForegroundColor Green;
            }
      }
      elseif($Operation -eq "DELETE"# If we are deleting property from item.
      {
            if($item.Properties.ContainsKey($ItemBagKey))
            {
                  $item.Properties.Remove($ItemBagKey);
                  $item.SystemUpdate($false);
                  Write-Host "Key removed from item bag : "  $ItemBagKey -ForegroundColor Green;
            }
            else
            {
                  Write-Host "Key not found in item bag to remove." -ForegroundColor Red;
            }
      }
      elseif($Operation -eq "UPDATE"# If we are updating property of item.
      {
            if($item.Properties.ContainsKey($ItemBagKey))
            {
                  $item.Properties[$ItemBagKey] = $NewValue;
                  $item.SystemUpdate($false);
                  Write-Host "Key updated with new value : "  $NewValue -ForegroundColor Green;
            }
            else
            {
                  Write-Host "Key not found in item bag." -ForegroundColor Red;
            }
      }
      elseif($Operation -eq "VIEW"# If we want to view value item property.
      {
            if($item.Properties.ContainsKey($ItemBagKey))
            {
                  Write-Host "Property value : "  $item.Properties[$ItemBagKey] -ForegroundColor Yellow;
            }
            else
            {
                  Write-Host "Key not found in item bag." -ForegroundColor Red;
            }
      }
}

try
{
     
      #Put your site URL in placeholder <siteurl> 
      $web = Get-SPWeb <siteurl>     

      #Put list name in placeholder <listname> 
      $list = $web.Lists["<listname>"


      #If the list is found
      if($list)
      {
  
  #Put list item id in placeholder <itemid> 
  $item = $list.GetItemById(<itemid> );


  #Put Item property key that you want to operate upon in placeholder               <propkey> 
  $_ItemBagKey = "<propkey>"


  #Replace placeholder <OP> with type of operation you want to perfrom it            could be one among four values ( ADD, UPDATE , DELETE , VIEW )
  $_Operation  = "<OP>"  # "ADD" # "UPDATE" # "DELETE" # "VIEW"


       #Replace placeholder <propvalue> with new value that you want to update          if you want to delete or view just leave the value blank.
       $_NewValue   = "<propvalue>"
  

 #call function to perform operation
 UpdateKey $_ItemBagKey $_Operation $_NewValue $item


 #Dispose web object to release resources.
 $web.Dispose()

}
else
{
   Write-Host "List not found." -ForegroundColor Red;
}
}
catch
{
   # Add your exception handling routine here to trap and handle the exception details.
}