Friday, October 25, 2013

Creating a printable InfoPath form

I don't like printing.  But inevitably, someone will want to do it somewhere.

We have a list, which uses an InfoPath form for data entering and viewing.  In here, we created a Print view, which is basic black text on white background, and read-only.

However, when trying to print this view, the rest of our SharePoint master page and branding is printed with it, and it doesn't look very professional.  So we needed to create a printable version of this Print view.

Some suggestions online included using jQuery to remove everything BUT the InfoPath form, but this sounded like a messy way of doing things.  Instead, I figured I could just create a new blank page in SharePoint Designer and grab the item ID from the URL.

My first attempt failed.  I tried using a Query String Filter Web Part, but then realised that sending an ID to an InfoPath Web Part doesn't do what you'd think it would do.  It doesn't magically open the item you're referencing with the ID, it simply changes the InfoPath form item ID.  You could use this method for pre-populating an InfoPath form based on parameters in your query string, but not for actually loading an already-existing form.

I figured that you could instead use that ID to filter a List View of your list, and then send that single item to the InfoPath web part.  This would also mean I wouldn't need the Filter Web Part, as a List View has its own Filter and Parameter settings.  So, here's what I did.

  1. Using SharePoint Designer, create an ASPX page in your site called PrintForm.aspx.
  2. In the ASPX page, add an InfoPath form web part, and configure the web part to use the list you're trying to print items from.  Configure this web part to use the correct Print view that you've already created in InfoPath Designer.
  3. Somewhere else on the page, add a Data View, and again configure to use the list you're trying to print items from.  Configure this web part to be hidden or not visible (unless you want to see the list view as well).
  4. With the List View web part selected, add a Parameter.  This will be a query string parameter with the name ID, and the Query String Variable of ID as well.  (You can change this to ItemID or something else if you want)
  5. Next, add a Filter for the List View web part.  This will get the Field Name ID to equal the parameter you just created, which will be displayed as [ID] or [ItemID] or whatever you chose in the previous step.
  6. Finally, Add a Connection from the List View to the InfoPath web part.  You want to Send Row of Data To the InfoPath web part, using the Target Action "Get Form From".  
  7. Save and check in the file as appropriate.

Now, if you try to access the URL of this page with an ID added to the end, you will get a nice, basic printable view of your data.  You'll want the URL to look like this:

http://sharepoint/sitename/Pages/PrintForm.aspx?ID=25

What you'll need to do then is add a Print button to the normal Read or Edit view of the InfoPath form, which will send the user to that URL above, with the current item ID after the ID= (in the example above, the item ID is 25).

There's also a little bit of JavaScript you can throw in to your PrintForm.aspx page which will tidy up a few last remnants of the InfoPath web part - namely, the web part name, and the light blue border.  It also presents the user with their browser Print dialog, to save them having to go to File/Print.  It looks like this:

<script src="/scripts/jquery-1.9.1.min.js" type="text/javascript"></script> 
<script type="text/javascript">
  $('.ms-WPHeader').hide();
  $('.ms-WPBorder').css('border', 'none');
  setTimeout(function() {
    window.print();
  }, 500);
</script>

Edit: added a setTimeout before printing, because it was printing a blank page, even though print preview was working correctly.

Thursday, October 24, 2013

When was a SharePoint list created? Who created a SharePoint list?

Pretty simple one, this - I was surprised to find I can't easily see a list Created date in the usual SharePoint 2010 interface, so this little PowerShell snippet did the trick.

$spweb = get-spweb -identity http://sharepoint/sitename
$splist = $spweb.lists["List Name"]
$splist | format-table -property created, author

Update: added the "Created By" (author) field as well, so you can see who created the list.

Tuesday, October 1, 2013

Unable to display this Web Part, only affecting some users, load balancing partially to blame?

This was a particularly strange one.  I can't imagine anyone having the exact same issue as we had this morning, but you never know.

Some users this morning reported the following error:

