Monday, February 3, 2014

SharePoint 2013 JSLink hide columns through calculated fields

So you've probably come across heaps of cool articles that show you how to create fancy rendering solutions using JS Link Templates. But every example tends to deal with only one field (Template.Fields) or all fields (Template.Item)

If you want to mess with more than one field it is really simple. Just add more to the array.
I.e.
Template.Fields = { "Budget" : {"View":somefunction}};
becomes
Template.Fields = { "Budget" : {"View":somefunction},
{"Timeline" : {"View":someotherfunction}}};

Sometimes you want to use the value of a field without actually showing it as a column. For example when you're adding icons to other fields or enhancing a column with extra info.
You'll notice is that the rendering template will fail if you do not include the desired field in your view, causing it to appear as extra annoying column.

Here is a trick I stumbled across by accident:
When you include a calculated column in your view, all referenced columns will become available to the current context through ctx.CurrentItem. So if you want to use the value of a field but don't want to include it as an extra column in the view, maybe you've got a calculated field you can abuse.
In my case I had following calculated column
BudgetStatus = [Actual Budget]/[Estimated Budget]
That made all three fields available in my context.
And now I wanted to include the Delivery Date for some funky rendering without making it a column? Simple. My new Budget Status looks like this:
BudgetStatus = ([Actual Budget]/[Estimated Budget]) + ([Delivery Date] * 0)

I know it's cheating. But hey, sometimes you have to cheat to get things done!

Friday, September 27, 2013

mouse pointer freezes in Windows 8

Does your mouse pointer freeze in Windows 8 regularly? Alt-Ctrl-Del will get you to the lock screen where the mouse works fine, but once you're back on the desktop app your mouse won't move?

Yup. happens to me regularly. Have not figured out what causes it, I'm guessing it has something to do with Outlook. or Remote desktops or Virtual Machines.
Often the mouse will freeze when I switch into or out of a remote desktop or VM using Alt-Tab. and until recently I had not way bar reboot or try a million key combinations hoping they will release the lock. But through pure luck I have found a solution that works each time now :-)

1) keep the Ctrl key pressed and your mouse will move. Like magic. release the key and the mouse freezes again. this at least will allow you to exit whatever focus you were in. For example exit the remote desktop console.
2) Alt-tab to your running instance of Outlook. Each time I have done that, the lock is released and the mouse will behave normal again. Does not work with tabbing to other windows. But with Outlook every time.

So is it Outlook who is locking the mouse? is it remote desktop? is it windows 8? I really have no clue. I'm just super happy I have found a solution which does not involve rebooting my machine.

Monday, July 15, 2013

Change Title to Filename in SharePoint 2013 Search Results

In this post I will share a little secret on how to fix the Search results on SharePoint 2013.

Problem

Whenever Search returns a Word result, it tries to be especially clever. If it prefers the first line of text in the document over the title field, it will use that instead of the title or filename in the search results. This is particularly annoying when the results are all forms and templates ,  where the first line in the document means absolutely nothing to the users.
So how to fix this? After a long battle with Microsoft support I was told that this is by design.
Some posts suggest not having a title at all. That way the filename will be chosen. Sadly that did not work in my case. It kept on returning the first line of the document. the only solution is to mess with the display templates used in Search. Luckily this is pretty simple nowadays.

Solution

Open the Item_CommonItem_Body.html DisplayTemplate in SharePoint Designer (_catalogs/masterpage/Display Templates/Search)
Not the Item_Word one!!! The Title logic is not defined here and any attempts to change it will be futile.

on the commonitem body template add after line 21 following code

if(ctx.CurrentItem.FileExtension == "doc" || ctx.CurrentItem.FileExtension == "docx"|| ctx.CurrentItem.FileExtension == "dot" || ctx.CurrentItem.FileExtension == "dotx"|| ctx.CurrentItem.FileExtension == "docm"){
  title =  ctx.CurrentItem.Path.replace(/^.*[\\\/]/, '');
  }
That will check for Word files, cut out the filename from the path using regex and replace the title with the filename.

Hope this helps!

Alex

Thursday, July 11, 2013

