Tuesday, January 7, 2014

Resolving error “Sorry, something went wrong An update conflict has occurred, and you must re-try this action” in SharePoint 2013

Recently I came across the following error message when trying to modify diagnostic logging categories in central administration.

image

This has occurred because of the file system cache (config cache) in SharePoint server is corrupted (having newer version than the source, which is the configuration database).

What is the file system cache (config cache)?

Config cache is where the objects from config db like timer job descriptions, features etc,, are cached locally so SharePoint does not need to query the configuration db every time. The cache is updated by a timer job.

The cache is located in “%SystemDrive%\ProgramData\Microsoft\SharePoint\Config\<GUID>” folder. You can see a set of xml files for purposes like

  • Timer job descriptions to be executed by the local SharePoint server using the timer service.
  • Descriptions on farm features.

image

How to resolve the error

To resolve error we need to clear and build the config cache manually. follow the steps given below to do that.

  1. Stop the SharePoint Tmer service in every server that runs SharePoint in the farmimage
  2. Go to the cache location and take a backup of the folder (folder with the Guuid)
  3. Delete all xml files inside the folder and do not delete the cache.ini (This is a hidden file. So you may need to edit folder options to see the file)
  4. Open the cache.ini file . remove existing value and enter the value 1image 
  5. Save cache.ini file
  6. Do this process for all servers running SharePoint.
  7. Start timer service in all servers running SharePoint.

If the cache clearing task is successful, new set of xml files should be generated automatically and the value of the cache.ini file should be modified (no longer 1)

That’s all. Now your cache should be consistent with the configuration db

Saturday, January 4, 2014

Service application architecture – Basic concepts

This is the beginning of a series of articles on service applications in SharePoint.

In this post I will cover some basic concepts about service applications. Although some topics like history and differences between old SSP model and service application model are omitted as there are enough resources available.

Following are the important keywords we should know

  • Service application instance : Actual instance of the service (binaries) running on the server
  • Service application : Logical component that contains the service configuration and management (e.g.: service application configuration info)
  • Service application connection : Interface used by the service consumers for communicating with the service and the load balancer
  • Service application proxy group : Group of service application connections associated with web applications

In this post I will present some scenarios where we can use above concepts differently.

1. One service application instance, one service application, one service application connection, one service application proxy group and one or more web applications

image

2. Multiple service applications with one service application instance and one service application connection for each, one service application proxy group and one or more web applications

image

3. Multiple service applications with one service application instance a for each, multiple service application proxy group and one or more web applications

image

4. Service applications with multiple service application instances

image

Tuesday, December 17, 2013

Fix Content Type Publishing : The compatibility level 14 of the content type hub site is different from the compatibility level of this site 15.

After we migrate from SharePoint 2010 environment to a SharePoint 2013 environment, we need to follow few post upgrade steps.

Let’s assume we had a content type hub site collection where other sites subscribe to consume content types. You can learn more on Content Types and Content Type publishing through a content type hub by referring this article

After we migrate, our content type hub site collection is still in the 14 compatibility mode (SharePoint 2010 mode). Since it in the old compatibility level, newly created site collections (SharePoint 2013 mode) can’t subscribe to the content type hub.

To fix the issue we need to either create a new Content Type Hub site collection or upgrade the existing site collection. Following are the steps required to upgrade/create content type hub site collection

1. Upgrade the content type hub site collection

You can either do it manually or by PowerShell statements

  1. Upgrade-SPSite "http://sp13/sites/hub" -VersionUpgrade -QueueOnly

2. Check/ Change the content type hub Url.

This step is not mandatory. But let’s assume we need to keep the existing content type hub site collection in 14 mode, and need to create a new site collection for the new environment. In that case we will skip the 1st step.

  • Create new site collection
  • Create content types as available in the old content type hub site collection
  • Enable the “Content Type Syndication Hub” site collection feature
  • Use following PowerShell statement to make the new site collection as the
  1. $newContentHub = "http://sp13/sites/hub15"
  2. $mms = Get-SPServiceApplication -Name "Managed Metadata Service"
  3. Set-SPMetadataServiceApplication -Identity $mms -HubURI $newContentHub

3. Publish/ Republish Content Type Hub.

Since we changed the content type hub site collection, we need to publish or republish content types those need to be published to other sites.

image

4. Run required timer jobs

