Category Archives: Software Development

The main theme of this blog: SharePoint, C#, ASP.NET, yada, yada

SharePoint Authentication and Session Management

What is authentication?

1. A security measure designed to protect a communications system against acceptance of a fraudulent transmission or simulation by establishing the validity of a transmission, message, or originator.
2. A means of identifying individuals and verifying their eligibility to receive specific categories of information.

Authentication is essentially the process of validating a user is who they say they are, such that they can gain access to a system – in this context, the system is SharePoint. Authentication is not authorization, which is the process in determine if a known user is permitted access to certain data in the system, after successful authentication.

SharePoint, much like any content management system, relies on user authentication to provide user access to secured content. Pre-SharePoint 2010, SharePoint relied on NTLM, Kerberos, or basic (forms-based) authentication protocols (their discussion out of scope of this text). SharePoint 2010 introduced Claims-based-Authentication (CBA), also present in SharePoint 2013. CBA consists of authentication abstraction, using a Secure Token Service (STS), and identification of users with multiple attributes –claims – not just the traditional username and password pair.

A Secure Token Service implements open standards. A typical STS implementation communicates over HTTPS, and packages user identity information (claim data) via signed and encrypted XML – Secure Assertion Markup Language (SAML). Examples of STS implementations are the STS engine in SharePoint 2010/2013, ADFS, and third party applications build using the Windows Identity Framework.

SharePoint Session Management

A user session in SharePoint 2010/2013 is the time in which a user is logged into SharePoint without needing to re-authenticate. SharePoint, like most secure systems, implements limited lifespan sessions – i.e. users may authentication with a SharePoint system, but they’re not authenticated with the system indefinitely. The length of user sessions falls under the control of session management, configured for each SharePoint Web Application.

SharePoint handles session management differently, depending on the authentication method in play (Kerberos, NTLM, CBA, Forms, etc.). This article discusses how SharePoint works with Active Directory Federated Services (ADFS) – an STS – to maintain abstracted user authentication and user session lifetime. The following is a sequence diagram of the default authentication and session creation process in SharePoint 2010/2013 when using CBA with ADFS.

The following is a summary of the authentication process, shown in the sequence diagram.

  1. A user requests a page in SharePoint from their browser this might be the home page of the site.
  2. SharePoint captures the request and determines that no valid session exists, by the absence of the FEDAUTH cookie.
  3. SharePoint redirects the user to the internal STS – this is important because the internal STS handles all authentication requests for SharePoint and is the core of the CBA implementation in SharePoint 2010/2013.
  4. Since we have configured SharePoint to use ADFS as a trusted login provider, the internal STS redirects the user to the ADFS login page.
  5. ADFS acquires credentials and authenticates the user.
  6. ADFS creates a SAML token, containing the user’s claims, as encrypted and signed.
  7. ADFS posts the SAML token to the internal SharePoint STS.
  8. The Internal STS saves the SAML token in the SAML Token Cache.
  9. SharePoint creates the FEDAUTH cookie, which contains a reference to the SAML token in the cache.
  10. The Internal STS redirects the user back to SharePoint, and then back to the original requested page.

Session Lifetime

The lifetime of a SharePoint session, when using ADFS, is the topic of much confusion. Ultimately, SharePoint determines whether a user has a current session by the presence of the FEDAUTH cookie. The default behavior of SharePoint is to store this persistent cookie on the user’s disk, with fixed expiration date. Before sending a new FEDAUTH cookie back to the user’s browser, SharePoint calculates the expiration of the cookie with the following formula:

SAML Token Lifetime – Logon Token Cache Expiration Window

The above values are important since they govern the overall lifetime of the FEDAUTH cookie, and hence the session lifetime. The following table describes each value and its source:

Configuration Value Description
SAML Token Lifetime This value, in minutes, is provided by the token issuer – ADFS. In the case of ADFS, each Relying Party configuration (one for each instance of SharePoint farm) has this value as part of the configuration.By default, SharePoint sets the session lifetime the same as this SAML token lifetime.

You can change this value using PowerShell and the ADFS command: Set-ADFSRelyingPartyTrust.

E.g.