Powershell fix for App master problem

Ever come across this beauty?

Sorry, something went wrong
Accessing referenced file ...MasterPage.master... is not allowed because the reference is outside of the App Web.
Oh, man this babe had me shouting and screaming for quite some time. But I now have a solution which will work every single time, even on Office 365!

First, why is it happening in the first place?

Three ways of causing it:
1) you have a piece of code which applies a custom master page to your site. In a feature receiver for example. It iterates through all webs and updates the master reference. Sadly app webs, although on a completely different URL are still regarded a sub-web of your main site collection. And thus you'll change the masterpage reference of your app web and it will crash and burn as it is trying to access restricted resources outside of the allowed arena.
2) you ticked the lovely check box(Reset all subsites to inherit this site master page setting) on the Masterpage admin page (ChangeSiteMasterPage.aspx)
 on a publishing enabled site collection which applies the master page to all sub sites. bang. apps get messed up.
3) you deployed a design package. Bang. apps get messed up.

Please keep in mind, that this problem only affects Apps which have an AppWeb. Ie. SharePoint hosted apps and Autohosted apps. Any App which does not need an app web will not be affected by this problem. Cloud Hosted Apps for example.

How to avoid it?

In your feature receiver, check isAppWeb on the SPWeb object before applying the masterpage. if isAppweb, then skip applying the new master page :-)

But that won't stop the publishing feature to mess up your app web!

Easy.
Make a copy of the app.master (found in C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\TEMPLATE\GLOBAL), include it in a module in your app project and hard-code the masterpage references in the aspx pages. That way they won't take on the hand-me-downs from the publishing feature. Also lets you be creative with the master page and what to do with it...

 But what if you don't have control over the app code? I.e. added an app from the SharePoint 2013 app store?

How to fix it?

So, you can't avoid it and need to fix it? Easy :-) Well. took me some thinking and tinkering.
You can't access the masterpage admin page on an app web :-(
You can't connect to the app web using SharePoint Designer :-(
But you can mess with it via Powershell :-)

This is the script I came up with to fix up the master reference on an app web that got messed up:
#CODE STARTS HERE

$siteurl = 'https://app-b9ece6611a5524.ContosoApps.com/'

try
{

   $site = Get-SPSite $siteurl
   $web = $site.OpenWeb('CorporateNewsApp');
   $web.CustomMasterUrl = "/CorporateNewsApp/_catalogs/masterpage/app.master"
   $web.MasterUrl = "/CorporateNewsApp/_catalogs/masterpage/app.master"
   $web.Update()  
}
catch
{
   Write-Host -ForegroundColor Red 'Error encountered when trying to fix app master url on ' $siteurl, ':' $Error[0].ToString();
}
 
#CODE ENDS HERE
But what if you're using Office 365? Need to connect via SharePoint Online Management Shell. No Get-SPSite option available... or is there??? Just replace the urls, user and password and you're good to go.
#CODE STARTS HERE

$programFiles = [environment]::getfolderpath("programfiles")
add-type -Path $programFiles'\SharePoint Online Management Shell\Microsoft.Online.SharePoint.PowerShell\Microsoft.SharePoint.Client.dll'

   $siteurl = 'https://contoso-b9ece6611a5524.sharepoint.com/CorporateNewsApp/'
   $username = 'admin@contoso.onmicrosoft.com'
   $password = ConvertTo-SecureString -String 'PASSWORD' -AsPlainText -Force

try
{
   [Microsoft.SharePoint.Client.ClientContext]$cc = New-Object Microsoft.SharePoint.Client.ClientContext($siteurl)
   [Microsoft.SharePoint.Client.SharePointOnlineCredentials]$spocreds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $password)

   $cc.Credentials = $spocreds
   $site = $cc.Site;  
$web = $site.OpenWeb('CorporateNewsApp');
   $web.CustomMasterUrl = "/CorporateNewsApp/_catalogs/masterpage/app.master"
   $web.MasterUrl = "/CorporateNewsApp/_catalogs/masterpage/app.master"
   $web.Update()
  
   $cc.ExecuteQuery();
 
}
catch
{
   Write-Host -ForegroundColor Red 'Error encountered when trying to fix app master url on ' $siteurl, ':' $Error[0].ToString();
}

