SharePoint Tip of the Day : Programmatically rollback to structural navigation in SharePoint 2013


Managed Navigation are the default choice when you create a publishing site in SharePoint 2013 but what do you need to do if you want to rollback programmatically to the old fashion structural navigation ?

The Navigation settings for each site are stored within the the property bag of the SPWeb and you can access it through

SPWeb.AllProperties[“_webnavigationsettings”] or through SharePoint Manager like showed hereunder

_webnavigationsettings

There is a new object WebNavigationSettings from the Microsoft.SharePoint.Publishing.Navigation dll that is responsible for managing (update & persist) the xml settings within the property bag.

Application pages like /_layouts/15/AreaNavigationSettings.aspx are adapting their UI based on these settings and by creating a new WebNavigationSettings with the current web as parameter to the constructor.

To rollback to the structural navigation, you can do all required configuration or use the built-in ResetToDefaults() method that will put back the PortalProvider instead of the Taxonomy one.

// Microsoft.SharePoint.Publishing.Navigation.WebNavigationSettings
public void ResetToDefaults()
{
    base.RequireNotFrozen();
    this.siteMapProviderSettingsByName.Clear();
    if (this.isRootWeb)
    {
        this.GlobalNavigation.Source = StandardNavigationSource.PortalProvider;
        this.CurrentNavigation.Source = StandardNavigationSource.PortalProvider;
    }
    else
    {
        this.GlobalNavigation.Source = (this.GlobalNavigation.InheritPortalSettingsFromParent ? StandardNavigationSource.InheritFromParentWeb : StandardNavigationSource.PortalProvider);
        this.CurrentNavigation.Source = (this.CurrentNavigation.InheritPortalSettingsFromParent ? StandardNavigationSource.InheritFromParentWeb : StandardNavigationSource.PortalProvider);
    }
    this.AddNewPagesToNavigation = true;
    this.CreateFriendlyUrlsForNewPages = true;
}

 

So in code, once you know it, it’s only a matter of doing

WebNavigationSettings webNavigationSettings = new WebNavigationSettings(rootWeb);
webNavigationSettings.ResetToDefaults(); // will rollback to PortalProvider
webNavigationSettings.Update();

To adapt the property bag and get the expected behaviour.

And if you’re wondering why it is the case by default, it is because the Portal Navigation properties feature which is part of the site definition of any publishing site (and stappled to a few others)  (Feature  Id= “541F5F57-C847-4e16-B59A-B31E90E6F9EA”) has a receiver that will do parse the feature properties and then always call the FriendlyUrlUtilities if the version is superior or equal to SharePoint 2013.

                if (publishingWeb.Web.Site.CompatibilityLevel >15)
                {
                    FriendlyUrlUtilities.ActivateManagedNavigation(publishingWeb.Web);
                }

And you guess it, that ActivateManagedNavigation will work with the WebNavigationSettings object and adapt it this time to support the Taxonomy Navigation.

_webnavigationsettings2

So if you’re stapling some feature with some receiver to rollback to the old way of working with navigation (and you should if you’re targeting a SharePoint 2013 Standard License !) make sure that you run after that receiver or execute it through PowerShell once the site is provisioned.

 

SharePoint Tip of the Day – Can’t find your custom site definition in SharePoint 2013 when creating your root variation label ?


As in previous SharePoint versions, whenever you create your root variation label, you’ll need to specify the template associated with all the labels.