Add-PSSnapin Microsoft.ADFS.PowerShell

Set-AdfsRelyingPartyTrust –TargetName “Relying Party Name” –TokenLifeTime 10

Logon Token Cache Expiration Window This value, in minutes, is provided by SharePoint STS and governs how long the SAML token remains active in the cache, and therefore how long the associated user session remains alive. For example, if ADFS sets the SAML Token Lifetime to 10 minutes and this value is set in the STS as 2 minutes then the overall SharePoint session lifespan is 8 minutes.

E.g.

$ap = Get-SPSecurityTokenServiceConfig

$ap.LogonTokenCacheExpirationWindow = (New-TimeSpan -minutes 2)

$ap.Update();

IIsreset

Sliding Session

A siding session is one where the session expiration time changes as a user interacts with the system. By default, SharePoint 2010/2013 does not offer sliding sessions. Each new session expires on a fixed time, based on the aforementioned formula, earlier in this text.

Use of a sliding session does not mean that we must compromise security. Should a user become inactive, a sliding session will timeout just as the fixed session, the main difference that a user can extend a sliding session with continued use of the SharePoint system.

Creation of sliding session requires configuration of the Relying Party in ADFS and the SharePoint Logon Token Cache Expiration. The following PowerShell configures the Relying Party to 60 minutes, which is the absolute maximum time that a session remains active should the user become inactive:

Add-PSSnapin Microsoft.ADFS.PowerShell
Set-AdfsRelyingPartyTrust –TargetName “Relying Party Name” –TokenLifeTime 60

The following PowerShell sets the Logon Token Cache Expiration in SharePoint STS, which forces the sliding session lifetime to 20 minutes.

$ap = Get-SPSecurityTokenServiceConfig
$ap.LogonTokenCacheExpirationWindow = (New-TimeSpan -minutes 40)
$ap.Update();
IIsreset

The above settings are only part of the solution. On their own we have a fixed session duration of 20 minutes, determined by the earlier mentioned formula subtracting the logon token cache expiration from the RP token lifetime. To make sure the session renews with continued activity, we must refresh the session (and FEDAUTH cookie), which we can achieve with an HTTP module. The following code is an excerpt to refresh the session with each HTTP request.

Persistent verses Session Cookies

By default, SharePoint stores the authentication/session (FEDAUTH) cookie as a persistent cookie on disk. This allows the user to close and reopen their browser and access SharePoint without having to re-authenticate. This behavior is not always desirable.

Fortunately, we can ask SharePoint to use in-memory cookies (session cookies) for the authentication (FEDAUTH) cookie, as follows:

$sts = Get-SPSecurityTokenServiceConfig
$sts.UseSessionCookies = $true
$sts.Update()
iisreset

SharePoint 2013 MCSD Beta MCSD Exams

I just signed up for the new SharePoint 2013 MCSD Beta exams 71-488 and 71-489. I managed to snag registration of these exams for free, with some promotions codes floating around the Internet.
Vlad has the codes posted on his blog – if you try them you migth be lucky to register for free, otherwise, the exams cost $150 a peice.

Unfortunately, there’s not a ton of material out there for study as yet (plug my book), as you’d expect with the exams in Beta.
Some of the topics in the beta exams require development skills and knowledge of Visual Studio. Vlad has included a summary of the study topics at the following locations:

Developing Microsoft SharePoint 2013 Core Solutions (71-488).
Developing Microsoft Sharepoint 2013 Advanced Solutions (71-489).

For those of you wondering the difference between 70-488 & 71-488; and 70-489 & 71-489…
Microsoft uses 71-xxx for Beta exams. Release of the official exam is scheduled for June and will use the 70-488 and 70-489 numbers.

If you pass the beta exams now, you won’t have to retake the official release versions after June.

Incase Vlad changes his blog, and for my study reference, the following is a list of the topics measured in each exam. Also check out these handy PDF (fillable) checklists I created…

70-488 Checklist
70-489 Checklist

71-488/70-488 – Skills Measured
 
