Chris Weldon

Rants and musings on ASP.Net, SharePoint, and Agile.

On Helpers and the Use of Static

One of my most recent interactions with several of my colleagues has been over best practices within software development. More specifically, the idea of static classes, static methods, and helper classes. It was a healthy debate with different view points. Some believe that static methods are perfectly fine for development. Others feel that helper classes provide unity to certain practices such as database access. Generally, however, I believe static and helper classes are an anti-pattern and lead to less maintainable code. This post is an expression of why I believe this to be the case. None of the code samples are actual snippets on real projects. They are paraphrased instances of practices I’ve seen on a myriad of past projects.

Communication Brevity

Let’s talk about something I really don’t like: e-mail. Let me clarify this by saying I loathe e-mails on team projects. Why? Persistence. Conversations via e-mail have this perception they will be “found” at a later time, but the proposed value is rarely so useful. Furthermore, new team members or collaborators rarely ever get that context, because it’s buried in another person’s e-mail. This is my approach to how teams should communicate to ensure longevity of this critically important information.

SharePoint 2013 My Site Timer Jobs Missing

The way My Sites are created in SharePoint 2013 is vastly different from SharePoint 2010, but for good reason. I won’t go into the details of how it’s changed, as Wictor Wilen has done an excellent job of this already in his blog post SharePoint 2013: Personal Site Instantiation Queues and Bad Throughput. I encountered problems with a new development workstation not setting up My Sites for users appropriately - blocking us from testing our solution, which was dependent upon a user having a My Site. In looking online (and in Wictor’s blog post), everything was pointing to checking the following three timer jobs:

  • My Site Instantiation Interactive Request Queue
  • My Site Instantiation Non-Interactive Request Queue
  • My Site Second Instantiation Interactive Request Queue

The problem is, those timer jobs were missing from my server!

Getting the Confusing SharePoint 2013 SocialDataStoreException

As I was writing an app using the new SharePoint 2013 app model the other day, I ran into an issue when I was trying to follow a site automatically through JavaScript:

1
The target of the operation was not found. Internal type name: Microsoft.Office.Server.UserProfiles.SocialDataStoreException. Internal error code: 0.

MigrateUsersToClaims - Operation Is Not Valid Due to the Current State of the Object

I’m in the process of migrating my customer from SharePoint 2010 to SharePoint 2013. In their SharePoint 2010 environment, they were still using classic-mode authentication, but are switching to claims-based authentication in SharePoint 2013.

The recommended path to upgrade from 2010 to 2013 is a content and service-application database migration. This works great for us since we have to do this piecemeal. However, many of the general approaches for converting to claims-based authentication is to do so at the web-application level, rather than the content-database level (source: TechNet).

In SharePoint 2013, there’s actually an SPWebApplication method dubbed MigrateUsersToClaims that takes 3 arguments:

  • NTAccount
  • removePermissionsAfter
  • SPWebApplication.SPMigrateUserParameters

There was no guidance on the NTAccount, other than the user “performing” the operation. I opted to use the farm account to ensure it had the appropriate level of permissions. The true power of the content database migration comes in with the third parameter. We can add individual content databases to migrate with this parameter rather than worrying about the entire web application.

Props go to Steve Peschka who originally pointed this out. However, in his post, the PowerShell to do this upgrade was the following:

1
2
-- SNIP -- 
$wa.MigrateUsersToClaims($acc, $true, $arguments)

For me, that throws the error Exception calling "MigrateUsersToClaims" with "3" argument(s): "Operation is not valid due to the current state of the object." This was strange, and I couldn’t figure it out. So, I cracked open the Microsoft.SharePoint.Administration dll and took a look at the MigrateUsersToClaims method:

1
2
3
4
5
6
7
8
public bool MigrateUsersToClaims(NTAccount account, bool removePermissionsAfter, SPWebApplication.SPMigrateUserParameters parameters)
{
    if ((NTAccount) null == account)
        throw new ArgumentNullException("account");
    if (removePermissionsAfter && parameters != null && (parameters.HasDatabaseToMigrate || parameters.OnlyMigratePolicyUsers))
        throw new InvalidOperationException();
    // The rest
}

That second one was the one that I questioned. I know the conditions matched for the first two checks. The question was how my parameters looked. Sure enough:

1
2
3
4
5
PS > $arguments

DatabasesToMigrate      HasDatabaseToMigrate        OnlyMigratePolicyUsers
------------------      --------------------        ----------------------
{WSS_MigrationTest_...}                 True                         False

With that, if I changed the middle parameter from $true to $false, the migration finally ran (and completed) succesfully.

Why did this happen? This was because my $acc user is my farm account. I’m also running my PowerShell session as my farm account. This is to ensure that I have full, unfettered access to the SharePoint Object Model and the Content Database. The middle parameter states (from MSDN):

The **account** will be given the correct permissions to perform the operation. Should this permission be removed when the operation is complete.