We need to run two timer jobs to make the changes reflect in subscribed sites. In central administration go to Monitoring > Review Job Definitions to select timer jobs.

  • Select the timer job “Content Type Hub” and click Run Now
  • Select the timer job “Content Type Subscriber” for the web application and cluck Run Now. If you have multiple web applications those are subscribed to content type hub, you have to run the Content Type Subscriber jobs for all of them

Monday, December 2, 2013

Reusing SharePoint custom service application proxy groups

When we create a new web application, we need to associate it with a service application proxy group. Either we can associate it with default proxy group or a custom group
image
Let’s say we need to create 2 web applications those require only Managed Metadata Service as a service application. In that case we need to go for a custom proxy group.
If we create those web applications using custom proxy group we can see 2 separate “Custom” proxy groups created.
Although they contain same service application proxies, We can’t reuse the groups by default. In that case if we need to associate a new service application proxy, we need to add it to each and every “Custom” group.
image
Is there any way to create named proxy groups where we can reuse for our web applications ?
We can use PowerShell cmdlets to create named proxy groups and add member service application proxies. Let’s say we create a proxy group named “Contoso” and we need only “Managed Metadata Service” for that group. Then we’ll need to provide following PowerShell commands.
New-SPServiceApplicationProxyGroup "Contoso"
$mmsproxy = Get-SPServiceApplicationProxy | where { $_.Name -eq “Managed Metadata Service” }
Add-SPServiceApplicationProxyGroupMember "Contoso" -Member $mmsproxy
Then we can see our group listed when we create a new web application (or changing the Service Application Association setting)
image
We can associate our existing sites using the Service Application Association section.

image
Now it looks very organized. If we need to associate new proxies we can add/remove them from our named proxy group which will be reflected for all associated web applications.

Tuesday, November 19, 2013

Add content and web parts to wiki page programmatically

When we provision sites and pages programmatically we may need to add or modify content to wiki pages as well. Although it is not a good practice to add web parts to the wiki field, some times it is the only option we have.

Following is a code sample where we can add content to a wiki page. We can use a feature receiver to do the task

  1. public override void FeatureActivated(SPFeatureReceiverProperties properties)
  2. {
  3.     var web = properties.Feature.Parent as SPWeb;
  4.     web.AllowUnsafeUpdates = true;
  5.  
  6.     //Add Shared Documents webpart
  7.     var sharedDocuments = web.Lists.TryGetList("Shared Documents");
  8.     var sharedDocWP = new XsltListViewWebPart();
  9.     sharedDocWP.ListId = sharedDocuments.ID;
  10.     sharedDocWP.Title = "Shared Documents";
  11.     sharedDocWP.ChromeType = PartChromeType.TitleOnly;
  12.     sharedDocWP.ID = Guid.NewGuid().ToString();
  13.     var homePage = web.GetFile("SitePages/Home1.aspx");
  14.  
  15.     // Replace the current wiki page content
  16.     GenerateNewWikiContent(homePage, sharedDocWP);
  17.     web.Update();
  18. }

