Tuesday, 24 September 2013

SharePoint 2013: Where is 'Sign in as Another User'?

The 'Sign in as Another User' has been removed by default, but it can be easily added.

There are a few options at your disposal:

1. Run your favourite browser 'as another user' by right clicking on it.
2. Navigate to the url <http://mysite>/_layouts/closeConnection.aspx?loginasanotheruser=true
3. Perform the following steps to add it to the user menu:

a      Locate and then open the following file in a text editor: C:\Program Files\Common Files\Microsoft Shared\Web Server 
Extensions\15\TEMPLATE\CONTROLTEMPLATES\Welcome.ascx

b.      Add the following element before the existing "ID_RequestAccess" element:
<SharePoint:MenuItemTemplate runat="server" ID="ID_LoginAsDifferentUser" Text="<%$Resources:wss,personalactions_loginasdifferentuser%>" Description="<%$Resources:wss,personalactions_loginasdifferentuserdescription%>" MenuGroupId="100" Sequence="100" UseShortId="true" />

c.      Save the file.





SharePoint 2013: Navigation item disappears behind a control

My intranet homepage has a navigation menu displaying the large number of sub sites in the site collection. The problem with the menu items is that they were disappearing behind the user control at the top of the page.

Fortunately, there is an easy fix - thank you Z-Index

ul.dynamic{
z-index:999;
}

Sunday, 22 September 2013

SharePoint 2013: Adding user permissions to specific lists

The intranet I am working on requires limited access to certain document libraries. This is easy enough - as I make my way through my configuration file in PowerShell, I gave the required users access to the document libraries they could see.

The only problem is that the users did not have access to the root site, so the sub site did not appear in the Navigation Bar. I tried adding 'View Only' permissions at the end, but that undid all my good work.

The solution was a change of approach; give the users access to the site and remove access from the items they should not see.

Its always helpful to sharpen the saw.

$list = $web.Lists["MyList"]
$web.AllowUnsafeUpdates = $true

if ($list.HasUniqueRoleAssignments -eq $false)
{
$list.BreakRoleInheritance($true)
}

$user = $web.EnsureUser("Domain\user")
$list.RoleAssignments.Remove($user)

$list.Update()

$web.AllowUnsafeUpdates = $false
$web.Update()

$web.Dispose()




Sharepoint 2013: Get all active tasks using SPSiteDataQuery for the current user (My Tasks)

My project was an intranet, a sub site monster that needed a query to show all the tasks for the current user. There were two options - recursive code (no thank you) or SPSiteDataQuery.

The key to the code is to limit the list query to the appropriate list type (see here for a list from Microsoft). In my case, it was "<Lists ListTemplate='107' />".

Then add some simple CAML (thank you Camldesigner) and you are there.

My final query was as follows:

            SPSiteDataQuery q = new SPSiteDataQuery();
            q.Webs = "<Webs Scope='SiteCollection' />";
            q.Lists = "<Lists ListTemplate='107' />";
            q.Query = "<Where><And><Or><Membership Type='CurrentUserGroups'><FieldRef Name='AssignedTo'/></Membership><Eq><FieldRef Name='AssignedTo'></FieldRef><Value Type='Integer'><UserID/></Value></Eq></Or>
<Neq>
<FieldRef Name=’Status’ />
<Value Type=’Text’>Completed</Value>
</Neq>
</And>
</Where>";
            // Always add a row limit (I may need to pass a CAF test)
            q.RowLimit = 1000;

Two things I noticed during my development:
1. Do NOT run this under elevated privileges. The script uses the context of the current user, so using elevated privileges will return the tasks assigned to the Application Pool account.
2. I had to write the CAML query in a single line. I tried using @" .... " but the runtime compiler kept complaining about invalid characters.




Thursday, 19 September 2013

Check code quality with SPDisposeCheck

Adding SPDisposeCheck to your VS solution is a good way to find potential performance and best practices issues early in the development cycle.

The code can be downloaded from http://code.msdn.microsoft.com/spdisposecheck

The installed executable (if you use the default settings like I did) is stored in
"C:\Program Files (x86)\Microsoft\SharePoint Dispose Check\SPDisposeCheck.exe"

The final step is to add the following script as a post build event:

cd $(ProjectDir)

“C:\Program Files (x86)\Microsoft\SharePoint Dispose Check\SPDisposeCheck” “$(TargetPath)” > “$(ProjectName)”.SPDisposeCheck.log

findstr /C:”Total Found:” “$(ProjectName)”.SPDisposeCheck.log

This will write the 'Total Found' with the number of SPDisposeCheck errors generated by the tool

Sharepoint 2013: Log in as another user

Switching users in SharePoint can be a pain - there is not 'Log In as Another User' in the suitebar.

The simple solution is to navigate to ~sitecollection/_layouts/closeConnection.aspx?loginasanotheruser=true and you will be prompted to log in again.

Active Directory Properties

I recently created a carousel control that read a few properties from AD.

I found this post here very useful - an extensive list of available properties.

PowerShell: Restart a SharePoint Service

Starting and stopping a service in PowerShell is pretty straight forward: Start-SPServiceInstance and Stop-SPServiceInstance

The tricky bit is passing in the correct parameter - the identity of the Service Instance.

The service can be found using Get-SPServiceInstance | Select TypeName, Id.

This will provide a list of the services and their corresponding Ids. You can then cut and paste the Guid into the appropriate command:

Start-SPServiceInstance -Identity <Guid>

Sharepoint 2013: List name does not correspond to URL name

