09/11/2013

Managed Metadata column disabled in List when creating a new item in the list.

When you try to set a Managed Metadata column for a new list item it looks like this:

 
Fix:
  • List Settings > Click on Managed Metadata column
  • Select Term Set (if selected before do it any way)
  • Click OK
 When you try to set a Managed Metadata column for a new list item now it looks like this:

09/10/2013

Modify your Master Page to display the top level web description

1) Create a new Web Control

The web control shall retrieve the description from your top level site.

In your Visual Studio project, right click and choose Add > New Item... In the New Item dialogue select Module. Give the new module a name (SiteDescription) and click OK.
Remove the txt file.
Add a class (Add > Class...), give it a name (SiteDescription) and click Add.
The source code of your class will look something like this:

namespace NameSpace.SiteDescription
{
    /// <summary>
    /// SiteDescription class is used to displayes the description of the top level web.
    /// </summary>
    [ToolboxData("<{0}:SiteDescription runat=server></{0}:SiteDescription>")]
    public class SiteDescription : WebControl
    {
        private string _alt = "- default description of site";

        /// <summary>
        /// override so that the surrounding tag is a div insteadof a span
        /// </summary>
        protected override HtmlTextWriterTag TagKey
        {
            get { return HtmlTextWriterTag.Div; }
        }

        /// <summary>
        /// Add the description as an em tag
        /// </summary>
        /// <param name="writer"></param>
        [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust"
            )]
        protected override void AddAttributesToRender(HtmlTextWriter writer)
        {
            writer.RenderBeginTag(HtmlTextWriterTag.Em);
            writer.WriteEncodedText(_alt);
            writer.RenderEndTag();
        }

        private void InitiateDescription()
        {
            try
            {
                var webApp = SPContext.Current.Site.WebApplication;
                SPWeb siteToUse = SPContext.Current.Web;
                foreach (SPSite site in webApp.Sites)
                {
                    if (site.RootWeb.Title.Equals("Title")) /* your title...*/
                    {
                        siteToUse = site.RootWeb;
                        break;
                    }
                }
                if (!String.IsNullOrEmpty(siteToUse.Description))
                {
                    _alt = siteToUse.Description;
                }
              
            }
            catch (Exception e)
            {
                /*error handling*/
            }
        }

        /// <summary>
        /// Create new web control
        /// </summary>
        public BannerDescription()
        {
            InitiateDescription();
        }
    }
}


Edit the Elements.xml file of your new Web Control:

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Control
   Id="SiteDescription"
   Sequence="24"
   ControlClass="Namespace.SiteDescription.SiteDescription"
    ControlAssembly="Namespace, Version=1.0.0.0, Culture=neutral, PublicKeyToken=xxx">
  </Control>
</Elements>


2) Use your description web control in your master page

<NameSpace:SiteDescription ID="SiteDescriptionWebControl" runat="server"/>

Visual Studio will prompt you with the right import statements.

07/10/2013

Unable to change Navigation Settings

Error message from ULS log when trying to modify Navigation Settings (Site Settings > Navigation):

Unable to retrieve TopNavigationBar SPNavigationNodeCollection from Web at: <url>. The SPNavigation store is likely corrupt.

Run the following db script:

INSERT INTO [Cotent_db].[dbo].[NavNodes]
 ([SiteId], [WebId], [Eid], [EidParent], [NumChildren], [RankChild],[ElementType], [Url],
 [DocId], [Name], [DateLastModified], [NodeMetainfo], [NonNavPage], [NavSequence], [ChildOfSequence])
SELECT DISTINCT SiteId, WebId ,1002 ,0 ,0 ,1 ,1 ,'', NULL, 'SharePoint Top Navbar',getdate() ,NULL ,0 ,1 ,0
 FROM [Cotent_db].[dbo].[NavNodes] WHERE WebId NOT IN (SELECT WebId FROM [Cotent_db].[dbo].[NavNodes] WHERE Eid = 1002)
 

Thanks to:
http://bimoss.wordpress.com/2009/09/29/unable-to-modify-global-navigation-add-headinglink/

02/10/2013

Add Site Column to existing Content Type in code

How to add a new Site Column to an existing Content Type from code


This post describes how to create a new column, add it to an existing Content Type in an existing feature and last run an upgrade in PowerShell of the feature.

Feature.xml file:
<?xml version="1.0" encoding="utf-8" ?>
<Feature xmlns="
http://schemas.microsoft.com/sharepoint/" Version="2.0.1.0">
  <ElementManifests>
    <ElementManifest Location="NewColName\Elements.xml" />
  </ElementManifests> 
  <UpgradeActions>
    <VersionRange EndVersion="3.0.0.0">
      <ApplyElementManifests>
        <ElementManifest Location="NewColName\Elements.xml" />
      </ApplyElementManifests>
      <CustomUpgradeAction Name="AddFieldToContentType">
        <Parameters>
          <Parameter Name="FieldId">x-x-x-x-x</Parameter>
          <Parameter Name="ContentTypeId">xxxx</Parameter>
          <Parameter Name="PushDown">TRUE</Parameter>
        </Parameters>
      </CustomUpgradeAction>
    </VersionRange>
  </UpgradeActions>