Plan and Design SharePoint Sites (10-15 percent)
  • Manage the site life cycle.
    • This objective may include but is not limited to: create a delayed site collection, manage site collection disposition, identify inactive site collections, back up and archive site collection data
  • Create content types.
    • This objective may include but is not limited to: subscribe to published content types, choose appropriate content type creation, use Schema Development, create content types using Object Model, create site columns, use content type inheritance
  • Manage content type behaviors.
    • This objective may include but is not limited to: manage event receivers, manage workflow associations, manage policies, manage document templates
  • Implement site provisioning.
    • This objective may include but is not limited to: create site definitions, create web templates, implement feature stapling, implement custom provisioning code
Implement Authorization and Authentication (10-15 percent)
  • Implement user authentication.
    • This objective may include but is not limited to: create a custom claims provider, create a custom sign-in page, create a custom membership provider, package and deploy a custom claims provider, package and deploy a custom membership provider, authenticate a user from a client application
  • Implement application authentication and authorization.
    • This objective may include but is not limited to: use the SharePoint App TokenHelper class, specify the App permission request scope manifest and permission request manifest, specify permissions for Office Store Apps, specify permissions for Corporate Catalog Apps, specify permissions for remote apps to access SharePoint data
  • Plan and implement user authorization.
    • This objective may include but is not limited to: create custom role definitions, create custom permission levels, maintain permissions, implement impersonation, plan and implement anonymous access, create a custom role manager
Access and Manage Data (10-15 percent)
  • Design solutions to handle large amounts of data.
    • This objective may include but is not limited to: create efficient CAML queries and views, choose appropriate APIs, create and use indexed columns, use Object Model Overrides, use Content Iterator, implement cross-site queries
  • Access data contained in SharePoint.
    • This objective may include but is not limited to: access data using server-side object model, access data using client-side object model (CSOM), access data using REST API, access data using out-of-the-box Web Services, access data using a custom WCF (Windows Communication Foundation) service to facilitate integration with an existing application
  • Store configuration data.
    • This objective may include but is not limited to: implement a hierarchical data store, implement a property bag, implement web.config, implement SharePoint List, implement credential storage
Implement SharePoint Solutions (15-20 percent)
  • Manage SharePoint Object Life Cycle.
    • This objective may include but is not limited to: implement Object Life Cycle management for SPWeb, implement Object Life Cycle management for SPSite, implement Object Life Cycle management for other objects, implement Object Life Cycle management with Windows PowerShell, implement Object Life Cycle management for SPContext
  • Upgrade solutions and features.
    • This objective may include but is not limited to: implement versioning of features and solutions, upgrade features and solutions, implement assembly versioning, build components for in-process request routing
  • Determine a solution structure.
    • This objective may include but is not limited to: select feature scope and visibility, define feature dependencies, define solution dependencies, organize SharePoint project items, structure app packages
  • Create sandbox solutions.
    • This objective may include but is not limited to: scope features to constraints, identify SharePoint artifacts that can be used in sandbox, access data outside of Sandbox scope, configure and troubleshoot sandbox solution deployment, upgrade sandbox solutions, implement solutions validators
  • Create a no-code solution.
    • This objective may include but is not limited to: configure no-code customizations for the SharePoint 2013 platform, create XSLT for web parts, create and upload JavaScript files, create Display Templates
Implement the User Experience and Information Architecture (10-15 percent)
  • Implement branding.
    • This objective may include but is not limited to: incorporate designer outputs, use Design Manager functionality, apply custom themes, export the design, create Master Page, create a channel
  • Implement navigation.
    • This objective may include but is not limited to: create a custom navigation provider, create taxonomy-based navigation, create search-driven navigation, configure globalcurrent navigation
  • Customize UI elements.
    • This objective may include but is not limited to: customize the ribbon, customize the edit control block (ECB), customize the status bar and notifications, customize the modal dialog window, customize the upgrade notification, select areas for Focus on Content
