Monday, June 29, 2015

Web Part Error when trying to view the Nintex Workflow Administration reports

Today I had to do a brand new installation of Nintex Workflow 2013 over SharePoint 2013 SP1.

After following the guide from Nintex, all worked well, except viewing the Administration reports.

This page is part of the Workflow Report Center and contains 10 different reports which are quite useful and they pertain to all sites within the entire SharePoint environment.

So the issue is that whenever you go to the highlighted link in the Nintex Workflow Management section in Central Admin:


You'd end up getting this:



Solution:

1. Open IIS Manager on the SharePoint server.
2. Navigate to the SharePoint Central Administration v4 Site and go to Explore.
3. Open the Web.config file after backing it up and add the two lines below before closing the tag </SafeControls>
4. Save web.config and refresh the Administration reports page.


<SafeControl Assembly="Nintex.Workflow.ServerControls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=913f6bae0ca5ae12" Namespace="Nintex.Workflow.ServerControls" TypeName="*" Safe="True" />
<SafeControl Assembly="Nintex.Workflow.ServerControls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=913f6bae0ca5ae12" Namespace="Nintex.Workflow.ServerControls.WebParts" TypeName="*" Safe="True" />

You should be able to deep dive into the Nintex Reporting functionalities now.





Friday, June 19, 2015

The Query String (URL) Filter Connections

That is a quite useful webpart... as MVP Laura Rogers  blogged in a series of posts a while ago.
I'll just mention what happens when you try to move it over, as it simply doesn't work as you'd expect it to work.

Today I've tried to bring accross a Team Site from SharePoint 2013 On-premise to SharePoint Online by using ShareGate Migration. *Almost* everything went well and I decided to do some sanity checks on basic functionalities of the site.

The one thing that's heavily used is a Client List solution that is implemented in the following way:

Page A: A web part page, containing a number of List View webparts, each of them containing different pieces of information related to specific clients, let's say client documents and key contacts.

Client Documents and Key Contacts, for example are separate lists, each of which has an identical column, called "Client" of type "Choice" Each item in those lists is associated with one client only.

Page B: A page with only one list view webpart, visualizing a list called "Clients", with a search box and some groupings which are collapsed so that the whole list of clients is not displayed by default.

The "Clients" lits has a column called "Link", of type guess what (Yes, Hyperlink or Picture of course) which supposed to take you to information for *only* that client on Page A by filtering all webparts on Page A, based on their "Client" column's value - it should be matching the value inserted in "Link". That is achieved through the Query String (URL) Filter webpart.

The format of the link is:  http://intranet/sites/teamA/clientlist.aspx?Client=NameofTheClient.

When this is clicked (that's what people do when they find the needed result), they're taken to Page A (clientlist.aspx) and view all info related to the client, with all other clients' data filtered out. Great, isn't it?

So, that was working well on the SharePoint 2013 on-prem, but not in Office 365 as I've tested it now post-migration.

The Query String (URL) Filter webpart is inserted on Page A. It's only visible in Edit Mode and it was visible on the page when I went to edit it. But the functionality that we used to have on premise was not working, when clicking on the "Link" column on Page B, I was taken to Page A, but totally unfiltered and seeing a bunch of data for a number of clients - not what I needed in order to find something quick. And the reason struck me immediately:



It seems the webpart connections are not brought over! I've tried exporting the webpart and importing it manually - still the same thing. The only thing that came over is the "source" of the filter parameter. Let's imagine that one was gone too, so we'd start nice and clean by readding our webpart:

Go to "Add Web Part" and locate the Query String (URL) Filter under the Filters category:

That's how the vanilla version looks like:

Open the tool pane to configure it and choose a meaningful name of your choice for the filter and the parameter that you'll be passing in the query (in our case Client):

Now we've got to add the connections. In our case those are 10+ lists but for the example, let's say we'd just need to apply the value to the Client Documents list:


On the next screen, choose "Get Filter Values From" and press the "Configure" button:


Choose the target list column that you'd like to use for filtering:


Done. The webpart will now show you the connection(s) rather than the annoying "Unconnected" warning:


Hope that was useful for you if you're tasked with migrating some solutions based on these webparts in your daily work. The interesting outstanding question is where are these connections stored when they're not coming over with the webpart itself? I'll be glad if someone posts a comment with an answer on that mistery.













Friday, June 5, 2015

SSRS Reports unloaded after SharePoint 2013 SP1 upgrade

This gloomy Friday morning I've had a look at the homepage of an Intranet that had SP1 applied last night and I found this on all webparts that had rdl files loaded in them (SSRS reports) and were displaying perfectly fine yesterday.

Not a big deal, if you have the .rdl files in hand :) Just load them again. But has anyone experienced such a problem and have any idea why it happened? I don't.. and unfortunately don't have the time to investigate it properly. The SP1 upgrade went fine with all psconfig steps completing in success.