#CODE ENDS HERE

Hope this helps some of you out there with the buggy app model on office 365. I tried to get this resolved by MS Online Support but they proved completely incapable of solving this problem, let alone understand what I was on about in the first place.

Thursday, June 6, 2013

SharePoint 70-332 Exam Tips

So a few weeks ago I passed the dreaded SharePoint 2013 Pro exam. And I must tell you, the panic was for naught. I expected it to be heaps tougher than the 331 predecessor. I was trying to read up as much as I could. Tried to prepare heaps. But in the end it had the same kind of questions as 70-331, just phrased differently with a more architectural spin on them.

So if you sat and passed 70-331, my advice is to not freak out about 332 and sit very soon after passing 331. That way the studies you did are still fresh from the previous exam and will help you though this tough little cookie.

Don't get me wrong, it was not easy. I found it as tough as the 331. It just was not any tougher and called upon the same set of knowledge which got me through 331.

Hope this helps some of you aspiring to become the next MCSE SharePoint.

For some tips on passing 70-331, check my earlier blog post

InfoPath Drop Downs using SharePoint 2013 REST

Ever had the need to map a choice field to a drop down list in InfoPath?
SharePoint REST API makes this super easy! gone are the days of Lookup Lists and Lookup Columns. No need to maintain two sets of values either!

A rather unknown feature of SharePoint 2010 onwards is the fact that the REST interface, the one you access via /_vti_bin/listdata.svc, also gives you access to your choice fields in a simple XML format. Effectively the new choice field becomes a new entity at the same level as the list/library with a concatenated name.
So if you list is called Customers and the choice field is called Region, the url would look as such:
/_vti_bin/listdata.svc/CustomersRegion
SharePoint will spit a RSS formatted feed back out at you with all the choices listed :-)

All you need to do now is go to your InfoPath form, create a new data source, select REST Web Service as the source and paste the url to the choice list. Press OK and Finish, and now you can use that data source for your drop down values by:
  • Modifying the Drop Down List Box Properties
  • Choose  Get values from an external data source
  • Pick the REST data source
  • For Entries source pick /ns1:feed/ns1:entry
  • For Value and Display Name pick ns1:title
Done! you now have an InfoPath drop down list powered dynamically by your SharePoint Choice field!

SharePoint 2013 User Profile Property Mappings Error

Just a heads up! SharePoint 2013 has a nasty bug which has not been fixed in the March CU.

Every time you try to add an export mapping to your user profile property (especially on mobile aka CellPhone, telephoneNumber aka WorkPhone and faximileNumber aka Fax), it does not apply the mapping to the property alone, but lumps each one you edit thereafter into the same property. So if you set all three, you will end up with three export mappings against each User Profile Property. Which obviously won't work as you'll end up overwriting all three AD fields with the first mapping of the list.

And no, this is not a problem that is only in the GUI. It is a fundamental issue with how the mappings are managed in SharePoint:
As a Property can have only one import mapping, the developers built a very one dimensional HashTable to track these mappings. Not thinking, that a property could have multiple export mappings. Thus when you map multiple exports, the underlying HashTable gets all confused (even on separate profile properties) and lumps them all together under one heading.

When the time comes to synch, the engine then either applies them all over each other, or only the last one. Not sure which happens, but the end effect it the same: all AD fields end up with the same value.

Is PowerShell the answer? Sadly No. I tried all tricks in the hat. PropertyMapping.AddNewExportMapping -> Fail
PropertyMapping.AddNewMapping, and then change the isExport and isImport Fields on the newly created mapping. -> looks perfect at a first glance, but still same multi mapping behaviour.
PropertyMapping.Add (Name, Type, Field, isExport, isImport) -> Super Fail. Each time I tried this baby with an export it came back with a duplicate key error. (which supported my theory of the badly designed collection in the first place)

Final verdict? Export mappings are broken in SP2013 and nothing bar writing your own Timer Job to do it yourself will solve it. You'll have to wait for SP1 and hope that they've fixed it by then.