We definitely don’t want this for the farm account. So, my updated code, for reference:

1
2
3
4
5
6
7
$wa = Get-SPWebApplication http://my-app-url
$acc = "domain\farm-account"
$arguments = New-Object Microsoft.SharePoint.Administration.SPWebApplication+SPMigrateUserParameters

$contentDb = $wa.ContentDatabase["Content Database Name"]
$arguments.AddDatabaseToMigrate($contentDb)
$wa.MigrateUsersToClaims($acc, $false, $arguments)

Cheers. Once again, thanks go to Steve Peschka for figuring this out.

Sorry, Only Tenant Administrators Can Add or Give Access to This App

I have just completed building my first SharePoint 2013 application. I came across the error message Sorry, only tenant administrators can add or give access to this app. when trying to deploy the application to my site. This happened regardless if I was deploying using a SharePoint development site or after installing the solution in the app catalog.

The application required Tenant Read permissions as I’m accessing the User Profile through the JavaScript object model. The purpose of using the User Profile JSOM is to get the suggestions of sites and people to follow that SharePoint presents.

Now, the concept of a “Tenant” makes sense for Office 365 or SharePoint Online. As a hosting provider, there are multiple tenants you want to support in a single environment. However, for an on-premise deployment, this error message didn’t make much sense. I started poking around and came across spinning up a tenant administration site, being able to set multiple app tenants through the App Management Service cmdlets, but none of those really seemed like the right solution for my on-premise deployment. I found an MDSN Forum Question which seemed closer to the solution. That post recommends splitting the service accounts used to host the App Management and Site Settings services from the farm account. This was critical as the Farm Account is not allowed to add apps under its identity whatsoever. You will get an error message when trying to provision, and the ULS logs will indicate that an assertion failed checking that the current account was not the system account.

What did it turn out to be? I just needed to make sure my user account was directly added as a member of the Farm Administrators group. We have traditionally deployed farm administrators via an Active Directory and local (Administrators) group. However, it appears that the App Management service dislikes this approach and wants users explicitly permissioned to the Farm Administrators group. Additionally, after granting your user direct permissions, you need to issue an iisreset so those changes take effect. Then, you can provision your app successfully.

Editing the SharePoint 2013 My Sites Web Part Pages

The last two weeks have been interesting. I’ve been trying to deploy an app part built as part of a SharePoint 2013 app I developed recently. The app part re-creates the “Suggestions” functionality that you see when visiting the “Followed Sites” and “Followed People” pages in your My Site. Those web parts were not easily reused in other parts of My Sites. The purpose of creating this app part was to be able to add suggestions directly to the Newsfeed page to make it a more useful information radiator. Unfortunately, editing the Newsfeed page (or any page) in the “My Site Host” was not nearly as intuitive as I had hoped.

I’m used to having the ribbon to edit pages in SharePoint, regardless if they are standard publishing pages or web part pages. However, in the “My Site Host”, there is no ribbon for the standard pages, even when you are a farm administrator. I jumped to the conclusion that I could add the App Part via SharePoint Designer. Sadly, this wasn’t the case. SharePoint Designer does not list any app parts.

I tried to go through the rigarmarole of adding the app to a separate site through the web editor, then copying the code from within SharePoint Designer and pasting it into the Newsfeed page, only for that to fail. The identifiers for the apps are completely different.

This is when I stepped back and though that the solution should be simpler than this. It turns out, it was. Click the gear icon (settings menu) in the upper-right corner of SharePoint and you’ll find the Edit Page link. I felt liberated and frustrated at myself for not checking there earlier. From there, you have complete control to edit the Newsfeed web part page (or any page in the “My Site Host”).

Using the Quicktate RESTful API

Quicktate is a service for which I’ve been consulting for since 2009. We have recently released a new RESTful API to help make integrating with the service a breeze. That said, while our new RESTful API documentation uses Swagger to generate our service documentation, many of the common RESTful semantics we rely on are completely missing from that documentation. Until we figure out an easier way to convey that information via Swagger, here’s some basic information on how to get around the API.

SqlFileStream Access Is Denied

I started playing around with SQL filestreams yesterday. We have a need to store large binary objects both quickly and efficiently from SharePoint in our SQL database for regulatory purposes. I found a great article on Code Project on how to actually store binary data in a filestream column. However, as I ran the code, I encountered a Win32Exception with the message “Access is denied.”.

I double (and triple) checked that the permissions for the account executing the code were correct. Since we’re using SharePoint, we are using only Windows authentication. Furthermore, I made sure that our connection string was using Integrated Security:

1
Server=sqlserver01;Database=Journaling;Integrated Security=true;

Ultimately, it came down to the fact that the SQL Server was not setup to allow remote server connections to filestream. I managed to fix this by following the Enable and Configure FILESTREAM article on MSDN. The Allow remote clients to have streaming access to FILESTREAM data. box was not checked, thus causing my problems.