SharePoint Tools learned at ShareCamp

April 20, 2013

I had the opportunity to attend to ShareCamp in Microsoft München and hier are some interesting tools that I saw during the lessons:

Name Description
Search query tool Really nice tool for generating search queries against SharePoint 2013. You can see the xml and field names that come from SharePoint. Really helpful when creating custom search templates.
dotPeek A free alternative to .NET Reflector by JetBrains
PowerGUI A free tool like Powershell ISE but better.
IronSP Interesting tool for development for SharePoint in Ruby. Currently under development and not simple to use without deep knowledge of the project.
Collaboration Manager A commercial tool for managing SharePoint templates including upgrades. However it costs lots of money.

Hope you find this list helpful.

Fixing Metadata Field Connection after importing a Website to another Farm

April 10, 2013

This is a follow up to this post, where I described how you can create new website from template using Import-SPWeb. If you use managed metadata fields in the you will find out, that these fields cannot be used after importing of the website. The reason is, that the link to the managed metadata application is broken. This script will fix it:

$url = "http://yoursitecollection"
$termStoreName = "yourTermStoreName"
$termSetName = "nameOfTheLinkedTermSet"
$listName = "nameOfTheListWithManagedMetadataField"
$fieldName = "nameOfTheManagedMetadataField"

$web = Get-SPWeb $url

$session = Get-SPTaxonomySession -Site $url

$termStore = $session.TermStores[0]

$group = $termStore.Groups[$termStoreName]

$termSet = $group.TermSets[$termSetName]

$list = $web.Lists[$listName]
$field = $list.Fields[$fieldName]
$field.SspId = $termStore.Id

$field.TermSetId = $termSet.Id
$field.Update()

$list = $web.Lists[$listName]
$field = $list.Fields[$fieldName]

$taxonomyList = $web.Lists["TaxonomyHiddenList"]

$field.SchemaXml = $field.SchemaXml.Replace($field.LookupWebId.ToString(), $web.ID.ToString())
$field.SchemaXml = $field.SchemaXml.Replace($field.LookupList.ToString(), $taxonomyList.ID.ToString())
$field.Update()

$web.Dispose()

The script relinks the managed metadata field to the termstore and fixed the link to the webid and link to the taxonomy hidden list.

Custom templates using SP-ExportWeb

March 25, 2013

When creating custom templates for users, you have following possibilities:

  1. Create a template in Visual Studio
  2. Create a template website in SharePoint and save website as a template (wsp).
  3. Create a template website in SharePoint and save it with Export-SPWeb powershell command.

Each of this solutions has its drawbacks:

Ad 1. complex and time consuming solution, prone to errors.
Ad 2. Following features are not supported: Customized permissions, running workflow instances, list item version history, workflow tasks associated with running workflows, people or group field values, taxonomy field values, publishing pages and publishing sites, My Sites, and stapled features. See following article http://msdn.microsoft.com/en-us/library/jj938033.aspx#bkmk_WhatIsTemplate
Ad 3. the taxonomy fields in the website created from template in the different sharepoint farm will be broken.

As the title suggests I will describe the third option in this article.

Creating the template

  1. Create your template in SharePoint. (Activate the features, add lists, fields and documents)
  2. Open the Powershell console and execute following command:

Export-SPWeb http://yoursite–Path "c:\temp\export.cmp"

Creating a website from the template
Create new empty website and use the Import-SPWeb to import the content from the file:
New-SPSite http://newsiteurl/ -OwnerAlias "loginname" -Name "newWebSiteName"
Import-SPWeb http://newsiteurl/ -Path "c:\temp\export.cmp" -IncludeUserSecurity

The advantage of this approach is, that if you create a new version of the template you can reimport it on an existing website. The changes in the new template will be merged with the changes in the existing website made by the users . However I recommend to create a backup from the website before reimporting.