</Feature>


The NewColName\Elements.xml contains the definition of the new column and shall be added in both the ElementManifest section and the UpgradeActions-ApplyElementManifest section. The ElementManifest section is used when deploying the feature the first time, and the UpgradeAction section is used when upgrading the feature. The new version of the feature is 2.0.1.0, and the upgrade action shall be active until version 3.0.0.0 (EndVersion attribute).
The CustomUpgradeAction refers to an upgrade action named "AddFieldToContentType". The action takes three parameters the new field ID the existing Content type ID and a parameter called PushDown, witch configures of the Content Type changes shall be pushed down to child Content Types.

The new column is defined in NewColName\Elements.xml:
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="
http://schemas.microsoft.com/sharepoint/"> 
  <Field

    Name="NewColName"
    StaticName="NewColName"
    Type="Text"
    Required="FALSE"
    DisplayName="NewColName"
    Description="The new column"
    Group="NewGroup"
    ID="{x-x-x-x-x}"
    Overwrite="TRUE" OverwriteInChildScopes="FALSE" 
    SourceID="http://schemas.microsoft.com/sharepoint/v3"
    xmlns="http://schemas.microsoft.com/sharepoint/" />
</Elements>


Create an event receiver and override the FeatureUpgrading method, this method is invoked when the feature is upgraded (surprise!) and the upgrade action name is taken as a parameter:
public override void FeatureUpgrading(
  SPFeatureReceiverProperties properties,
  string upgradeActionName,
  System.Collections.Generic.IDictionary<string, string> parameters)
{
  if (properties.Feature.Parent is SPSite)
  {
    SPWeb web = ((SPSite) properties.Feature.Parent).RootWeb;
    switch (upgradeActionName)
    {
      case "AddFieldToContentType":
        string fieldId = parameters["FieldId"];
        string contentTypeId = parameters["ContentTypeId"];
        bool updateChilds = true;
        bool flag;
        updateChilds=bool.TryParse(parameters["PushDown"],out flag);
        AddFieldToContentType(web,contentTypeId,fieldId,updateChilds);
        break;
      default:
        break;
    }
  }
}


AddFieldToContentType method:
private void AddFieldToContentType(SPWeb web, string contentTypeId, string fieldId, bool updateChilds)
{
  SPContentType type = web.ContentTypes[new SPContentTypeId(contentTypeId)];
  type.FieldLinks.Add(new SPFieldLink(web.Fields[new Guid(fieldId)]));
  type.Update(updateChilds, updateChilds);
}


The last thing to do is to override the FeatureActivated method, this method is invoked when the feature is activated and it will make sure that the new Field also is added to the Content Type the first time the feature is activated:
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
  if (properties.Feature.Parent is SPSite)
  {
    SPWeb site = ((SPSite) properties.Feature.Parent).RootWeb;
    const string fieldId = "x-x-x-x-x";
    const string contentTypeId = "xxx";
    AddFieldToContentType(site, contentTypeId, fieldId, true);
  }
}


So to upgrade the feature run this script in PowerShell :
$versionFolder = "C:\temp\"
$solutionName = “x.wsp”
$solutionPath = $versionFolder + $solutionName
$siteUrl = "
http://.../"
$featureId = "{x-x-x-x-x}"

Update-SPSolution –Identity $solutionName –LiteralPath $solutionPath –GacDeployment
# wait for it to finish
$site = get-spsite $siteUrl
$feature = $site.Features | where {$_.Definition.Id -eq $featureId}

if($feature)
{
    $ex = $feature.Upgrade($true)
    Write-Host $ex #if anything went wrong this is printed
}

18/09/2013

SharePoint portalsuperreaderaccount and portalsuperuseraccount

Get and Set super reader and super user accounts


How to get and set the SharePoint portalsuperreaderaccount and portalsuperuseraccount:

$w = Get-SPWebApplication "url"
$w.properties["portalsuperuseraccount"] = "domain\username"
$w.properties["portalsuperreaderaccount"] = "domain\username"
$w.Update()
Write-Host "superreader: " $w.properties["portalsuperreaderaccount"]
Write-Host "superuser: " $w.properties["portalsuperuseraccount"]


Error message that can appear if not properly set:

Object Cache: The super reader account utilized by the cache does not have sufficient permissions to SharePoint databases.
To configure the account use the following command 'stsadm -o setproperty -propertyname portalsuperreaderaccount -propertyvalue account -url webappurl'. It should be configured to be an account that has Read access to the SharePoint databases.
 Additional Data:
 Current default super reader account: NT AUTHORITY\LOCAL SERVICE