It can be quite frustrating when the name of a list does not correspond to the URL. 

For example, the default Images library maps to /publishingimages/. 

I had this problem a little while ago and the solution was staring me in the face - the answer is held in the object model. If you pass in the name of the list ("Images"), you can get the SPList the old fashioned way: 

SPList list = SPContext.Current.Web.Lists["Images"].

However, if you manufacture a link, you need to use list.RootFolder.Name (or SPContext.Current.Web.Lists["Images"].RootFolder.Name)

Tuesday, 17 September 2013

SharePoint: Visual Web Part CSS Reference

Adding a CSS reference to a visual web part is quite simple:

<SharePoint:CssLink ID="Test" runat="server" DefaultUrl="Url/blah.css" />

The problem comes when referencing a relative url with spaces in it. To URL Encode or not, that is the question.

Initially, I have the reference as DefaultUrl="/Style%20Library/blah.css", but it was not being picked up by the web part. When I opened the source of the page, I found why - the url was being URL encoded by Sharepoint. This means that the URL in the source was

<link rel="stylesheet" type="text/css" href="/Style%2520Library/blah.css"/>

The URL was now double encoded.

I removed the %20 from the Url to resolve the problem.

Sharepoint 2013: Deploy a master page through a feature

It seems that the deployment code required for a masterpage in SharePoint 2013 is a little different from previous versions.

The same logic applies - create a module and deploy it with a feature.

Here is a sample module code, using my custom masterpage 'MyMaster.master'

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Module Name="MasterPageModule" List="116" Url="_catalogs/masterpage">
    <File Path="MasterPageModule\MyMaster.master" Url="MyMaster.master" Type="GhostableInLibrary" />
  </Module>
</Elements>

And here is the code in the feature receiver on the FeatureActivated event.

SPSite site = properties.Feature.Parent as SPSite;
SPWeb curWeb = site.RootWeb;

//create full master url
Uri masterURI = new Uri(curWeb.Url + "/_catalogs/masterpage/MyMaster.master");

curWeb.MasterUrl = masterURI.AbsolutePath;
curWeb.CustomMasterUrl = masterURI.AbsolutePath;
curWeb.Update();


Monday, 16 September 2013

Sharepoint 2013: Create a site template (where is it?)

Here is an excellent article outlining how to resolve the problem.

The problem is that site template creation is disabled by default. This property can be easily changed through Sharepoint Designer (in the Site Options button -> change the value of 'SaveSiteAsTemplateEnabled' to 'true').

Navigate to ~site/_layouts/15/savetmpl.aspx and create the template.

SharePoint 2013: Add Managed Metatadata navigation nodes in Powershell

The following script will add some managed metadata for navigation purposes. It will create a term store call 'My Group' and a term set  called  'My Term Set'. It will then add navigation links to Google and Hotmail.

# define some variables
$defaultMetadataServiceProxy = "Managed Metadata Service"
$groupName = "My Group"
$termSetName="My Term Set Name

#create the function to add the terms
function CreateNavigationTerm($termSet, $termName, $link, $termstore)
{
Write-Host "Add $termName"
$term = $termset.CreateTerm("$termName",1033)
$term.SetLocalCustomProperty("_Sys_Nav_SimpleLinkUrl", $link)
$termstore.CommitAll()
Write-Host "Successfully added $termName"
}

#get central admin
$adminwebapp = Get-SPWebapplication -includecentraladministration | where {$_.IsAdministrationWebApplication}

$caSite=Get-SPSite $adminwebapp.Url

#get the Taxonomy session
$session = new-object Microsoft.SharePoint.Taxonomy.TaxonomySession($caSite)

#get the Term Store
$termstore = $session.TermStores | where {$_.Name -eq $defaultMetadataServiceProxy}

#create the group (if required)
$rootgroup = $termstore.Groups["$groupName"]
if ($rootgroup -eq $null)
{
$rootgroup = = $termstore.CreateGroup("$groupName");
}

#delete the term set (if it exists)
if ($rootgroup.TermSets["$termSetName"] -ne $null)
{
$rootgroup.TermSets["$termSetName"].Delete();
}

# create it anew
$termset = $rootgroup.CreateTermSet("$termSetName",1033)
$termset.SetCustomProperty("_Sys_Nav_IsNavigationTermSet", "True")

# add the navigation terms
CreateNavigationTerm $termset "Google" "http://www.google.com" $termstore
CreateNavigationTerm $termset "Hotmail" "http://www.hotmail.com" $termstore

Write-Host "Done!!"



Sunday, 8 September 2013

SharePoint 2013: Hiding custom masterpage images in the upload page

My current masterpage contains some custom images and a banner.

<div id="wrapper">
    <div id="logo">
          <a href="/"><img src="/Style%20Library/Images/MyLogo.jpg" alt="My Logo" /></a>
</div>
<div id="banner" />

and a little css around it

#banner{
background-image:url(/Style%20Library/Images/MyBanner.jpg);
background-repeat:no-repeat;
}

This makes the site look great until I try and upload a file to a document library - the banner is now appearing in the upload page.

One way to get rid of it is to use a little JQuery to remove the images.

$(document).ready(function () {
                var pathname = window.location.pathname.toLowerCase();  
             
                    if(( pathname.indexOf('_layouts/15/upload.aspx') >0 )
                  || (pathname.indexOf('_layouts/15/checkin.aspx') >0 ))
               {
                    $("div[Id='logo']").css('display','none');
                    $("div[Id='banner']").css('display','none');
               }
});