Create Business Processes (10-15 percent)
  • Create event receivers and timer jobs.
    • This objective may include but is not limited to: plan the use of event receivers or timer jobs, create remote event receivers, create a work item timer job
  • Create SharePoint Designer workflows.
    • This objective may include but is not limited to: plan the type of workflow and associated forms (site, reusable, list, InfoPath), use custom actions, create workflow definition, create reusable workflows for content types, import and export Microsoft Visio workflows, export a workflow to a SharePoint solution
  • Create and deploy Microsoft Visual Studio workflows.
    • This objective may include but is not limited to: create custom actions, create a workflow definition, create external connectors, deploy a workflow as part of a SharePoint solution or app, upgrade a SharePoint 2013 Visual Studio workflow, plan the type of workflow and associated forms
Create Office Apps (10-15 percent)
  • Plan and design applications.
    • This objective may include but is not limited to: choose a hosting location, specify a starting location, specify a licensing model, specify permission requirements, select a user experience for apps
  • Create applications.
    • This objective may include but is not limited to: create provider-hosted applications, create auto-hosted applications, create SharePoint-hosted applications, apply chrome control
  • Package and deploy Apps.
    • This objective may include but is not limited to: package an application, publish to Corporate Catalog, publish to SharePoint store, publish to Windows Azure, manage trust relationship with other providers
  • Manage the App life cycle.
    • This objective may include but is not limited to: upgrade an application, remove an application, manage licensing, manage usage tracking
71-489/70-489 – Skills Measured
 
Design and Implement Search (15-20 percent)
  • Query Search.
    • This objective may include but is not limited to: build search queries using FQL (FAST Query Language) and KQL (Keyword Query Language), execute search queries using client-side object model (CSOM), Web Services, and REST
  • Customize search results.
    • This objective may include but is not limited to: create custom result sources, create display templates, create result types, create custom refiner definitions, implement query rules
  • Customize content processing.
    • This objective may include but is not limited to: feed external content types, implement content processing extensions (entity extraction), configure out-of-the box content processing, create content mappings
Implement  BCS (Business Connectivity Services) (10-15 percent)
  • Create a model.
    • This objective may include but is not limited to: optimize queries for performance and throttling, use naming conventions, use batching, create filters, implement methods, create associations
  • Create external content types.
    • This objective may include but is not limited to: use SQL data sources, use WCF (Windows Communication Foundation) Web Services, use oData, use.NET connector
  • Implement authorization and authentication.
    • This objective may include but is not limited to: use pass-through, use BCS Identity and User Identity, use a custom model
  • Create custom connectors.
    • This objective may include but is not limited to: implement methods (including Search), implement security trimming, implement configuration properties, implement caching, implement external event receiver
  • Access BCS data.
    • This objective may include but is not limited to: use BCS Web Parts, use BCS data in workflows, use BCS CSOM, use the server-side object model, use BCS REST
  • Implement client-side BCS.
    • This objective may include but is not limited to: use caching, use Microsoft Office apps, use Microsoft Visual Studio Tools for Office, use SQL replication, implement authorization and authentication
Implement User Profiles and Customize Social Workload (15-20 percent)
  • Manage user profile properties.
    • This objective may include but is not limited to: create and update user profile properties, update privacy filters, map properties to external data, use managed metadata term sets, update profile picture
  • Manage feeds.
    • This objective may include but is not limited to: use CSOM to follow documents, people, sites, get feeds, create posts, and manage Like, reply, mention, tag, link, add pictures
  • Access user profile data.
    • This objective may include but is not limited to: use CSOM, use the object model, use REST, use Web Services
Implement ECM (Enterprise Content Management) and WCM (Web Content Management) (15-20 percent)
  • Implement a multi-lingual site.
    • This objective may include but is not limited to: submit a page or batch of pages for translation, publish pages, create source and target labels, create channels, implement multi-language site navigation
  • Implement E-discovery.
    • This objective may include but is not limited to: create a new hold, integrate with Microsoft Exchange Web Services, specify content sources and Search criteria, export discovery sets, manage permissions for hold
  • Implement SEO (Search Engine Optimization).
    • This objective may include but is not limited to: create a site map, customize a site map, maintain SEO configuration properties, maintain robots.txt file, maintain SEO properties on term
  • Implement content management.
    • This objective may include but is not limited to: create information management policies, create content organizer rules, create document sets, create document ID providers
  • Implement a publishing page.
    • This objective may include but is not limited to: add field controls to a page layout, add web parts to a page layout, create a publishing page layout, inherit content types