Thursday, May 7, 2015

Cannot Edit Content Query Webpart

One of our clients who use SharePoint 2010 as a publishing solution (Internet) had an issue where they suddenly couldn't edit a content query webpart on a publishing page. The webpart can be added and displayed correctly, but not edited. It's slightly customized, containing a predefined query that's grabbing items from a list. Trying with a vanilla CQWP didn't make any difference though. Creating a new page and trying the same still did not succeed.

Whenever they tried to edit the webpart, they'd get Unexpected Error.


Looking at the ULS logs, I stumbled upon this:

System.Xml.XmlException: Reference to undeclared entity 'nbsp'. Line 1027, position 40.   
 at System.Xml.XmlTextReaderImpl.Throw(Exception e)    
 at System.Xml.XmlTextReaderImpl.HandleGeneralEntityReference(String name, Boolean isInAttributeValue, Boolean pushFakeEntityIfNullResolver, Int32 entityStartLinePos)    
 at System.Xml.XmlTextReaderImpl.ResolveEntity()    
 at System.Xml.XmlLoader.LoadEntityReferenceNode(Boolean direct)    
 at System.Xml.XmlLoader.LoadNode(Boolean skipOverWhitespace)    
 at System.Xml.XmlLoader.LoadDocSequence(XmlDocument parentDoc)    
 at System.Xml.XmlDocument.Load(XmlReader reader)    
 at System.Xml.XmlDocument.LoadXml(String xml)    
 at Microsoft.SharePoint.Publishing.WebControls.CmsDataFormWebPart.GetXslFile(String templateFileUrl)    
 at Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart.createItemStyleList()    
 at Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart.get_ItemStyleList()    
 at Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart.createAllSlotNames()    
 at Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart.get_AllSlotNames()    
 at Microsoft.SharePoint.Publishing.WebControls.ContentByQueryToolPart.createFieldsToDisplayControlGroup()    
 at Microsoft.SharePoint.Publishing.WebControls.ContentByQueryToolPart.createConfigureLayoutSectionControls()    
 at Microsoft.SharePoint.Publishing.WebControls.ContentByQueryToolPart.CreateChildControls()    
 at System.Web.UI.Control.EnsureChildControls()    
 at System.Web.UI.Control.PreRenderRecursiveInternal()    
 at System.Web.UI.Control.PreRenderRecursiveInternal()    
 at System.Web.UI.Control.PreRenderRecursiveInternal()    
 at System.Web.UI.Control.PreRenderRecursiveInternal()    
 at System.Web.UI.Control.PreRenderRecursiveInternal()    
 at System.Web.UI.Control.PreRenderRecursiveInternal()    
 at System.Web.UI.Control.PreRenderRecursiveInternal()    
 at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

So it seems somebody tried to insert an interval somewhere along the customizations. Looking further into the error, it seems it comes from the ItemStyle stylesheet. I grabbed it from the farm and saw there was &amp;nbsp; at one location. By default, the &nbsp; would not be rendered when inserted in the XSL.

There are three quick ways to overcome this.

1. Change &nbsp; to &#160

2. Change &nbsp to <![CDATA[&nbsp;]]>

3. Insert this in the XSLT file:

<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp "&#x00A0;"> ]>

We chose solution 1 and it works like a charm. Content Query webparts can now be edited,.

Tuesday, April 21, 2015

Deleted Term Set in SharePoint Online - consequences and solutions

One of our clients has accidentally deleted a whole Term Set from their SharePoint Online tenant.
The term set was mostly reusing some terms from other Term Sets, and had just one unique term.
There is one column in one document library, which was linked to that Term Set and about 2600 documents in that library that have a term assigned from that Term Set.