Unfortunately the UI seems to only propose the Publishing Site (CMSPublishing#0) and the Publishing Site With Workflows (BlankInternet#2). While these two will fit most needs, I still find handy to have my own customized site definition, deriving from the OOTB ones that will only include the feature that I need and automatically do specific action upon provisioning.

01

So how can you add your own site definition to the list like in the image above ?Time to do a little bit of reflection to see how this administration page is working and let’s call ILSpy to the rescue !

The page is inheriting from Microsoft.SharePoint.Publishing.Internal.CodeBehind.VariationLabelPage

and will load available choices through its private method private SortedDictionary<string, string> PublishingTemplates which is getting the available templates from the site collection through GetCustomWebTemplates and filtering the results through VariationLabelPage.FindFilterCategory to only retain the ones which have a property FilterCategories with the value “PublishingSiteTemplate”…

02
03

Knowing that, it’s only a matter of adding that property to your webtemp entry and voilà, it’s now usable (do an IISReset to ensure the choices, loaded from SharePoint internal cache, are reloaded).

04

Hope it will help !

SharePoint Tip of the Day – Where is the Microsoft.SharePoint.IdentityModel.dll in #SP2013 ?


SPFederationAuthenticationModule and / or using Microsoft.SharePoint.IdentityModel anyone ?

Wondering why you can’t add reference from Visual Studio to this DLL ?

Turns out that you need to make a reference to the dll from the gac (or copy it from it)

Assuming windows is installed on your C drive (you’ll be clever enough to figure out the other path otherwise) :

C:WindowsMicrosoft.NETassemblyGAC_MSILMicrosoft.SharePoint.IdentityModelv4.0_15.0.0.0__71e9bce111e9429cMicrosoft.SharePoint.IdentityModel.dll

Thanks ILSpy & GacView utilities (would marry both them if they were not utilities !)

SharePoint Tip of the Day – Who is the LocalSystem account used to run the Administration Service (SPAdminV4) ?


Localsystemaccount

Even on least privileges installation of your farm, the SPAdminV4 services will run under the Local System account (be sure to read this reference table : http://nikspatel.wordpress.com/2010/12/24/sharepoint-2010-service-account-references-for-least-privileged-installation/ and this – for SP 2007 but still as valid for 2010 / 2013 : http://technet.microsoft.com/en-us/library/cc288210%28v=office.12%29.aspx) but ‘who’ is this built-in account ?

The LocalSystem account has extensive privileges on the local computer, and acts as the computer on the network. Its token includes the NT AUTHORITYSYSTEM and BUILTINAdministrators SIDs; these accounts have access to most system objects. The name of the account in all locales is .LocalSystem. The name, LocalSystem or ComputerNameLocalSystem can also be used. This account does not have a password.

One advantage of running under the LocalSystem account is that the service has complete unrestricted access to local resources. This is also the disadvantage of LocalSystem because a LocalSystem service can do things that would bring down the entire system

(http://msdn.microsoft.com/en-us/library/windows/desktop/ms684190%28v=vs.85%29.aspx & http://msdn.microsoft.com/en-us/library/windows/desktop/ms677973%28v=vs.85%29.aspx)

SharePoint / Excel Tip of the Day – Easily remove duplicates in your MMS csv files


Excel-duplicates-finder

Whenever working with huge term sets, you can hardly avoid having duplicates. Even if an import will skip them, if you process them programmatically (eg: PowerShell import & processing) it’s better & easier to work on a proper set than always checking for duplicates. It’s also welcome when you send this back & forth to consumers so they can easily refine their taxonomy without missing with duplicates.

Turns out it’s pretty simple in Excel, you just highlight the area you want to filter, go to data > Filter (Advanced) you specify a region next to your current one (you can’t do this on another sheet) and you’ll have only the unique entries. Copy / paste this selection on a new document and you now have your filtered set, with only unique entries.

Hard to beat when dealing with taxonomies that have thousands of terms 🙂

SharePoint Tip of the day – Don’t forget the Managed Metadata friendly “PageFieldValue” CQWP filter to create rich OOTB relations between your content


Cqwp-pagefieldvalue

Another reminder to myself (like nearly all the posts in this small diary) to rely whenever possible on the Content Query WebPart “PageFieldValue” for the relation between content.
No custom user/web controls wrapped or not in webpart(s), no extensive search service configuration and core search result webpart configuration (altough I still like that option !), the good old trusty CQWP with its PageFieldValue and the ability to work natively with Managed metada field (including children terms) is a pure joy to use.

And if you’re targeting content that might also bring the actual page, don’t forget to exclude it (eg : by its title or its ID) through once again the PageFieldValue since it will be obviously the first candidate to match your filter.

SharePoint Tip of the Day – PowerShell snippet to disable mobile view for a specific web application


A good reminder to myself to exclude this from feature receiver and put it on separate PowerShell scripts that can be easily run only on specific environment(s).

$webApp = Get-SPWebApplication "http://www.public-site.com" $configMod = New-Object Microsoft.SharePoint.Administration.SPWebConfigModification$configMod.Path = "configuration/system.web"$configMod.Name = "browserCaps"$configMod.Sequence = 0 $configMod.Type = 0$configMod.Value = "<browserCaps> </browserCaps>" $childConfigMod = New-Object Microsoft.SharePoint.Administration.SPWebConfigModification$childConfigMod.Path = "configuration/system.web/browserCaps" $childConfigMod.Name = "result"$childConfigMod.Sequence = 0$childConfigMod.Type = 0$childConfigMod.Value = "<result type=""System.Web.Mobile.MobileCapabilities, System.Web.Mobile, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a""/><filter>isMobileDevice=false</filter>"  $webApp.WebConfigModifications.Add($configMod)$webApp.WebConfigModifications.Add($childConfigMod)$webApp.Update()$webApp.Parent.ApplyWebConfigModifications()$webApp.WebConfigModifications.Clear()

SharePoint Tip of the Day – X-UA-Compatible IE Edge / IE8 and anonymous audience


Ie_edge_sp2010

As some might now, switching the IE rendering mode to IE=Edge on your SharePoint master page might bring unexpected issue

But for mostly anonymous audience, it might be neat to have it while retaining the classic IE=8 mode for contributors.

In order to quickly toggle between IE Edge mode and IE 8 mode depending on the audience I relied on a LoginView :

    <asp:LoginView runat=”server”>
        <anonymoustemplate>
            <meta http-equiv=”X-UA-Compatible” content=”IE=Edge” />
        </anonymoustemplate>
        <LoggedInTemplate>
            <meta http-equiv=”X-UA-Compatible” content=”IE=8″ />
        </LoggedInTemplate>
    </asp:LoginView>

Simple and codeless. The contributors will work in IE8 mode (no issue with the people picker, calendar, dialog, etc.) while the final audience will see the (publishing) site in the freshest mode depending on their IE version.

Next step, finally implementing the dual master page solution from Johan Leino to remove the fat from these bloated master pages.

Windows Tip of the Day – Change the keyboard layout for the Welcome Screen


Welcomescreenkeyboard

Using an azerty keyboard, I’m always having issue when I have to take the ownership of a Windows 7 / 2008 environment that was configured with a EN-US layouts.
Fortunately, it’s fairly easy (once you know where to look at !) to apply your current settings to the welcome screen :

Control Panel -> Regional and Language Settings -> Administerative -> Copy Settings -> Click the check marks (at the bottom) to the welcome screen and accounts that you want to copy the settings to and click ok

SharePoint 2013 Tip of the Day – Consumer Preview & Key Resources


Let’s get ready for the information overload !

SharePoint 2013 is now available for consumer preview and your RSS / Tweets / whatever subscriptions are overloaded with fresh content. I won’t help to lower the load.

My cherry picked selection at the moment :

To download the binaries :

Presentations / Walkthrough

Happy reading / discovering.

SharePoint Tip of the Day : Be careful when working with date & time in SharePoint !


Microsoft SharePoint stores date and time values in Coordinated Universal Time (UTC, but also named GMT or Zulu) format, and almost all date and time values that are returned by members of the object model are … in UTC format.

Unfortunately, there is one big exception and that’s probably the case you’ll be using the most : the list column values that are obtained through the indexer for the SPListItem class are already formatted in the local time for the site so if you’re working on current context list item and fetch a datetime field like so SPContext.Current.ListItem[“Your-DateTime-Field”] you’ll retrieve a DateTime object according the the specified time zone in the regional settings (and taking into account the “lovely” summer / winter time).

Other special case is whenever you want to display a date time value in your page layout, instead of using the generic field value :

<SharePointWebControls:FieldValue FieldName=”Modified” runat=”server” />

You should use the specific date time field value <SharePointWebControls:DateTimeField FieldName=”Modified” runat=”server” /> which will return the value according to the time zone of the current SPWeb.

As a final reminder, whenever you’re doing a CAML query and you’re working with date you can specify the property DatesInUTC to grab them as they are stored and I heavily suggest you to work with Offset (positive or negative) from Today <Today Offset=”10″ />
 or generate your Zulu “TZ date” (eg : 2012-05-24T16:32:00Z) based on a specific UTC time (and not the server current time). So instead of working with a DateTime.Now, rely on DateTime.UtcNow to avoid unexpected behaviour.

Hope it helps.

SharePoint News of the Day – SharePoint 15 SDK (technical preview) material already available !


Sharepoint15

The communication around the next release of the Office suite has offically started a few days ago and now, it’s already possible to download the technical preview version of the SDK of the next version of SharePoint (currently smartly named SharePoint 15) http://www.microsoft.com/download/en/details.aspx?id=28768. And you thought you were able to put your head out of the SharePoint 2010 water / jungle ? 😉

SharePoint Tip of the Day – Reminder on how to install Adobe PDF IFilter in SharePoint 2010


There are an outstanding amount of walkthroughs on the web to do it but some are missing some steps or overcomplicating the task. Here’s thus the recipe I give when I deliver projects requiring pdf content results.

  1. Install PDF iFilter 9.0 (64 bit) from http://www.adobe.com/support/downloads/detail.jsp?ftpID=4025
  2. Download PDF icon picture from Adobe web site http://www.adobe.com/misc/linking.html or used the one attached

    Pdf

    (the one from adobe is not clean IMHO) and copy to C:Program FilesCommon FilesMicrosoft SharedWeb Server Extensions14TEMPLATEIMAGES 

  3. Add the following entry in C:Program FilesCommon FilesMicrosoft SharedWeb Server Extensions14TEMPLATEXMLdocIcon.xml <Mapping Key=”pdf” Value=”pdf.gif” />
  4. Add a pdf file type on the File Type page under Search Service Application
  5. Open regedit and navigate to the following location HKEY_LOCAL_MACHINESOFTWAREMicrosoftOffice Server14.0SearchSetupContentIndexCommonFiltersExtension. Right-click > Click New > Key to create a new key for .pdf and add the following GUID in the default value {E8978DA6-047F-4E3D-9C78-CDBE46041603}
  6. KB article ask to restart the SharePoint Server Search 14 service and to reboot the SharePoint servers in the farm better not skip that part (and schedule it wisely in production).
  7. Perform a full crawl on all your content sources to get the pdf within your results.

If price is not an issue (hmmm…), you should consider the Foxit IFilter, which offers much better performance (by lowering the time for the crawls). In the meantime, the adobe way is working and fully supported.

Happy configuring

SharePoint Tip of the Day – Unextend a web application


I always went the hard way, removing the AAM entry and deleting the IIS website, thinking blindly that SharePoint would understand my unfriendly actions but there is a way, if you don’t fear to click on delete on your primary (non extended) web application !

Unextend

  1. Go to the Central Administration
  2. Go to Application Management section
  3. Select the web application that the extended web app was extended from
  4. Click on the small arrow under delete and select Remove SharePoint from IIS Web Site
  5. Specify the relevant extension to delete
  6. Check to delete the IIS Web site

I had to manually deleted the site from IIS even if I checked the option, but at least the configuration database is now in a cleaner state.

Cheers.

SharePoint Tip of the day – Reorder fields within your list instance


During your application lifecycle management, you’ll probably have to add new fields or update your content types based on new requirements / needs.
Re-ordering fields within list instances consuming these content types can be handy to give the professional finish touch to your upgrade scenario.

Fortunately, it’s extremely easy once you know how to do it ! Just grap the FieldLinks property on the content type of the list and call the re-order method on it. Don’t forget to update your list afterward !

                SPContentType bannerContentType = rootWeb.Lists[Configuration.Lists.Banners].ContentTypes[ContentTypes.Banner];                SPFieldLinkCollection fieldLinkCollection = bannerContentType.FieldLinks;                fieldLinkCollection.Reorder(new[]{                                                    Fields.Title, Fields.BannerKeyword,                                                     Fields.Language,Fields.Taxonomy, Fields.TargetChannels,                                                     Fields.BannerType, Fields.BannerImage, Fields.BannerAlternateText,                                                    Fields.BannerTargetUrl, Fields.BannerUrlTarget,                                                     Fields.BannerBody, Fields.BannerBodyPosition,                                                    Fields.PublicationStartDate, Fields.PublicationEndDate});                bannerContentType.Update();

SharePoint Annoyance of the day – Cryptography nightly error on a server


Dear all,

If you encounter like we did on one of our testing server  a popup (appearing in the morning) with a cryptography exception and wanting to attach the VS Debugger Process, don’t worry. It’s documented and somehow normal.

 

Image001

This will only happens on some configurations  and if we have VS installed on the server (it’s usually not the case on staging environment and definitively not on authoring / production environment) otherwise a warning will be logged and nothing else.

In case you encountered the same behaviour of the customer would be complaining that any of your solution is doing something harmful (after all, a cryptography exception is quite frightening by its sole name), please refer him to this entry

SharePoint Tip of the day – Lookup fields defined through xml, WebId and managed paths


Lookup

Wondering why your lookup field(s) defined through xml are not working anymore when you deploy your solution outside of the root of the web application ? (/sites/whatever or /whatever for the explicit inclusion managed paths) ? Turns out that you need to specify the web id to the tokenized ~sitecollection (and also set overwrite to true if you do have a separate feature for your field and your list schema).

Without this, the lookup field definition which was working flawlessly without any code on the root of the web application was unable to find back its associated list.

That webid attribute, awfully unproperly documented within msdn / sdk, also allows you to define the guid of the target web holding the list instance.

SharePoint Tip of the Day – How to access the term store management tool as a contributor (not an owner) from a specific site collection


Sharepoint-2010_term_store_man

Took me quite an unexpected long time to figure this out but got it working ! Site collection contributors are obviously not able to connect to the central administration and cannot access the complete site settings administration page on a specific site collection since they are not owners

The administration page of the Term Store Management tool is thus hidden for them but the access once they know the link is available (/_layouts/termstoremanager.aspx?tsid=my-farm-guid-for-my-term-store)

If added as contributors within the term store manager in central administration, they will be able to add / edit terms (and manage translations). If added as administrators (while still being only contributors on the site collection) they will be able to do structural changes to the metadatas.

Good news for companies since they will be able to easily deleguate this to contributors without making access to the central administration nor needing custom permissions ! Strange enough that with all the plumbing done, a simple link is not available…

As always, once you know it …

SharePoint Tip of the Day – Add Alternate URL using stsadm (AAM)


If you try to automate as much as possible your solution deployment, you'll likely enjoy having your alternate access mappings deployed in a structured and repeatable way.
Turns out that it's quite easy and manageable by stsadm without doing some custom development.

To add an internal url to your web application :

stsadm -o addalternatedomain -url http://agents.company.com -urlzone Internet -incomingurl http://agentABC.company.com

And to add a public url :

stsadm -o addzoneurl -url http://SP2010:88 -urlzone Internet -zonemappedurl http://www.company.com

Quite handy and something we can add to our little batch files that deploy our SharePoint solutions.

SharePoint Tip of the Day – Don’t forget to set Inherits=”false” when you’re removing field reference(s) in your SP2010 content types


… or how something that worked in SharePoint 2007 is now not working as expected in SharePoint 2010.

Never minds, if I read carefully msdn documentation, it was kinda explained, I need to remove the inherits="true" (or stop using the built-in template for the content type creation !) or change it to inherits="false".

Optional Boolean. The value of this attribute determines whether the content type inherits fields from its parent content type when it is created.If Inherits is TRUE, the child content type inherits all fields that are in the parent, including fields that users have added.

If Inherits is FALSE or absent and the parent content type is a built-in type, the child content type inherits only the fields that were in the parent content type when SharePoint Foundation was installed. The child content type does not have any fields that users have added to the parent content type.

(source : http://msdn.microsoft.com/en-us/library/aa544268.aspx)

If you use some  RemoveFieldRef entries in your content type definition and you're still seeing the removed fields, then you now know why.

Did you know that … (Response.End versus HttpContext.Current.ApplicationInstance.CompleteRequest)


If you use the Response.End, Response.Redirect, or Server.Transfer method, a ThreadAbortException exception occurs. You can use a try-catch statement to catch this exception (of type ThreadAbortException) but having an empty catch block after my Response.End was kinda ugly.

 

So, rather than doing Response.End, we can call HttpContext.Current.ApplicationInstance.CompleteRequest it will causes ASP.NET to bypass all events and filtering in the HTTP pipeline chain of execution and directly execute the EndRequest event…

http://msdn.microsoft.com/en-us/library/system.web.httpapplication.completerequest%28vs.80%29.aspx

We never stop learning !

SharePoint Tip of the day : AAM, Hosts, Bindings, Search Scopes and Server Name Mappings reminder


As a SharePoint developer, I don't have to play too much with all the administrative tasks when I'm outside of my VMs as our IT service is responsible for ensuring the proper health status of the production facing site. So stuff like Alternate Access Mappings, Bindings and Server Name Mappings were quite new for me.

So, here is a small reminder of the steps that I did to have my site collection accessible through a fake public url (eg : http://www.company.com) instead of http://sharepoint-dev-01 and ensure the search results are returned properly using the right url.

  • Edit the host file on the server, make 127.0.0.1 point to http://www.company.com
  • Edit the IIS binding (inetmgr -> point the relevant website entry -> bindings and add a new one with www.company.com as the host name on port 80 (all ip addresses unassigned)
  • Add an Internet Alternate Access Mapping for your computer name (in my example : http://sharepoint-dev-01)
  • Fire up your browser and access your website through the new url (you can launch Fiddler and have a look at all requests / responses to ensure everything is properly mapped

The most important part is now what to do (or what to avoid) to ensure that your search is working as you would expect it to do. The general idea is to stick with the server name as the host name instead of already playing with the AAM name. The alternate access mapping created previously will take care of all url rewritting so do not do like me and don't mess your content source or scopes with the fully qualified domain name !

  • Ensure your content source is pointing to the server name instead of the fully qualify domain name (eg : http://sharepoint-dev-01)
  • Ensure all relevant scopes are using the server name instead of the fully qualify domain name on your folder rules (eg Folder = http://sharepoint-dev-01/be-en/products/)
  • Make a full crawl
  • Enjoy your search results being served with the fully qualified domain name when your search page is accessed through http://www.company.com

It must be possible to adapt url of the search results through the "server name mappings" configuration screen but I've never been able to make it work as expected. I guess the main culprit was the fact that I mixed fqdn and server name at various place which confused the search service.

I'll never stop learning 🙂

 

SharePoint tip of the day – what to do when stsadm restore results in ‘Access Denied’ error (E_ACCESSDENIED)


Ensure that your account has enough permissions to do the operation or that you’re list as a site collection administrator for the site collection that you are restoring.
Your site collection might also be locked by a previously failed restore job : stsadm -o setsitelock -url “http://yoururl-lock none

(and don’t worry, even when the backup is on the same disk as the sql server, it’s awfully slow to restore… Don’t kill the process and get a long coffee break !)