There are two things  that remain open:

  1. The metadata fields will not be relinked to the termsets after importing into another farm.
  2. The “Self Service Creation”-like functionality is missing. There is some development that needs to be done.

Maybe next time.

 

Announcement

March 25, 2013

Recently me and my friend Radek Matouch  started a new company. We focus on development and consulting in SharePoint  and .NET. Check out our website www.codeeffect.cz if you are interested and wish us luck . ;-)

High Trusted SharePoint Application Gotchas

December 10, 2012

I followed this guide and this guide to create a demo high trust applications and here’s the summary of things the I came across:

Problem
Cannot deploy the solution in general.
Fix:

  1. You cannot be logged on as sharepoint\system. Log on as another user to the server.
  2. You have to start Visual Studio Administrator (Right Click “Run as administrator” command)

Problem
Cannot deploy the solution with error: Error occurred in deployment step Uninstall App for SharePoint’: ‘Cannot connect to the sharepoint site
Fix
The current user does not have permissions on the SharePoint Config Database and Content Database. Give the user owner permissions on these two databases.

Problem
Cannot deploy the solution with error: Error occurred in deployment step ‘Install app for SharePoint’: The provided App differs from another App with the same version and product ID.
Fix
Open manifest.xml in code view and generate new guid for the app.

Problem
Cannot deploy the solution with error: Error occurred in deployment step ‘Install app for SharePoint’: We’re sorry, we weren’t able to complete the operation, please try again in a few minutes. If you see this message repeatedly, contact your administrator.
Fix
The current user has to have owner permissions on the App_Management Database.

Problem
Problem when trying to debug: Unable to launch IIS Express Web Server
Fix
Switch to full IIS.

  1. Open Properties of the AppWeb Project and uncheck the checkbox “Use ISS Express” on the “Web” app.
  2. Click Create new Virtual Directory on the same tab.
  3. Assign “full control” permissions on the folder for the application pool account.

Problem
Cannot connect to https://localhost
Fix
I did not configure IIS to run with https. I had  to change the manifest.xml of the app to replace the ~remoteAppUrl to http://localhost .

Problem
Could not load file or assembly ‘Microsoft.IdentityModel, Version=3.5.0.0 TypeInitializerException System.Runtime.InteropServices.COMException: The handle is invalid. (Exception from HRESULT: 0×80070006 (E_HANDLE))
Fix
The application pool was running in .NET Framework Version 2.0. Should be 4.0. You can change this directly in the IIS in the application pool settings.

 

Multilanguage in Navigation using Webtemplate does not work

May 15, 2012