Or this error message

Trying to store a checked out item (/PAGES/PAGENAME.ASPX) in the object cache.  This may be because the checked out user is accessing the page, or it could be that the SharePoint system account has the item checked out.  To improve performance, you should set the portalsuperuseraccount property on the web application.  See the documentation for more information.

05/09/2013

Generate Excel content with PowerShell

Prerequisites

  • Excel must be installed
  • If the Excel file shall be generated and saved in a scheduled task some folders must be created: C:\Windows\System32\config\systemprofile\Desktop (32 bit and 64 bit) and C:\Windows\SysWOW64\config\systemprofile\Desktop (64 bit)

Open an existing Excel file

Using-Culture en-us {

 # open existing file
 $excelFilePath = "path" + "fileName.xls"
 $Excel = New-Object -COM Excel.Application
 $Excel.visible = $False
 $Excel.DisplayAlerts = $False
 $Excel.Workbooks.Open($excelFilePath)

 
 # create new sheet and activate it
 $sheet = $Excel.sheets.Add()                                                   
 $sheet.Name = "sheetName"
 $sheet.activate()

 
 # clean up
 Remove-ComObject -Verbose

}

Help functions

function Using-Culture ([System.Globalization.CultureInfo]$culture, [ScriptBlock]$script)
{
 $OldCulture = [System.Threading.Thread]::CurrentThread.CurrentCulture
 trap
 {
  [System.Threading.Thread]::CurrentThread.CurrentCulture = $OldCulture
 }
 [System.Threading.Thread]::CurrentThread.CurrentCulture = $culture
 $ExecutionContext.InvokeCommand.InvokeScript($script)
 [System.Threading.Thread]::CurrentThread.CurrentCulture = $OldCulture
}


function Remove-ComObject {
 [CmdletBinding()]
 param()
 end {

  Start-Sleep -Milliseconds 500
  [Management.Automation.ScopedItemOptions]$scopedOpt = 'ReadOnly, Constant'
  Get-Variable -Scope 1 | Where-Object {
   $_.Value.pstypenames -contains 'System.__ComObject' -and -not ($scopedOpt -band $_.Options)
  } | Remove-Variable -Scope 1 -Verbose:([Bool]$PSBoundParameters['Verbose'].IsPresent)
    [gc]::Collect()
  }
}


Data

# Retrieve cell (1,1) and set the value Name
$sheet.Cells.Item(1,1) = "Name"


# Clear data from a given range
$range = $sheet.Range("a1","e1000")
$range.clear()


Formatting

# Indent cell (1,1) 4 times
$sheet.Cells.Item(1,1).AddIndent = $true
$sheet.Cells.Item(1,1).IndentLevel = 4


# set Bold text on a row
$sheet.Rows.Item(1).Font.Bold = $true


# set Font size on a given range
$range = $sheet.Range("a1","e1000")
$range.Font.Size = 12     


# set Font style on row 1
$sheet.Rows.Item(1).Style = "Heading 2"


# set column width in cell (1,1)
$sheet.Cells.Item(1,1).columnwidth=40

03/09/2013

SharePoint 2010 Surveys - incomplete results

List the user of all Incomplete Survey Results

Incomplete results means that a user has pressed Save and Close in the Survey instead of Finish.
  1. Find Site ID for the Survey Site
    • Central Admin > Change Site Collection administrators
    • Change site collection and the site id will appear in the URL
  2. Find List ID for the Survey
    • List Settings > Audience Targeting
    • Copy the list ID from the URL
  3. Run DB Query:
Select userdata.tp_author,
(Select tp_Title from UserInfo where UserInfo.tp_ID=userdata.tp_author and tp_siteID='siteid')
As UserName from USERDATA
where tp_ListId like 'listid' and tp_level = 255

SharePoint 2010 Federated Search web part

Federated Search web part, Search Scope and Federated Location


  1. Create Search scope in Central Admin
    • Central Admin > Application Management > Manage Service Applications > Search Service Application > Scopes
    • New Scope
    • Set result page and rules to filter the search result, e.g. "YourUserProperty = 1", where YourUserProperty is a property or simply "contentclass = urn:content-class:SPSPeople"
  2. Create "Search Scopes" in Central Admin
    • Central Admin > Application Management > Manage Service Applications > Search Service Application > Manage Federated Locations
    • New Location
      • Set properties:
      • More Results Link Template: add an URL and a "*" after each search term when pressing the More Results link, e.g. "yourresultpage.aspx?k={searchTerms}*"
      • Query Template: add scope if preferred, e.g. {searchTerms} scope:YourScope
  3. Add "Federated Results" web part to the Site
    • Set "Federated Location" to a location created in Central Admin