Following is the method to add html content and serialized web part to the page. We can use several StringBuilders to create the content and finally assign to the WikiField property.

  1. public static void GenerateNewWikiContent(SPFile wikiFile, WebPart webpart)
  2. {
  3.     var stringBuilder = new StringBuilder("");
  4.     var pageColumn1 = new StringBuilder("");
  5.     var pageColumn2 = new StringBuilder("");
  6.     stringBuilder.Append("<table id='layoutsTable' style='width: 100%'><tbody><tr style='vertical-align:top'>");
  7.  
  8.     //Content for column 1
  9.     pageColumn1.Append("<td style='width: 66.6%'><div class='ms-rte-layoutszone-outer' style='width:100%'><div class='ms-rte-layoutszone-inner' style='min-height:60px;word-wrap:break-word'>");
  10.     pageColumn1.Append(" <h1 class='ms-rteElement-H1B'  style='margin-bottom: 0px;'><span><span>Welcome to your site!</span></span></h1>");
  11.     pageColumn1.Append("<p>Add a new image, change this welcome text or add new lists to this page by clicking the edit button above. You can click on Shared Documents to add files or on the calendar to create new team events. Use the links in the getting started section to share your site and customize its look.</p>");
  12.     pageColumn1.Append("<p/><br/>");
  13.  
  14.     //Deleting existing Wiki Content
  15.     wikiFile.Item[SPBuiltInFieldId.WikiField] = string.Empty;
  16.     wikiFile.Item.UpdateOverwriteVersion();
  17.  
  18.     using (var limitedWebPartManager = wikiFile.GetLimitedWebPartManager(PersonalizationScope.Shared))
  19.     {
  20.         var storageKey = Guid.NewGuid();
  21.         var strStorageKey = "g_" + storageKey.ToString().Replace('-', '_');
  22.  
  23.         webpart.ID = strStorageKey;
  24.         limitedWebPartManager.AddWebPart(webpart, "wpz", 0);
  25.         var webPart = string.Format(CultureInfo.InvariantCulture,
  26.                                     "<div class='ms-rtestate-read ms-rte-wpbox' contentEditable='false'><div class='ms-rtestate-read {0}' id='div_{0}'></div><div style='display:none' id='vid_{0}'/></div>",
  27.                                     new object[] { storageKey.ToString("D") });
  28.         pageColumn1.Append(webPart);
  29.         pageColumn1.Append("</div></div></td>");
  30.  
  31.         //Content for column 2
  32.         pageColumn2.Append(
  33.             "<td style='width: 33.3%'><div class='ms-rte-layoutszone-outer' style='width: 100%'><div class='ms-rte-layoutszone-inner' style='min-height: 60px; word-wrap: break-word'>");
  34.         pageColumn2.Append("<p class='ms-rteThemeForeColor-5-5' style='text-align:left;font-size:10pt;' >");
  35.         pageColumn2.Append(
  36.             "<img style='margin:5px;' alt='People collaborating' src='/_layouts/images/homepageSamplePhoto.jpg' />");
  37.         pageColumn2.Append("</p>");
  38.  
  39.         pageColumn2.Append("</div></div></td>");
  40.  
  41.         stringBuilder.Append(pageColumn1.ToString());
  42.         stringBuilder.Append(pageColumn2.ToString());
  43.         stringBuilder.Append("</tr></tbody></table><span id='layoutsData' style='display: none'>false,false,2</span>");
  44.         wikiFile.Item[SPBuiltInFieldId.WikiField] = stringBuilder.ToString();
  45.         wikiFile.Item.UpdateOverwriteVersion();
  46.         wikiFile.Item.Update();
  47.     }
  48. }

Following is the page output

image

Thursday, November 14, 2013

Presentation–Logical architecture considerations for SharePoint 2013

Recently I did a presentation at Sri Lanka SharePoint forum regarding how to design the logical architecture for new and existing SharePoint 2013 environments.

1450839_10151871096182530_689902513_n

There are some best practices influenced by SharePoint online regarding the logical architecture. We discussed how web applications, sites and other components are created in SharePoint online and how we can create a similar environment.

Monday, November 4, 2013

Encrypt values of a column - SQL Server

We can use T-SQL EncryptByKey method to encrypt data in a specific column and DecryptByKey method to decrypt that. In this post I’ll explain how to use those methods.
As the first task we will create a symmetric key and a certificate as below.
USE Staff;
GO

CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'Passwordabcd';
GO
CREATE CERTIFICATE Prod_Cert WITH SUBJECT = 'Key Protection';
GO

CREATE SYMMETRIC KEY My_Key WITH
    KEY_SOURCE = 'This is the symmetric key',
    ALGORITHM = AES_256, 
    IDENTITY_VALUE = 'This is the symmetric key'
    ENCRYPTION BY CERTIFICATE Prod_Cert;
GO

-- Create a column in which to store the encrypted data.
ALTER TABLE dbo.Employee
ADD EncryptedAge varbinary(128); 
GO
After that we can insert/update data to the column we just created while encrypting the data.
USE Staff;
GO

OPEN SYMMETRIC KEY My_Key
   DECRYPTION BY CERTIFICATE Prod_Cert;

UPDATE dbo.Employee
SET EncryptedAge
    = EncryptByKey(Key_GUID('My_Key'), 'my new value');
GO
Values in the column are encrypted as below.

image
Use below query to decrypt the value
OPEN SYMMETRIC KEY My_Key
   DECRYPTION BY CERTIFICATE Prod_Cert;
GO

SELECT Name, EncryptedAge 
AS 'Encrypted Age',
CONVERT(varchar, DecryptByKey(EncryptedAge)) 
AS 'Decrypted Age'
FROM dbo.Employee;

GO
You can get the decrypted value as below

image