I created a webtemplate (http://msdn.microsoft.com/en-us/library/ms434313.aspx) in SharePoint and added following localized Navigation Bar to the top the navigation in the onet.xml:

<NavBar Name="$Resources:osrvcore,SspAdministrationTopNavBarTitle;" ID="1002">
<NavBarLink Name="$Resources:osrvcore,HelpText;" Url="default.aspx" />
 </NavBar>

then I created a web site based on the template and turned the multilanguage on.

The problem is that the navigation bar stays always in one language and is never localised to current language of the website. If I use the same xml file in the sitetemplate everything works correctly.

The problem is recognized as designed by Microsoft and there is only workaround available.

Solution

  1. Delete the navigation from the onet.xml
  2. Recreate the Navigation with code.

Creating the navigation programmatically

  • Create the xml file called navigation.xml with the navigation and let it be deployed to the layouts folder. The file should have following structure:
</div>
<?xml version="1.0" encoding="utf-8" ?>
<NavBars>
<NavBar Template="templatename">
<NavBarLink Url="$Resources:cmscore,List_Pages_UrlName;/page1.aspx" Name="$Resources:osrvcore,HelpText"/>
 <NavBarLink Url="$Resources:cmscore,List_Pages_UrlName;/page2.aspx" Name="$Resources:osrvcore,HelpText"/>
</NavBar>
</NavBars>
  • Load the xml file:
public IList<NavigationNode> GetNavigation(string templateName)
{
{
var fileName = SPUtility.GetGenericSetupPath("TEMPLATE\\LAYOUTS\\navigation.xml");
var navigation = new List<NavigationNode>();
var data = new XmlDocument();
data.Load(fileName);
var xpath = string.Format("/NavBars/NavBar[@Template='{0}']/NavBarLink", templateName);
var nodes = data.SelectNodes(xpath);

foreach (XmlNode node in nodes)
{
navigation.Add(new NavigationNode
{
Name = node.Attributes["Name"].Value,
Url = node.Attributes["Url"].Value
});
}

return navigation;
}
}
  • Add the navigation nodes to the top navigation. There is also handling if the url contains resources that have to be replaced
foreach (var navigationNode in GetNavigation(templatename))
{
var parsedUrl =  ParseNavigationUrl(navigationNode.Url, web.Language);
var spNavigationNode = new SPNavigationNode(navigationNode.Name, parsedUrl, true);
web.Navigation.TopNavigationBar.AddAsLast(spNavigationNode);
}
private static string ParseNavigationUrl(string url, uint language)
{
var resourceExpression = GetResourceExpressionFromString(url);
if (string.IsNullOrEmpty(resourceExpression))
return url;
var localizedString = SPUtility.GetLocalizedString(resourceExpression, string.Empty, language);           return url.Replace(resourceExpression, localizedString);
}
private static string GetResourceExpressionFromString(string text)
{
if (string.IsNullOrEmpty(text))
return string.Empty;
var dollarIndex = text.IndexOf("$");
var semicolonIndex = text.IndexOf(";");
if ((dollarIndex == -1) || (semicolonIndex == -1))
return string.Empty;
return text.Substring(dollarIndex, semicolonIndex - dollarIndex + 1);
}

SharePoint 2013 v15 What’s new?

May 2, 2012

I recently found following document SharePoint 15 Technical Preview Interoperability API Documentation. Here can we find some parts of the new SharePoint 15 API.

Here are some information, which you could find interesting. Please keep in mind, that what I write here are only guesses and I can be totally wrong.

Market place

I found following classes: SPApp, SPAppCatalog, SPAppInstance. These new classes suggest that Microsoft will release a market place for the next version of SharePoint. What role will be playing Sandboxed Solution. There exists even a licensing model for the marketplace. The SPWebapplication was extended with the method IsUserLicensedForEntity. The Application will be loaded into SPWeb according to the methods SPWeb.LoadAndInstallApp. You can read more about it here. However in czech.

Extensive usage of JSON

There are following new classes JsonReader, SPFieldServerStub, SPFieldLookupServerStub. These classes contain methods for creating and reading JSON objects. So it will be possible to read information about field in Javascript.

SPFieldLookup.GetJsonClientFormFieldSchema

Details: Gets an object containing field schema information for client rendering.

So we can read also the information about the field definition in Javascript.

SPFileRightsManagementSettings

New Dataholder for SPFile properties. The  class has  following properties:

  • AllowPrint Gets or sets a value indicating whether the viewer can print the document.
  • AllowScript Gets or sets a value indicating whether the viewer can run script on downloaded document.
  • AllowWriteCopy Gets or sets a value indicating whether the viewer can write on a copy of the downloaded document.
  • DocumentAcceExpireDays Gets or sets the number of days before a downloaded document will expire
  • GroupName Gets or sets the group name (email address) to which the permission applies.

SPSite.CompatibilityLevel

Gets the major version of this site collection for purposes of major version-level compatibility checks. For which version is the Site Collection designed?

SPUtility.GetLayoutsFolder

Returns the versioned layouts folder for the specified site collection.

According to this we can have different versions of laouts folder for different webs. The laouts folder is not Farm scoped anymore.

OAuth

Class SPOAuth2BearerCredentials and namespace Microsoft.SharePoint.IdentityModel.OAuth2. Support of OAuth2 like Windows Live ID, Twitter, Facebook?

ClientContext extensions

Microsoft.SharePoint.Client.Search.Query

We can start search queries directly from the Client Object Model

Microsoft.SharePoint.Client.Search.SearchExecutor

We can start multiple search queries  in batch.

Microsoft.SharePoint.Client.File

OpenBinaryStream:  We can open the file from server on the client.

 

 

Custom Solutions on Multiple Server SharePoint Farm

April 23, 2012

Consider following basic Farm Configuration

The Web Frontend Server processes the requests and the application server is designated for other applications like search. According to Microsoft best practices you should turn off the “Microsoft SharePoint Foundation Web Application” service on the application server.

If you do this and you have a solution that contains web, site or webapplication scoped features your solution will be deployed only on the web front end server. This is pretty bad if you have timer jobs that should run on the application server. The dlls on the application server are missing and the timerjob will fail.

Here are your options:

  1. Turn the “Microsoft SharePoint Foundation Web Application” role on again. The drawback is that you in this do not follow the best practices from Microsoft. The other drawback ist that the web applications will take resources on the App Server (RAM, Applicaiton pools)
  2. Turn of the timer job service on the application server. The drawback is that you actually disable the application server and change the farm to single farm solution.
  3. Split the solutions
Split the solution into two separate solutions.

The first solution will contain the farm timer jobs and farm scoped features and will be deployed globally. It means also on the application server. The other solution will contain all web, site or webapplication scoped features and will be deployed into your web application as before.

One thing you have to do is to change the deployment type of the farm scoped solution to Application Server. Open the package folder in the solution and in the properties window change the deployment server type to ApplicationServer. See screenshot

The other nice thing that you could do is to create an activationdependency from the WFE soltuion to the APP server solution.


Google Id/Windows Authentication in SharePoint 2010 using Windows Azure

December 11, 2011

In this article I will describe how to enable signing in using Google Id, Windows Open Id, Facebook or Yahoo account to a SharePoint 2010 site collection. As authentication provider I will use Windows Azure Platform.
Here are the steps you have to do:

Configure the Azure platform

  1. Create an account on Windows Azure Platform using your Windows Live Id. There is 90 days evaluation period available on Windows Azure that is free, additionaly the Access Control Services I will use as authnetication provider are free at least until December 2012. During the registration process you will be however asked to fill in you credit card number. For more information about pricing see this.
  2. After you created your azure account go to the Windows Azure management portal  https://windows.azure.com/.
  3. In the portal click “Services Bus, Access Control & Caching ” and then “Access Control”. See following picture
  4. Click new to create a new namespace and select a unique name for the namespace and the region where your server exists and click “Create namespace” button
  5. Wait until the namespace is activated. It takes several minutes
  6. Click the newly created namespace and then “Access Control Service”
  7. Click “Identity providers” and add the providers that should be used in your SharePoint site collection for the authentication. See folllowing image.
  8. Click Relying party application button in the left tab and add a new Relying application and fill the form as marked in the following image. The url should be the url of your sharepoint web application.
  9. Also check the “Create new rule group”
  10. Now click the “Rule groups” and click Generate. The form should look like this afterwards:
  11. Click save.
  12. Click  “Application Integration” under “Development” tab. Then “Login pages” and then your relying service application.
  13. Copy the content of the textbox und option 1. It should look like this https://yournamespace.accesscontrol.windows.net:443/v2/wsfederation?wa=wsignin1.0&wtrealm=http%3a%2f%2fsharepoint2010%2f
  14. For now you are done with the azure platform configuration. Now go to your SharePoint server where should be the claims authentication enabled.

Create and export new certificate

  1. Run following command “MakeCert.exe -r -pe -n “CN=<yournamespace>.accesscontrol.windows.net” -sky exchange -ss my”. The Makecert.exe can you find in this folder: C:\Program Files\Microsoft Office Servers\14.0\Tools
  2. Here http://msdn.microsoft.com/en-us/library/gg185932.aspx  you can find a description how to export the newly created certificate for the communication betwen SharePoint and Azure.
  3. Once you have the file go back to Azure platform to your namespace and click “Certificates and keys” and click “Add” button in the “Token signing” section.
  4. Upload the exported certificate and leave the other setings to default

Configure SharePoint to use claims
Run following script. Replace following things:

  1. Path to the certificate
  2. Password of the certificate
  3. $realm (it is the Url you gave in the Relying Application Settings as Realm). Mind the slashes.
  4. $signinurl It is the url from step 17
  5. The names of the providers.

Add-PSSnapin "Microsoft.SharePoint.PowerShell"

$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("yourcertificatename.pfx","yourpassword")

$map1 = New-SPClaimTypeMapping "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" -IncomingClaimTypeDisplayName "Email" -SameAsIncoming

$realm = "http://sharepoint2010/"

$signinurl = "https://yournamespace.accesscontrol.windows.net:443/v2/wsfederation?wa=wsignin1.0&wtrealm=http%3a%2f%2fsharepoint2010%2f"

New-SPTrustedIdentityTokenIssuer -Name "Azure ACS" -Description "Windows Azure ACS v2" -Realm $realm -ImportTrustCertificate $cert -ClaimsMappings $map1 -SignInUrl $signinurl -IdentifierClaim $map1.InputClaimType

New-SPTrustedRootAuthority -Name "Azure Test Token Signing" -Certificate $cert

$issuer = Get-SPTrustedIdentityTokenIssuer
$authority = Get-SPTrustedRootAuthority
$issuer.ProviderUri = $signinurl
$issuer.Update

Check if the things work:

  1. Open central administration and open Web application
  2. Click Create new Web application
  3. Switch to claims authentication
  4. Check the “Azure ACS”
  5. Create new web application
  6. Create new site collection
  7. Set the permissions on the site collection that the users have access to the site collection
  8. Log in with your Google Id to the site collection

References:  Travis Nielsen blog

Creating Secure Store Service Application through Powershell

November 24, 2011

SSSA is a good way how to store credentials for accessing external systems.
Here is a script that will help you to create such a service application through powershell.
Thanks to the codeplex project autospinstaller for the inspiration.

Add-PsSnapin Microsoft.SharePoint.PowerShell
$serviceApplicationPool  = "SecurityTokenServiceApplicationPool" #name of the application pool under which the application should run
$secureStoreDatabaseName  = "SecureStoreServiceDatabase" #the sharepoint database where the service app will store the data
$secureStoreApplicationName  ="Secure Store Service Application" #name of the service application
$secureStoreApplicationProxyName  ="Secure Store Service Application Proxy" #name of the service application proxy
$secureStoreAdministrator = "domain\administrator" #the administrator of the application
$secureStoreUser = "domain\user" #the group or user that will have access to service application. I use the group configuration
$secureStoreAdministratorEmail = "adminemail" #email of the administrator
$serviceContext = "http://localhost" # the url for getting the service application context
$targeApplicationUserName= "administrator" #user name which will be used to access the external application
$targetApplicationUserPassword = "password"
#password which will be used to access the external application
$passPhrase = "PassPhrase" #passphrase for securing the application

If ($secureStoreApplicationName -eq $null) {$secureStoreApplicationName = "State Service Application"}
# Get the service instance
$SecureStoreServiceInstances = Get-SPServiceInstance | ? {$_.GetType().Equals([Microsoft.Office.SecureStoreService.Server.SecureStoreServiceInstance])}
$SecureStoreServiceInstance = $SecureStoreServiceInstances | ? {$_.Server.Address -eq $env:COMPUTERNAME}
If (-not $?) { Throw " - Failed to find Secure Store service instance" }
# Start Service instance
If ($SecureStoreServiceInstance.Status -eq "Disabled")
{
	Write-Host  " - Starting Secure Store Service Instance..."
	$SecureStoreServiceInstance.Provision()
	If (-not $?) { Throw " - Failed to start Secure Store service instance" }
	# Wait
	Write-Host  " - Waiting for Secure Store service..." -NoNewline
	While ($SecureStoreServiceInstance.Status -ne "Online")
	{
	   Write-Host  "." -NoNewline
		Start-Sleep 1
		$SecureStoreServiceInstances = Get-SPServiceInstance | ? {$_.GetType().ToString() -eq "Microsoft.Office.SecureStoreService.Server.SecureStoreServiceInstance"}
		$SecureStoreServiceInstance = $SecureStoreServiceInstances | ? {$_.Server.Address -eq $env:COMPUTERNAME}
	}
	Write-Host  $($SecureStoreServiceInstance.Status)
}
			# Create Service Application
			$GetSPSecureStoreServiceApplication = Get-SPServiceApplication | ? {$_.GetType().Equals([Microsoft.Office.SecureStoreService.Server.SecureStoreServiceApplication])}
			If ($GetSPSecureStoreServiceApplication -eq $Null)
			{
				Write-Host  " - Creating Secure Store Service Application..."
				New-SPSecureStoreServiceApplication -Name $secureStoreApplicationName -PartitionMode:$false -Sharing:$false -DatabaseName $secureStoreDatabaseName -ApplicationPool $serviceApplicationPool -AuditingEnabled:$true -AuditLogMaxSize 30 | Out-Null
				Write-Host  " - Creating Secure Store Service Application Proxy..."
				Get-SPServiceApplication | ? {$_.GetType().Equals([Microsoft.Office.SecureStoreService.Server.SecureStoreServiceApplication])} | New-SPSecureStoreServiceApplicationProxy -Name $secureStoreApplicationProxyName -DefaultProxyGroup | Out-Null
				Write-Host  " - Done creating Secure Store Service Application."
			}
			Else {Write-Host  " - Secure Store Service Application already provisioned."}

			$secureStore = Get-SPServiceApplicationProxy | Where {$_.GetType().Equals([Microsoft.Office.SecureStoreService.Server.SecureStoreServiceApplicationProxy])}
			Start-Sleep 5
			Write-Host  " - Creating the Master Key..."
			Update-SPSecureStoreMasterKey -ServiceApplicationProxy $secureStore.Id -Passphrase $passPhrase
			Start-Sleep 5
			Write-Host  " - Creating the Application Key..."
			Update-SPSecureStoreApplicationServerKey -ServiceApplicationProxy $secureStore.Id -Passphrase $passPhrase -ErrorAction SilentlyContinue

$usernameField = New-SPSecureStoreApplicationField –Name “UserName” -Type UserName –Masked:$false
$passwordField = New-SPSecureStoreApplicationField –Name “Password” –Type Password –Masked:$true
$fields = $usernameField,$passwordField

$adminClaim = New-SPClaimsPrincipal –Identity $secureStoreAdministrator –IdentityType  WindowsSamAccountName
$userClaim = New-SPClaimsPrincipal –Identity $secureStoreUser –IdentityType  WindowsSamAccountName
$targetApp = new-spsecurestoretargetapplication -name "externalApplication" -friendlyname "externalApplication" -contactemail $secureStoreAdministratorEmail -applicationtype Group -timeoutinminutes 3
$ssApp = New-SPSecureStoreApplication –ServiceContext $serviceContext –TargetApplication $targetApp –Field$fields –Administrator $adminClaim -CredentialsOwnerGroup $userClaim
$firstCredential = ConvertTo-SecureString $targeApplicationUserName –AsPlainText –Force
$secondCredential = ConvertTo-SecureString $targeApplicationUserPassword –AsPlainText –Force
$credentialValues = $firstCredential,$secondCredential
Update-SPSecureStoreGroupCredentialMapping  –Identity $ssApp –Values $credentialValues

Follow

Get every new post delivered to your Inbox.