Unable to display this Web Part. To troubleshoot the problem, open this Web page in a Microsoft SharePoint Foundation-compatible HTML editor such as Microsoft SharePoint Designer. If the problem persists, contact your Web server administrator.

Looking into the SharePoint error logs, I found this:

Error while executing web part: System.NullReferenceException: Object reference not set to an instance of an object.     at Microsoft.Xslt.MethodCollection.ResolveMemberRef(Int32 tokenNum)     at Microsoft.Xslt.MethodCollection.ResolveToken(Int32 token)     at Microsoft.Xslt.MethodCollection.MethodDescription.DeclareDynamicMethod(MethodCollection methodColl)     at Microsoft.Xslt.MethodCollection.CreateDynamicMethods()     at Microsoft.Xslt.MethodCollection.GetMethodInfoInternal(Int32 methodNumber)     at Microsoft.Xslt.MethodCollection.GetMethodInfo(Int32 methodNumber)     at Microsoft.Xslt.STransform.GetCompiledTransform()     at Microsoft.SharePoint.WebPartPages.BaseXsltListWebPart.LoadXslCompiledTransform(WSSXmlUrlResolver someXmlResolver)     at Microsoft.SharePoint.WebPartPages.DataFormWebPart.GetXslCompiledTransform()     at Microsoft.SharePoint.WebPartPages.DataFormWebPart.PrepareAndPerformTransform(Boolean bDeferExecuteTransform)