Design for Performance and Troubleshooting (15-20 percent)
  • Design solutions to handle a high-traffic site.
    • This objective may include but is not limited to: combine images, implement caching, minimize number of queries, optimize JavaScript loading, use CDNs (Content Delivery Networks), create a scalable aggregator
  • Design client applications for performance.
    • This objective may include but is not limited to: leverage health score rules, optimize number of batch server requests, use client-side cache, minimize amount of data requested
  • Monitor and mitigate performance and scalability issues.
    • This objective may include but is not limited to: diagnose application stability issues, debug the server side and app code on the client side, create application diagnostics, measure and test application performance
Implement Managed Metadata Service (MMS) (15-20 percent)
  • Manage term sets.
    • This objective may include but is not limited to: import and export term sets, create multi-lingual labels, re-use terms, manage term properties, perform translation, create groups and assign permissions
  • Create solutions by using MMS.
    • This objective may include but is not limited to: use Profile Pages, use the Product Catalog, use cross-site publishing, integrate with Search, implement metadata-driven navigation
  • Use an MMS API.
    • This objective may include but is not limited to: use CSOM in client applications, use REST in client applications, use managed fields, use server-side object model

Creating External Content Types in SPD Preview 2013

I am using SharePoint Designer 2013 Preview. I recently tried to create a new External Content Type and ran into an issue when adding a data source. SharePoint Designer hangs “Loading Data Sources”. Fortunately, there’s a work-around…

Copy the following commands to a batch file and run it as an elevated administrator on the SPD machine:

reg add HKLMSOFTWAREMicrosoftStrongNameVerification*,71e9bce111e9429c /f
reg add HKLMSOFTWAREWow6432NodeMicrosoftStrongNameVerification*,71e9bce111e9429c /f
reg add HKLMSOFTWAREMicrosoftStrongNameVerification*,* /f
reg add HKLMSOFTWAREWow6432NodeMicrosoftStrongNameVerification*,* /f

Recycle the Windows Installer service (or start it if stopped).

You should be good to go.

Thanks to a user called Dalibor, for this info Winking smile

Configuring SharePoint 2013 for Windows Azure Workflow

SharePoint 2013 now abstracts workflow processing to the cloud – using Windows Azure Workflow (WAW). SharePoint still maintains the legacy workflow engine, as part of the .NET Framework 3.5.1, to enable execution of SharePoint 2010 workflows. However, SharePoint 2013 does not install WAW by default. The following steps detail additional configuration.

1. Ensure you are not installing on a domain controller – WAW integration does not work with SharePoint 2013 running on a single server domain controller

2. Create an account in your domain for WAW

3. Add this account to the local administrators group on the SharePoint server and grant log on locally permissions

4. Ensure the SQL server accepts connections via TCP/IP – use the SQL Server Configuration Manager tool

5. Provide the WAW account access to SQL Server, include create database permissions (or you could grant administrative permissions if you are brave)

6. Log onto the SharePoint server as that account