Consequences


  • Due to the fact the column is "Required" people can no longer upload documents to the library. Whenever you go to the upload form, the field for this columns is simply greyed out (as it's linked nowhere). The "Documents" column is the one that has the issue in our example:







  • Whenever you try to filter by that column by any of the terms, you get no results although there are plenty of documents with the same term assigned. Imagine you filter by a value that you already see jus underneath the filtering button, and boom - you get nothing:






Solutions:


  • Restore.


Bad news. You can't restore anything from the Term Store in SharePoint Online. Support call to Microsoft did not help either, you need to have a 3rd party solution in palce that can export your term store. I found this one  but it's a manual, on-demand export process, there's no automation option.
Another downside is that this is not a free software either.


  • Recreate.

That's what we've done - recreated the Term Set immediately after we've found restore is not an option. We've also reused the terms again (they were not that many - around 20). If you don't know which terms were used, unfortunately you'll have to look at the items in the document library and see what's already assigned to the items (manual process, takes a lot of scrolling...).

Let's say you've gone through the painful process of srolling through some ~2600 documents to get a full list of your terms, so now your Term Setrecreated, full of terms, and you've lost nothing rather than those 30 minutes (could be more or less) depending on how many documents and terms you've got. Wait, was it that easy? No... let's go to the filtering once again.


Doesn't work, of course. Term Sets have their own GUIDs and once you've deleted your Term Set, you've lost that GUID forever. Even if you knew it, you can't manipulate the GUIDs of any Term Sets, as they're automatically generated.

So, how do you handle that? You've got 2 options....

1. Go to the Quick Edit view in the library and start tagging the documents manually with the same terms (they're considered new terms as they reside in a new Term Set). 2600 documents - that would take quite some time.... half a day or a day, maybe. 

2. Smarter option. Create a list view, filtered by that managed metadata column and use one term as a start. That'll give you the documents that have this term assigned, and now you can remap the term for all the documents that have it assigned (or almost all, read further on to find out why). The first thing to do is verify those two options for your document library. 

  •  Don't require documents to be checked out before they can be edited.


  • And allow items in the document library to be edited using Quick Edit



Then... create your view fo the first term...imagine if the impacted column name is "Subscriber ID" and one of your terms assigned to hundreds of documents is called "Test".

The quick Edit view button can't be missed - it's the second button in the ribbon, right next to "View".


Select all the items in the view and then you click on the almost invisible managed metadata button on the left side of the term name. Then you have the option to choose "Replace all selected values with these terms", you choose the same term from your new term set (or any other one if you've changed your mind about what those documents should be tagged with) and click OK. Once you do that, you'll see SharePoint is "Working on it..." 



You are very likely to end up with this little message. I've raised it with MS and they've advised that the "Quick Edit" view is limited to 100 items.. although I could actually open it and see all of the 2600 items in our document library.

My personal tests have concluded that it only works with changes for up to 50 items maximum in the view... and I had a few occurences of the issue even with just 50 item, so had to reexecute the update or use less items - 25 was working perfectly for me.


That's it, with about 1 hour of retagging the documents we're back in business. 
Outcome: Be extremely careful with your Term Sets.


Friday, March 27, 2015

Deleted User Profile - How to Relink MySite (SharePoint 2010)

I've had a very interesting case on a SharePoint 2010 environment. A user's account was deleted accidentally by their internal AD team on Friday the 13th :) The account got recreated, but when the user tried to open MySite, they got "Access Denied" when clicking on "Contents".

I've made sure the user is the Site Collection Admin, checked every possible permission level and even re-added it just in case. No luck.

With the Farm Admin account, I was able to see the Contents of this user at all times.

I've come up with the following approach after a few hours of IIS / ULS logs reading that were simply showing 401 when this particular user tried to access their own MySite.

- Deleted the MySite (ensured we've got a fresh backup).
- The user then recreated a blank MySite.
- I've restored the backup with the Restore-SPSite command.

At this stage, I was able to see the contents with the Farm Admin account again, but when the user tried, he got the following error:

The attempted operation is prohibited because it exceeds the list view threshold enforced by the administrator.

And the respective ULS log entry:

The attempted operation is prohibited because it exceeds the list view threshold enforced by the administrator.
 at Microsoft.SharePoint.SPGlobal.HandleThrottleException(COMException comEx)    
 at Microsoft.SharePoint.Library.SPRequest.CrossListQuery(String bstrUrl, String bstrXmlWebs, String bstrXmlLists, String bstrXmlQuery, ISP2DSafeArrayWriter pCallback, Object& pvarColumns)    
 at Microsoft.SharePoint.SPWeb.GetSiteData(SPSiteDataQuery query)    
 at Microsoft.SharePoint.WebPartPages.AggregationWebPart.RunQuery(SPSiteDataQuery query)    
 at Microsoft.SharePoint.WebPartPages.UserDocsWebPart.GetEligibleItems()    
 at Microsoft.SharePoint.WebPartPages.AggregationWebPart.RenderWebPart(HtmlTextWriter writer) Inner Exception: The attempted operation is prohibited because it exceeds the list view threshold enforced by the administrator.  
 at Microsoft.SharePoint.Library.SPRequestInternalClass.CrossListQuery(String bstrUrl, String bstrXmlWebs, String bstrXmlLists, String bstrXmlQuery, ISP2DSafeArrayWriter pCallback, Object& pvarColumns)    
 at Microsoft.SharePoint.Library.SPRequest.CrossListQuery(String bstrUrl, String bstrXmlWebs, String bstrXmlLists, String bstrXmlQuery, ISP2DSafeArrayWriter pCallback, Object& pvarColumns)

Now... the list view treshold was set to 5000 for non-admins (default) and 20 000 for admins (again default). I've lifted it to 20 000 for non-admin users as well, just to find out it doesn't matter. No luck.

I've even decided to make the user a Farm Admin for a minute... again nothing changes.
Whenever he tried to access any of the libraries in "My Site", Unexpected error. The webpart "SharePoint Documents" still saying the stupid message about the List View Tresohld.

Maybe I should have mentioned that there are nowhere near 5000 items in that user's MySite in total.

So... next steps.

- Deleted the User Profile from SharePoint.
- Issued an Incremental Sync to import it - it didn't import.
- Issued a Full Sync - not imported again.
- Recreated the User Profile in SharePoint manually with all the properties

And still at the same stage...

Finally... I've decided to use the Export/Import instead of Backup and Restore and I did not use the -IncludeUserSecurity on purpose... as I am thinking that the old account is still referred to somewhere in the site permissions and that's causing all the headaches. Boom! All working fine now after the Import.

The only downside would be that the "SharePoint Documents" webpart which is the default one visible when you go to "Contents" under MySite will be showing no documents... as when I've used the Export method with the Farm Admin account now all documents show as modified by this account. Anyway once the user edits (or just check-out / check-in) a few documents, this webpart populates again and there's finally nothing more to worry about. Just be careful when deleting AD accounts :)

Monday, March 16, 2015

Yammer DirSync filtering by OU

This post might not be as helpful now as it would have been a year ago due to this improvement. Now Yammer DirSync could be used by organizations requiring Yammer SSO, previously it was used by each organization wanting to sync users from on-premise Active Directory to the Yammer network. More info on how to implement Yammer SSO, which is a different scenario can be found here.

I won't be trying to reinvent the wheel in this post, as there are plenty of good information sources on the Yammer DirSync implementation itself, like this one, but I'd rather share the limitations and issues I've faced when I had to meet a requirement to implement sophisticated filtering for the synchronization process.

The requirement seemed quite simple at a first sight - the customer wanted to synchronize users only from 5 specific OUs in their on-premise Active Directory domain.

Yammer DirSync (as well as the SharePoint User Profile Service) synchronization allows the use of LDAP queries. If you're new to those, you can read more about their syntax here.

The bad thing is, you have no option to query for a specific OU - and hence - no visible option to meet this requirement. The good thing is, there is a more advanced option to do this - partly a configuration cheat and partly modifications in the globalsettings.config.json file. 

The first part consists of adding more than one directory source, but if the OUs that you'd like to sync are in only one domain as in our scenario, you have two options:

- Sync from different domain controllers, add each one by hostname (better approach, straight forward)

You can't use a load-balanced name if you have created one (as per the installation guide).
- Sync from the same domain controller if you only have one (very rarely these days) or the requirement is to sync from one

In our scenario we needed to only sync from one DC, and the issue here arises from the fact that you can't add the same hostname in the configuration screen twice. It'll just tell you it already exists in the configuration.

The only ways to add the same DC again are to use the FQDN or the IP address in addition ot the NETBIOS hostname. Later on you can change that in the config files, but you have to go through the wizard first.

The configuration files you need then are stored in C:\ProgramData\Yammer\DirSync by default.

To locate the globalsettings.config.json file on your Yammer DirSync server, you need to go to the Yammer icon in the notifications tray and then click "About":


Then on the new pop-up window that you'll get, click on "Advanced Configuration":




Once you have the file open, you can implement some LDAP filters on each synchronization connection (I had to do this due to more specific requirements), but you still can't get the OU in the picture. The only way to do it is to use the "OverrideRootNamingContext" parameter which tells the sync tool which is the "root" container in the domain. So in our example, on each of the 5 synchronization connections that were created, we had to add the respective parameters. Let's say our domain name is contoso.local and we only want to sync users from the Test OU. We insert this in the first synchronization connection, and replace "Test" with the other OUs that we'd like to sync in the rest of the synchronization connections.


·   "OverrideRootNamingContext": "OU=Test,DC=contoso,DC=local”,