Now, some Googling found many references to a Windows Security Update that caused a problem back in July.  However, there was no record of this update being installed on any of the SharePoint servers, and certainly nothing had changed overnight (this problem wasn't occurring yesterday).

The strange thing is, this problem wasn't affecting me, no matter which account I used to try to replicate.  But it was affecting my colleague.  In fact, it was his laptop - when I logged into his laptop with my account, I had the same problem.  His laptop is Windows 7, and my machine is Windows Server 2012 (not the SharePoint server).

I initially thought it was just him, because he was able to fix each individual list view by going into SharePoint Designer, saving the view (without making changes), and the list view worked again.  Until he restarted his laptop, then the problem came back.  Eventually, I had a few emails from other people receiving the same error message.

Very strange indeed, and continued to not affect me.

Some more Googling, and I finally found someone else on TechCenter - Recycling app pool causes webparts to fail - who had the same errors as displayed above, but had occurred before the Security Update, so obviously wasn't caused by that.  They figured out that the application pool used by SharePoint hadn't recycled correctly, so recycling it manually fixed the problem (for a while, although it came back some days later).

As we have two web front ends, using Windows Network Load Balancing, I checked the theory - I accessed one of the offending list views from one web front end, and the error happened.  On the other web front end, the error didn't happen.  Clearly one of my web front ends was broken.

I went into Network Load Balancing, took the broken web front end offline, and recycled the SharePoint application pool.  Problem solved.  Restored NLB, and everything is back to normal again.

But what's puzzling me is why this only affected Windows 7 users (when they went through the NLB), and Windows Server 2012 didn't.  It seemed that Windows 7 machines were constantly being sent to WFE1, and Windows Server 2012 machine was being sent to WFE2.  Surely that defeats the point of load balancing?

Thursday, September 12, 2013

SharePoint 2010 Management Shell and Windows Management Framework 3.0

I have four Windows Server 2008 R2 machines which are used for SharePoint 2010.  However, I remotely connect to these machines from my Windows Server 2012 box.  Windows Server 2012 has a pretty nifty Server Manager which allows management of remote servers, but in order to manage Windows Server 2008 machines, it needs Windows Management Framework (WMF) 3.0 installed on the 2008 machines.

I've installed that, and can manage the servers remotely - works brilliantly.  However, opening the SharePoint 2010 Management Shell (PowerShell) now produces the old favourite error message:

The local farm is not accessible. Cmdlets with FeatureDependencyId are not registered

I've found (from this post on TechNet) that WMF 3.0 seems to be a bit incompatible with SharePoint 2010. A blog post - Henrik's blog: SharePoint 2010 - Windows update powershell error - recommended uninstalling WMF 3.0 to resolve this.  But I found that adding a '-v 2' parameter to the shortcut for SP2010 Management Shell seems to work quite well so far:

C:\Windows\System32\WindowsPowerShell\v1.0\PowerShell.exe -v 2 -NoExit  " & ' C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\CONFIG\POWERSHELL\Registration\\sharepoint.ps1 ' "

There are some reports that this doesn't completely fix the incompatibility, but I've not encountered any other problems yet.

Friday, September 6, 2013

How to search a list using a Content Editor web part

Had a challenge for a little while - a large list, over 4000 items, that need to be searchable.  Our staff don't want to understand how to use columns to filter, and they like text boxes that they can type in to.

Only found out today that you can search a list using a query string, a la:

http://sharepoint/Lists/Applications/AllItems.aspx?FilterName=Title&FilterMultiValue=*adobe*

This will bring back all items in this list that has a title containing the word "adobe".  Changing FilterName to the name of the column you wish to search will enable you to search other columns as well.

So, with a bit of a kickstart from here - SharePoint List Search in Moss 2007 - I adapted and came up with this code, which you can easily shove into a Content Editor web part at the top of your list page (AllItems.aspx, in this case).

<script type="text/javascript">
function RedirectUrl() {
var cs = document.getElementById("searchText").value;
var url = '';
url = "FilterName=Title&FilterMultiValue=*" + cs + "*";
window.location.href = "AllItems.aspx?" + url;
};
</script>
<div style="border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; background: #efefef; border-bottom: #cccccc 1px solid; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; margin: 10px auto 0pt; border-left: #cccccc 1px solid; display: block; padding-right: 5px; width: 60%">
<h3 style="text-align: center">
Type in this box to filter the list below:
<input class="search" id="searchText" type="text" style="padding-bottom: 10px; padding-top: 10px; padding-left: 10px; padding-right: 10px"/>
<input id="btnSearch" onclick="return RedirectUrl();" type="button" value="Search"/>
</h3>

</div>

If you would like more information on throwing things around in a query string to filter or sort a list, have a look at this lovely blog post: Search, Filter or Sort Lists from a Query String.

Monday, September 2, 2013

Exporting all custom solutions from a SharePoint 2010 farm

Not many updates to the blog lately, apologies for that.  I'm working on moving our current SharePoint 2010 environment to a new server farm, hosted by a new company who insist that we have to rebuild everything from the ground up.

I've been using AutoSPInstaller to automate a lot of the process of building a new farm, but one thing I couldn't find much instruction on is those custom solutions and features we're using.  I didn't want to source every single solution again - some were developed by me, so they're easy to find, but there are others which aren't so easy to find (3rd party contractor developments).

Finally found a solution, from Using PowerShell to export all solutions from your SharePoint 2010 farm and other fun:

(Get-SPFarm).Solutions | ForEach-Object{$var = (Get-Location).Path + "\" + $_.Name; $_.SolutionFile.SaveAs($var)}

So simple, and works exactly as you'd expect.  Now I can pick from all of my solutions which ones I still actually need.

Monday, June 10, 2013

JSON returned from listdata.svc for a full list, but "XML" for a single item

I've been trying to use jQuery to get some data from a SharePoint list named Articles, using REST.  Hit a wall, couldn't figure it out.  Quick blog post about how I got around it.

Basically, when I tried to use $.getJSON with this URL:

http://sharepoint/_vti_bin/listdata.svc/Articles()

I was able to parse the data in jQuery as you'd expect.  Worked like a dream.  However, when I tried to just return one single list item, using:

http://sharepoint/_vti_bin/listdata.svc/Articles(1)

jQuery silently failed.  Couldn't get any data out of it whatsoever.  When I looked at Google Chrome's Developer Tools (specifically, the Network function), I could see that Articles() was being returned as application/json as you'd expect, but Articles(1) was being returned as text/plain.  jQuery didn't like that.

So, I added a parameter to my URL:

http://sharepoint/_vti_bin/listdata.svc/Articles(1)?format=JSON

And everything is right in the world again.

Monday, June 3, 2013

Investigating Translation Services in SharePoint 2013

There are a few parts to Translation Services.

The first is the ability to translate a document within Word Web App (interesting to note that Office Web Apps now runs separately to SharePoint 2013, whereas it was previously installed as a component to SharePoint 2010).  All you have to do is to click File, and then Translate.  You'll be given a list of languages to translate to, and your document will then be translated.  Of course, this is a systematic translation and won't be completely accurate, but it'll be a good indication. See this video - SharePoint 2013 Translation Service - to see it in action.

Secondly, and more impressively for developers and administrators, is the ability to translate documents from within the SP2013 interface.  Out of the box, there are PowerShell commands to perform translations, but a small piece of coding can be done (see: SharePoint 2013 translation services) that will allow you to add context or ribbon options that perform translations for you.  These can be done either synchronously (you wait for the translation to complete before you continue) - or asynchronously (the translations are carried out in the background and will be ready for viewing at a later stage, often within seconds).  This can be tied into workflow, so a document could be uploaded to a library, and the translation could then be placed into a language-specific library or sent to a human translator for approval.

The most interesting part of the asynchronous process (as demonstrated in the video above) is that entire document libraries can be translated at once.  A copy of each file is created, with the language code added to the file name after translation.

Finally, we come to Variations.  If you intend for your entire site to be multilingual, you would activate Variations.  This will allow all content - navigation, pages, even list items - to be different (or varying) across languages or locales.

If "Variations" have been enabled, SP2013 can prepare an XLIFF translation package for selected documents, and these can then be sent to, or downloaded by, an external translation agency.  When they have finished translating these documents, they send back, or upload, the translation package, and SP2013 will carry out the operations required to make these documents or pages available to that language variation.

For more info on Variations, see Variations overview in SharePoint Server 2013
...and for more info on Translation Services, see Introduction to Machine Translation Services in SharePoint 2013

Friday, May 31, 2013

Investigating network performance improvements in SharePoint 2013

Various improvements have been made to network performance in SharePoint 2013.  

One of the key improvements is known as Minimal Download Strategy.  From Introduction to Minimal Download Strategy in SharePoint 2013: "Minimal Download Strategy is a new feature in SharePoint 2013 that improves client rendering performance and fluidity when navigating from page to page by download only the changes between two compatible pages. Fewer bytes will be downloaded and the page will appear more quickly."

Sites running with Minimal Download Strategy (enabled by default for SP2013 team and community sites) only load the master page and layout once.  To compare, in SP2010, navigating to a sub-folder in a document library will cause the entire page to load again.  In our existing SP2010 site, the core layout and master page takes up 48Kb of bandwidth on each load, plus whatever the content of the actual page is (such as a document library, which is about 25Kb per page).  If you navigate to five pages within a site on SP2010, that uses around 350Kb of bandwidth.  In SP2013, this would be 170Kb.

In my tests on my own connection to the SP2010 server, a 70Kb page took on average 1113ms to display, which works out at 16ms per Kb.  For 20 typical page loads in SP2010, this would be 22.4 seconds of network usage.  In SP2013 (in theory), this would be reduced to 8.7 seconds of valuable network usage.

(Please note that these tests are certainly not controlled and comprehensive, but give a general idea of the improvements that Minimal Download Strategy can bring.)

Other improvements to WAN performance are improved image compression, and faster response time to incoming requests (up to 50% in some tests).  In other tests carried out by Microsoft (see Testing WAN connections for SharePoint 2013 architectures) on a connection between Redmond and Beijing showed a 10Mb ZIP file taking 53-140 seconds to upload to SP2010, but only taking 49-63 seconds to upload in SP2013.

Also worthy to note is the improved document library synchronisation.  This did exist in SP2010 using SharePoint Workspace, but I found this to be incredibly buggy and difficult to use when working with large teams.  Since SP2013 uses SkyDrive Pro (included with Office 2013), SharePoint document libraries can be completely synced onto a user's computer for offline use.  This can be used for an individual's personal work documents (in which case, the files are synchronised to the user's MySite on SP2013), or for a team to collaborate on documents as a group.  SkyDrive is already considered a worthy competitor to other services such as Dropbox and Google Drive for personal use, and this SP2013 integration brings that functionality to a business as well. (See also: Overview of SkyDrive Pro in SharePoint Server 2013)

To bring this all back to the end user, these improvements, plus the new look and feel (with better tactile response and more interactive page layouts) can help the SP2013 site seem almost instant and easier to use.

Thursday, May 30, 2013

How to sell SharePoint 2013 to a steering committee

A few weeks ago, I was asked to prepare a presentation on the reasons we should upgrade our SharePoint 2010 environment to SharePoint 2013.  It wasn't enough to simply say "it looks pretty", but that was obviously (what I thought) a key selling point, as the presentation was to be delivered to non-technical decision makers.  My presentation included a look at the improved social computing features, an improved way of deploying new custom developments (or apps), and one final slide just summarising some of the new technical features - Translation Services, Workflow Services, and "Minimal Download Strategy".

It turns out that the greatest interest from almost everyone at the table was these three technical points.  The look and feel?  Not of interest to most people, as we already have a heavily-customised and branded master page.  Others didn't like the social element at all.  But the last slide was the strongest for them, and I learnt from that to focus more on these parts.

I decided to carry out more research on these technical features to better sell the product.  Sure, the end users will probably appreciate the new user interface and ease of use, but if the business owners don't see a benefit, the users will never get to use it.

The next few posts will be my semi-technical findings on:

  • Minimal Download Strategy (or, more generally, network performance improvements)
  • Translation Services

Hopefully someone else researching SP2013 will find some interest in these features and help them also sell a very promising product upgrade.

Wednesday, May 29, 2013

Changing a name in SharePoint People Picker using PowerShell

The company I work for has recently acquired another business, and the migration process for getting their Active Directory users into our Active Directory has resulted in duplicate accounts for the same person. Sometimes the duplicate account is on a different domain, but often it's the same domain, resulting in confusion when there is a need to select a user from the People Picker.

One option to resolve this is to simply delete the SPUser.  However, I don't like deleting things.  There is always a chance this could have adverse effects somewhere else, and there's also the higher chance that the SPUser will just be recreated when something occurs in the Active Directory.  So, I've opted for another solution, which is to simply change the DisplayName of that erroneous account to something obvious (such as "Do not use").

Eventually, these duplicate accounts will be deleted from the Active Directory, which makes me more confident in deleting the SPUsers too, but until then, this will have to do.

Set-SPUser -Web http://sharepoint -Identity "domain\duplicateuser" -DisplayName "Do Not Use"

Friday, April 26, 2013

Periodic "Unable to display this web part" error

For a few of my SharePoint sites, the "landing page" contains multiple data view web parts.  These simply display a filtered view of a document library or list on the same site.

Occasionally, when browsing to these sites, the web parts won't display.  The error is:

Unable to display this Web Part. To troubleshoot the problem, open this Web page in a Microsoft SharePoint Foundation-compatible HTML editor such as Microsoft SharePoint Designer. If the problem persists, contact your Web server administrator.  (Correlation ID provided)

Doesn't tell me much.  I took the correlation ID and trawled through my SharePoint logs.  I found this exception:

Error while executing web part: System.StackOverflowException: Operation caused a stack overflow.     at Microsoft.Xslt.NativeMethod.CheckForSufficientStack()     at <xsl:template match="FieldRef[@ListItemMenu]" name="FieldRef_Menu_PrintFieldWithECB" mode="PrintFieldWithECB">(XmlQueryRuntime , XPathNavigator , XPathNavigator , Double )     at <xsl:template match="FieldRef" name="FieldRef_printTableCell_EcbAllowed" mode="printTableCellEcbAllowed">(XmlQueryRuntime , XPathNavigator , XPathNavigator , String )     at <xsl:template match="Row" mode="Item">(XmlQueryRuntime , XPathNavigator , IList`1 , IList`1 , Double , Double )     at <xsl:template match="View" mode="RenderView">(XmlQueryRuntime , XPathNavigator )     at <xsl:template match="View" mode="full">(XmlQueryRuntime , XPathNavigator , String )     at <xsl:template match="View" name="View_Default_RootTemplate" mode="RootTemplate">(XmlQueryRuntime , XPathNavigator , String )     at <xsl:template match="/">(XmlQueryRuntime )     at Root(XmlQueryRuntime )     at System.Xml.Xsl.XmlILCommand.Execute(Object defaultDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlWriter writer, Boolean closeWriter)     at System.Xml.Xsl.XmlILCommand.Execute(IXPathNavigable contextDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlWriter results)     at System.Xml.Xsl.XslCompiledTransform.Transform(IXPathNavigable input, XsltArgumentList arguments, XmlWriter results)     at Microsoft.SharePoint.WebPartPages.DataFormWebPart.ExecuteTransform(XslCompiledTransform xslCompiledTransform, XsltArgumentList xmlArguments, Boolean bDeferExecuteTransform)     at Microsoft.SharePoint.WebPartPages.DataFormWebPart.PrepareAndPerformTransform(Boolean bDeferExecuteTransform)

A bit of Googling took me to a Technet post (http://social.technet.microsoft.com/Forums/en-US/sharepointgeneralprevious/thread/1a38bdff-e40a-4e50-a2e8-47cbcb31cc6b/) which suggested that this issue may be caused by a timeout issue.  By default, the timeout setting is set to one second, which (in my opinion) isn't very generous.  The following PowerShell command checks the current timeout setting:

$farm = Get-SPFarm
$farm.XsltTransformTimeOut

To change this to five seconds, which is more reasonable:

$farm = Get-SPFarm
$farm.XsltTransformTimeOut = 5
$farm.Update()

My hesitation with any sort of farm update is that this will cause an IIS recycle or other temporary downtime.  Fortunately, this had no effect that I could see.  I've not seen the Web Part error since.

Thursday, April 25, 2013

Managed metadata column is empty, even though it can be filtered

We experienced a peculiar problem with a SharePoint list today.  One of the columns in the list is a managed metadata column, which allows the administrator of this site to add terms themselves.

Although the user could browse the metadata and create new terms, the document library view showed no data in this column.  Viewing the document properties showed the terms correctly, so the data was being saved, but it just didn't show up in the view.

What made this even more peculiar is that you could still filter by that column, and the filter worked correctly - it just didn't show anything in the column.  This didn't affect farm administrators, only end-users.

It didn't take much searching the web to find a solution (thanks http://social.technet.microsoft.com/forums/en-US/sharepointadminprevious/thread/f647f47f-a51a-49b7-8dca-4d2f67644b9c) but it seemed worthy of mention here.

It appears that when an end-user adds a term to managed metadata, a hidden list (called TaxonomyHiddenList) is updated with the new term added as a new list item.  The TaxonomyHiddenList is found at http://sharepoint/Lists/TaxonomyHiddenList (where "sharepoint" is the root site collection).  The permissions for this list were not inheriting from the root site collection, so only SHAREPOINT\system had access to this list.

I added NT AUTHORITY\authenticated users with Read access to the list, and the problem mentioned above instantly vanished, and the managed metadata column was populated.

Wednesday, April 17, 2013

View size of all document libraries using PowerShell

Quick and dirty post this time around.  This PowerShell script will analyse all document libraries in a site collection and dump the results in a (very basic) comma-seperated text file called output.txt.  The size will be in KB.


$sitecol = Get-SPSite -Identity http://sharepoint

foreach($site in $sitecol)
{
  foreach($s in $site.AllWebs)
  {
    foreach($l in $s.lists)
    {
      if($l.BaseType -eq "DocumentLibrary") {
        $listSize = 0
        foreach($item in $l.items) {
          $listSize += ($item.file).length
        }
        $filesize = [string][Math]::Round(($listSize/1KB),2)
        $title = $filesize + "," + $s.Title + ":" + $l.Title
        $title >> "output.txt"
      }
    }
    $s.Dispose()
  }
}

Wednesday, April 10, 2013

Filtering rows in SharePoint Designer not working

I had an issue with SharePoint Designer which left me quite frustrated yesterday.  Today, a colleague mentioned something from his experience which fixed the problem, and made me hate SharePoint Designer even more.

I needed to create a document library view that used a query string as a parameter.  Having done this multiple times, I didn't expect any issues.  However, in this instance, the filter did not work.  It simply showed no items (even though I could clearly see the item I wanted to filter in SharePoint proper, and even filter the column in the usual way in the web browser).

To test, I created a new document library, new view and new filter - this worked perfectly.  After spending a few hours trying to figure this out yesterday, I asked my office buddy to look over my shoulder and see if I'm doing something wrong.

He mentioned that, from his experience, if you click in the column name in SharePoint Designer and assign a Filter from there, it never works.  But if you click on the actual document library content (in SharePoint Designer) and click Filter, it does work.

Seemed too simple to be the issue, but sure enough, that's exactly what it was.

So, if you're trying to filter a list or library in SharePoint Designer, DON'T click on the column header to set up a Filter (even though it gives you the option to do so).  Click on an item row instead.

Friday, February 22, 2013

SharePoint document groupings not showing the grouped documents when expanded

One of our sites on SharePoint is used to store customer contracts.  A SharePoint list item, called a Contract Record, stores the data relating to that instance of a customer.  Separate to this, a document library, called Contract Files, stores the actual contract files, which are then associated with the Contract Record.

When viewing the files, they are grouped by Contract Record.  And when clicking on a Contract Record to view more information, the files are displayed below, using a simple filtered web part.

We already hold all of our customers’ names in SAP, so we have an SSIS package taking an export from SAP and throwing the data into a SharePoint list, called Customers.  So, when you create a Contract Record, you use an InfoPath form to search (using CAML) for the Customer, and a combination of the Customer Name, Country Code, and Customer ID are used to create the title of the Contract Record.
Simple, right?

Anyway.  This whole process was working fine, until recently.  While Contract Files assigned to an existing Contract Record were displaying fine under the grouping, new Contract Records were not.  The grouping title (the Contract Record name) was displaying correctly (along with the number of files in that group), but when you expanded that group, nothing appeared underneath.

Similarly, the filtered document library web part was not showing any files, even though files had been assigned to that Contract Record.

So we dug around in the data obtained using CAML.  It appeared that there were a few additional characters being inserted into the raw CAML output:

<d:LongName>Customer Name - FR&#xD; (000059184) </d:LongName>

Did a bit of Googling and found that &#xD; is basically a line feed.  This was ignored in the Contract Files lookup for a Contract Record and seemingly ignored when grouping documents, but when expanding a group, the line feed is taken into consideration and no grouped files exist.  Or something like that.

So we looked to the data imported using SSIS, and sure enough, this line feed is added to the end of most of the country codes.

<d:Country xml:space="preserve">FR&#xD;</d:Country>

I did a test – I created a new SSIS package and had it copy all data from Customer into a new, identical list called CustomerTest.  This removed the line feed.  But obviously, there’s not much point creating a new SSIS package just to fix data from an existing one, so I’ve had the original SSIS package only bring back the first two characters from the Country code.  Seems to have worked.

Note: this relates to another post I made not too long ago, here: Filtering Large SharePoint list data in InfoPath

Monday, February 4, 2013

"Access denied" for newly-created AD accounts, not showing up in People Picker

For the last week, we've been experiencing a problem where certain user accounts have not been able to access our SharePoint 2010 site.  They have been presented with an Access Denied message, wrapped in the usual SharePoint error template.  The affected accounts were no different to similar accounts that did work (such as my own).

I trawled the SharePoint error logs and found the following.


Name=Request (GET:http://SP2010)
Begin Query the AD to get the user email and display name.
End Query the AD to get the user email and display name.

Access denied.  You do not have permission to perform this action or access this resource.
Leaving Monitored Scope (GetFileAndMetaInfo). Execution Time=53.0181908594528
Leaving Monitored Scope (GetWebPartPageContent). Execution Time=53.1897210399646
Leaving Monitored Scope (PostResolveRequestCacheHandler). Execution Time=55.7009340572615
System.Runtime.InteropServices.COMException: Access denied.  You do not have permission to perform this action or access this resource.    at Microsoft.SharePoint.Library.SPRequestInternalClass.GetFileAndMetaInfo(String bstrUrl, Byte bPageView, Byte bPageMode, Byte bGetBuildDependencySet, String bstrCurrentFolderUrl, Int32 iRequestVersion, Boolean& pbCanCustomizePages, Boolean& pbCanPersonalizeWebParts, Boolean& pbCanAddDeleteWebParts, Boolean& pbGhostedDocument, Boolean& pbDefaultToPersonal, Boolean& pbIsWebWelcomePage, String& pbstrSiteRoot, Guid& pgSiteId, UInt32& pdwVersion, String& pbstrTimeLastModified, String& pbstrContent, Byte& pVerGhostedSetupPath, UInt32& pdwPartCount, Object& pvarMetaData, Object& pvarMultipleMeetingDoclibRootFolders, String& pbstrRedirectUrl, Boolean& pbObject...
...IsList, Guid& pgListId, UInt32& pdwItemId, Int64& pllListFlags, Boolean& pbAccessDenied, Guid& pgDocid, Byte& piLevel, UInt64& ppermMask, Object& pvarBuildDependencySet, UInt32& pdwNumBuildDependencies, Object& pvarBuildDependencies, String& pbstrFolderUrl, String& pbstrContentTypeOrder)     at Microsoft.SharePoint.Library.SPRequest.GetFileAndMetaInfo(String bstrUrl, Byte bPageView, Byte bPageMode, Byte bGetBuildDependencySet, String bstrCurrentFolderUrl, Int32 iRequestVersion, Boolean& pbCanCustomizePages, Boolean& pbCanPersonalizeWebParts, Boolean& pbCanAddDeleteWebParts, Boolean& pbGhostedDocument, Boolean& pbDefaultToPersonal, Boolean& pbIsWebWelcomePage, String& pbstrSiteRoot, Guid& pgSiteId, UInt32& pdwVersion, String& pbstrTimeLastModified, String& pbstrContent, Byte& pVerGhostedSet...
...upPath, UInt32& pdwPartCount, Object& pvarMetaData, Object& pvarMultipleMeetingDoclibRootFolders, String& pbstrRedirectUrl, Boolean& pbObjectIsList, Guid& pgListId, UInt32& pdwItemId, Int64& pllListFlags, Boolean& pbAccessDenied, Guid& pgDocid, Byte& piLevel, UInt64& ppermMask, Object& pvarBuildDependencySet, UInt32& pdwNumBuildDependencies, Object& pvarBuildDependencies, String& pbstrFolderUrl, String& pbstrContentTypeOrder)

I found only one link online which was relevant to this - http://sharepoint.stackexchange.com/questions/39243/you-do-not-have-permission-to-perform-this-action-or-access-this-resource-nativ.  It suggested that I perform an stsadm command to remove a setting that may have been applied.

Then I remembered.  We had been looking into the idea of restricting the people picker to only show AD accounts within a certain domain.  I had passed this on to another SharePoint engineer to look into, and he must have carried out a command with this in mind.  However, documentation on this command is limited, and it may have had a side effect.

So, to test this theory, I reset the field using stsadm:


stsadm -o setsiteuseraccountdirectorypath -url http://sp2010 -path ""

Sure enough, as soon as I completed this command, the affected accounts could now access our SharePoint site.