7. Install Workflow Beta 1.0 (http://technet.microsoft.com/en-us/library/jj193478), using the Web Platform Installer

8. After installation, you should see the WAW Configuration Wizard

9. Click to create a new farm, using custom settings

10. Configure databases and click the Test Connection button for each

11. Make sure the WAW service account is correct – use the fully qualified domain name (FQDN), by default it prepopulates the textbox with a non-FQDN

12. Provide certificate generation keys

13. Leave the ports as default

14. Check the checkbox to allow management over HTTP (if you choose to use HTTPS you will need to establish trust between SharePoint and WAW using a trusted certificate)

15. Click the next button to move onto configuring the service bus

16. Complete similar steps for database, service account, and certificates settings as you did above

17. Again, leave the ports as default

18. Review the summary page, then click the tick button to complete the configuration

19. Wait for the configuration to complete – this might take a little time

20. After WAW configuration completes, run the following PowerShell command:

Register-SPWorkflowService –SPSite "http://{sitecollectionurl}" –WorkflowHostUri "http://{workflowserve}:12291" –AllowOAuthHttp

21. Assuming no errors, you have now configured WAW in SharePoint 2013 for your site collection

More information on installing and configuring WAW is available at the following URL: http://technet.microsoft.com/en-us/library/jj658588%28v=office.15%29

SharePoint 2013 Managed Navigation

After much awaited anticipation, SharePoint 2013 now offers custom navigation of sites via the Managed Metadata Term Store. SharePoint 2010 introduced managed metadata for tagging purposes, with hierarchical terms. This same hierarchical infrastructure bodes well for site navigation, which is also hierarchical. I often hear the word “taxonomy” said a lot, pertaining to both tagging taxonomy and site structure, which just speaks to the fact that the Managed Metadata Term Store is great for managing custom navigation.

Prior to SharePoint 2013, custom navigation typically involved some custom component, to read navigation structure from either a list, XML file, or some other hierarchical node store. The out-of-the-box offering provided very little in the way of custom navigation – just the ability to include headers and links at each site level. The main issue with the out-of-the-box offering is that it was limited in the number of nested navigation nodes, without adhering to the actual structure of sites and sub-sites in the collection. Despite typical site navigation following site structure, content owners should have the ability to store their content (sites and pages) in any structure and the navigation look completely different. Content storage and structure suits how content owners maintain content, and navigation is about how end users access content, and the two may look very different. Managed Metadata Navigation finally allows content owners to create an independent navigation structure to that of their content model.

To demonstrate Managed Navigation, I shall first create a hierarchy in the default term store, for our application:

  1. Open Central Administration
  2. Click the link for managed service applications
  3. Scroll down the list and click the Managed Metadata Service
  4. Click the Manage icon in the ribbon to open the Term Store editor
  5. Ensure you have permissions to edit the term store – add your username to the term store administrators field
  6. Managed navigation binds to term sets, so I created a new group for navigation and then a term set for site navigation

SharePoint creates a default term set in the Managed Metadata Term Store for your site collection; I created my own for demonstration purposes.

  1. Create a term set structure
  2. Click the Site Navigation term set
  3. In the right panel, click the tab for Intended Use
  4. Check the checkbox to enable the term set for navigation – you can also use the term set for tagging if you wish by toggling the other checkbox option
  5. Click the save button to save the changes
  6. Click the tab for term driven pages – this page shows the settings for friendly URLs for the term set (more on friendly URLs shortly)
  7. Now we are ready to configure our publishing site to use the managed navigation
  8. Open your publishing site (assuming the hosting web application uses the managed metadata service you just configured)
  9. Click the gear icon, the select the menu item for site settings
  10. Click the link for Navigation, under the Look and Feel header
  11. SharePoint displays the navigation settings page
  12. Choose the radio button option for Managed Navigation for either or both the left and global (top) navigation
  13. Scroll to the bottom of the page to the managed navigation term set section
  14. Select the term set to use for managed navigation
  15. The checkboxes below the term set browser tell SharePoint whether to populate your term set with nodes when you create new pages in the site, and whether to generate friendly URLs for new pages
  16. Click the OK button at the bottom of the page, to save your changes

managednav2013

Synchronous Web Events

Triggering custom behavior, after sub-site (web) creation in SharePoint 2007, involved stapling a custom site feature to the site definition. SharePoint 2010 provides additional “web” events, which developers may bind custom event receivers and execute custom code.

Creating a new event receiver and binding to web events is a simple exercise in Visual Studio 2010 (Add a new event receiver item to a SharePoint project and specify the event).

I recently wrote a custom event receiver to provision content types in the Pages library of a publishing site at site creation – straight forward enough.  Everything worked great inside the debugger, but after deployment, SharePoint would kick back a synchronization error, indicating a previous update had been made, during the provisioning process.

After some head scratching, I suspected that even though SharePoint fired the WebProvisioned event, the site provisioning process was continuing in the background. A breakpoint set on my catch block tipped me off because the pages library did not exist.

I consulted with a colleague, who made me aware of the following XML node in the event receiver Elements.xml file:

<Synchronization>Synchronous</Synchronization>

By default, SharePoint calls the WebProvisioned event asynchronously, without the above node in the Elements.xml file.

After a quick recompile and deployment (with the above node added), I was able to test sub-site provisioning working and my event receiver running each time without failure.

How to change a Page Layout Associated Content Type Id Programmatically

I developed some code that uploads a new page layout file (ASPX) from disk to the Master Page Gallery of a site collection.  I wanted to associate the uploaded publishing page with an existing content type, such as the “Welcome Page” content type.  This is equivalent to editing the properties of the page layout and setting the “Associated Content Type” property…

 

image

 

Setting the Associated Content Type property in code is not as easy as thought.  After trawling around the web for an hour, I found no good example.  I found plenty of examples to create a Page Layout declaratively in XML and assign the associated content property, but no examples in C# for an existing SPFile object.  Then it hit me…

The PublishingAssociatedContentType property expects a formatted string that contains both the display name and the content type ID.  So, armed with both an SPFile object that is the page layout file and an SPContentType object, I was able to associate the page layout with the following code:

file.Item.Properties["PublishingAssociatedContentType"] = String.Format(";#{0};#{1};#", spCT.Name, spCT.Id.ToString());

Make sure to call file.Item.Update();

Wham!

Assigning a Unique Master Page to a Page Layout in SharePoint 2010

In the old days of SharePoint 2007, the master page reference in a publishing page layout lived in the MasterPageFile attribute of the @Page reference at the top off the layout file. 

This made good when you needed to create a page layout that stood out from the common branding of the site – such as a page layout that had no chrome for popups etc… and this was exactly what I wanted to accomplish today in SharePoint 2010.

Unfortunately, Microsoft changed the way in which Page Layouts associate with their master page.  Open any of the out of the box page layouts in SP2010 and you should notice that there are no references to master page files anywhere.  This is because the master page association is handled by the containing site settings.

So how does one go about creating a “special” page layout that does not follow the same branding as the rest of the site?  One option is to isolate such pages in sub sites, which is frankly crappy.  Unfortunately, the alternative is much better – the general consensus is that the solution to this problem consists of creating a new sub class that inherits the PublishingLayoutPage class and sets the CustomMasterUrl property explicitly in the Page Init event.

Thanks to Eric for his post, which I referenced to solve this issue.

TaxonomyClientService.AddTerms Wrong Documentation

I’ve been working lately on a project that requires access to the Managed Metadata Service in SP2010.  I got to a point where I needed to add a term to the default term store under a term set.

I have some code in my project that takes in the following parameters and creates a term in the term store:

– TaxonomyClientService proxy instance

– Term name

– Term store ID

– Term Set ID

I needed to use the AddTerm method of the proxy to create a new term, and spent most of my afternoon wrestling with the format of the NewTerms parameter of the method.

The following MSDN documentation is wrong! (here) – or at least not informative.

The MSDN documentation stipulates to use NewTerm nodes to wrap new terms in the XML passed to the service.  What the documentation did not tell me was:

1. The term set must be open, otherwise the method returns an empty string.

2. The method need the exact syntax for the XML to work – looking on the web, I found no real answer to this problem, and ended up reflecting the web service code to get my answer.  Below is a sample piece of XML.

<newTerms><newTerm label="MyTerm" clientId="1" parentTermId="GUID of parent or empty GUID if none"></newTerm></newTerms>

Worth noting with the above XML…

1. Notice the lowercase use of newTerms and newTerm (not uppercase N as in the MSDN documentation)

2. clientId does very little and so you can pass the value 1

3. The parentTermId must be a real GUID, and Guid.Empty if no parent

4. New terms wrap in the newTerms node, which MSDN failed to mention.

I hope this post saves others an afternoon worth of work, which it cost me.

Programmatically Provision Term Store

I recently had to write a feature to provision the SharePoint 2010 Term Store. Numerous blog posts exist on how to populate the term store using Power Shell or how to write XML to add terms to the store, but what I wanted to do was a little different.  The requirements for my feature were as follows:

1. Works in SharePoint 2010 (duh)

2. Create a new Term Store Group in default Term Store

3. Great a series of Term Sets

4. Create a series of Terms in the Term Sets

5. Deploy the feature at the Farm scope.

One of the issues with setting up a Term Store in the SharePoint 2010 Metadata Managed Service Application is that the service can be temperamental if the proxy for the service does not have the setting checked for default term store storage location for site collections.  I wrote a previous blog post on this issue here

To save you some reading, the issue above is with obtaining the default term store instance for a given site collection when using the TaxonomySession object in the Microsoft.SharePoint.Taxonomy API.  As my previous post mentioned, the way to resolve this issue is to check the option under Properties fore the proxy and ensure that the current user had full control as an Administrator of the Managed Metadata Service Application.

Nice one Rob! But what if you want to avoid the manual step and want to configure these operations in code?  It is not as hard as it may sound, check out the code below…

        private void ProvisionMetadataService()
        {
            // We don't have the metadata service configured, so let's do that.
            var proxy = SPFarm.Local.ServiceProxies.Where(s =&gt; s.GetType().Name.Equals
(&quot;MetadataWebServiceProxy&quot;)).FirstOrDefault();
            if (null == proxy) 
throw new SPException(&quot;Failed to get instance of metadata web service proxy, is it installed?&quot;);
            foreach (var proxyApp in proxy.ApplicationProxies.Where(proxyApp =&gt; 
proxyApp.Properties.ContainsKey(&quot;IsDefaultSiteCollectionTaxonomy&quot;)))
            {
                proxyApp.Properties[&quot;IsDefaultSiteCollectionTaxonomy&quot;] = true;
                proxyApp.Update(true);
            }
            // Give the current user access rights to the metadata service.
            var service = SPFarm.Local.Services.Where(s =&gt; s.GetType().Name.Equals
(&quot;MetadataWebService&quot;)).FirstOrDefault();
            if (null == service) 
throw new SPException(&quot;Failed to get instance of metadata web service, is it installed?&quot;);
            var serviceApp = service.Applications.OfType&lt;SPIisWebServiceApplication&gt;().FirstOrDefault();
            if (null == serviceApp) 
throw new SPException(&quot;Failed to get instance of metadata web service app, is it installed?&quot;);
            var security = serviceApp.GetAdministrationAccessControl();
            var cba = SPClaimProviderManager.Local;
            var claim = cba.ConvertIdentifierToClaim(&quot;DOMAINuser&quot;, 
SPIdentifierTypes.WindowsSamAccountName);
            security.AddAccessRule(
new SPAclAccessRule&lt;SPCentralAdministrationRights&gt;(claim, SPCentralAdministrationRights.FullControl));
            serviceApp.SetAdministrationAccessControl(security);
            serviceApp.Uncache();
            service.Uncache();
        }

 

With the above code executed, you can then open an instance of the site collection to the Central Admin Site and then request the default site collection term store with the following code:

using (var site = new SPSite(_farmUrl))
            {
                // Do we have explicit credentials?
                if (!String.IsNullOrEmpty(_username) &amp;&amp; !String.IsNullOrEmpty(_password))
                {
                    var user = site.RootWeb.AllUsers[_username];
                    if (null == user) 
throw new SPException(String.Format(&quot;no user in site collection {0}&quot;, _username));
                    using (var secureSite = new SPSite(site.ID, user.UserToken))
                    {
                        // Get the term store.
                        var session = new TaxonomySession(secureSite);
                        var termStore = session.DefaultSiteCollectionTermStore;
                        if (null == termStore) 
throw new SPException(&quot;Failed to get the default term store instance&quot;);
                        del(termStore);
                    }
                }
                else
                {
                    // Get the term store.
                    var session = new TaxonomySession(site);
                    var termStore = session.DefaultSiteCollectionTermStore;
                    if (null == termStore) 
throw new SPException(&quot;Failed to get the default term store instance&quot;);
                    del(termStore);
                }
            }

It’s not obvious from the code above, but the call to “del” is a delegate call that I include as a parameter to the wrapping method of the above cod.

So, lastly, how did I get the Central Admin URL in the feature receiver?  See below:

var app = SPAdministratrionWebApplication.GetInstanceLocalToFarm(SPFarm.Local);
var url = app.Sites[0].Url