Category Archives: Technical

SP2013: Display multiple lines in the Pages (search) webpart

In SharePoint 2013, rolling up content has changed a lot. The Content Query Web Part is gone, which in my opinion is a GREAT thing. There are some new webparts to replace it, which are based on search.

One of those webparts is the Pages webpart. You can use that to show an overview of pages. By customizing the settings, you can adjust from which site the pages are shown, what kind of pages are shown, etcetera. This makes it very easy to create a news overview!

But… select one of the ootb display templates and you’ll notice that “3 lines” is exactly that: 3 individual lines. I like the summary of a news article to be as big as I require it to be, not always one single line. This article describes how to get to this result:

pages webpart multiline

Continue reading

SP2010: Administrators and permissions

At my current job, I’m more of an administrator than I am a dev. It’s quite enlightening to be honest. As a developer, you don’t tend to think that much about site structure, governance and all those things. Not that I had no experience in that, but I surely have learned some things extra since my admin job. One of those is permission management and I’d like to share a little story about that. Continue reading

SP2010: The hidden TaxonomyStaplerFeature

I am a big fan of keeping things clean. The more you clutter, the more chance of faults you might not have expected. Today, I learned that sometimes cleaner is not better.

I like using the blank site template to create new sites. Most people tend to use the team site, but that already has a document library, calendar and a number of preactivated features. Nice to start a team site, but what if the site you’re creating is not a team site?? As I said; I like starting clean.

But amongst the features not being activated by default on a blank site is a tricky one: the TaxonomyStaplerFeature (ID 73EF14B1-13A9-416b-A9B5-ECECA2B0604C). This is a stapling feature which in it’s turn activates multiple other hidden features. You need it for several taxonomy related things, like subscribing to content types from an enterprise content hub. And as said; the features are hidden, so you can only enable them if you have server access.

So I guess we’ll need another stapling feature, to staple the missing features to the blank site definition!? :-) I’m not sure yet if this is the only one which messes up pretty regular functionality. I don’t mind features I don’t use that often being off, but this one should have been on by default in my opinion. Or they could have provided another template: “blank site with no functionality whatsoever”.

WCF service using Azure relay and ADFS authentication (2/2)

In the second part of this article (read part 1 here), we’re going to extend our relayed service with AD (Active Directory) authentication. In most cases you’ll need authentication to provide some security for your business data. In this example, we’re keeping it simple; just using a valid domain account to access the data. All (enabled) accounts are valid. But with some extending, you can quite easily adapt this code to work with AD groups for instance, making sure only certain users can get to the data. This is done by using claims, perhaps I’ll cover that in a third article. Continue reading

WCF service using Azure relay and ADFS authentication (1/2)

What I’m going to write about in this two-part article is what could be considered quite a common scenario. Your company wants to expose data to its employees outside of the internal network. Take a mobile app (or Windows 8 app) for instance, which gets its data from a legacy back-end system. In “old fashioned” scenario’s, you could:

  • Create a WCF webservice to host the data.
  • Deploy the webservice into some kind of secured network zone (DMZ).
  • Kindly ask the firewall admins to open up a port to your service.
  • Register a DNS address which makes it easier to call your service.
  • Request SSL certificates and secure your service so only encrypted data is sent.

In this article, I’ll write about how Azure can make your life easier by handling some of these things in a different way. You, as a reader, should be familiar with WCF and have a basic understanding of authentication schemes. Some knowledge of what ADFS is would be handy too.

There’s two Azure topics I want to talk about: relay and ACS. In the first part of this article, we’ll talk about relay. How to setup ACS with ADFS will be topic of the second part.

 

Setting up the service bus in Azure

Relay is a technique which enables you to register your WCF service with Azure. Once registered, clients are able to call Azure instead of your service directly. And because the service initiates the communication, you only need access to the Internet, not from it. In Azure, this is handled by the service bus, which is a multifunctional messaging system. Relay is only a part of the functionality.

Here’s what happens in general:

  1. The service registers itself with Azure .
  2. Azure acknowledges the registration. The connection is kept open for future use.
  3. A client now connects to the endpoint registered with Azure and sends a webservice request.
  4. The request is relayed to the local WCF service.
  5. The result is passed back to Azure.
  6. The service bus passes the result to the client.

For you as a developer, this has some advantages:

  • The call to Azure is https secured, so all data going to Azure is always encrypted. No need to purchase an SSL certificate.
  • Same goes for data going to the client, encrypted as well.
  • No need to open up any firewall ports. Default internet access is enough to make this work
  • Although I haven’t thoroughly tested this, it should work in all kinds of proxy-enabled scenario’s too.

Ok, cool. So what do you need to make this work? To begin with, you’ll need a Windows Azure account. Open up the management portal (https://manage.windowsazure.com/) and go to the “service bus” section. Click “Create” and choose a namespace for your service bus instance:

You can request the access key once you created the service bus instance. This key is used to authenticate server / client with the service bus. In part 2, we’re going to use ACS / ADFS for that, in which case the shared secret access key is irrelevant.

Creating a relayed WCF service

Once you’ve got your service bus namespace setup, it’s time to create a service. Most easy way is to create a console application which will use a ServiceHost object to self-host the service. The most important thing here are the bindings. You will have to use two bindings:

  • One normal binding (like BasicHttpBinding) which hosts the service in a normal way, for instance on http://localhost:1234.
  • A matching relay binding (in this case BasicHttpRelayBinding) which is used to connect to Azure and relay the service.

Assuming some WCF knowledge, creating a service host should be easy:

ServiceHost serviceHost = new ServiceHost(typeof(CalculatorAPI), new Uri(serviceEndpoint));

Registering the endpoints and bindings:

serviceHost.AddServiceEndpoint(
  typeof(ICalculatorAPI), new
  BasicHttpBinding(), "/"
);

serviceHost.AddServiceEndpoint(
    typeof(ICalculatorAPI), new BasicHttpRelayBinding(
        EndToEndBasicHttpSecurityMode.None, 
        RelayClientAuthenticationType.None),
    ServiceBusEnvironment.CreateServiceUri("https", "calculator", "api"))
    .Behaviors.Add(new TransportClientEndpointBehavior
    {
        TokenProvider = TokenProvider.CreateSharedSecretTokenProvider("owner", "<<azure_access_key>>")
    });

The things to notice:

  • The bindings need to match. So use a BasicHttpRelayBinding in combination with a BasicHttpBinding and not a WsHttpBinding for instance.
  • Both endpoints register the same interface class, so both endpoints know which methods your service will provide.
  • For the relay binding, you specify the service bus address with the help of the CreateServiceUri method. This asks for a scheme, the namespace you created earlier and a service path which can be anything you like.

In the example for part 2 (ADFS), we’ll switch from using a SharedSecretTokenProvider to a SamlTokenProvider used with SAML tokens.

Basically, that’s all you need to do on the server side. Simple, right? You could create one extra endpoint to provide a mex metadata exchange binding. The code to do that:

// Check to see if the service host already has a ServiceMetadataBehavior
ServiceMetadataBehavior smb = serviceHost.Description.Behaviors.Find<ServiceMetadataBehavior>();

// If not, add one
if (smb == null)
  smb = new ServiceMetadataBehavior();

smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
serviceHost.Description.Behaviors.Add(smb);

// Add MEX endpoint
serviceHost.AddServiceEndpoint(
    ServiceMetadataBehavior.MexContractName,
    MetadataExchangeBindings.CreateMexHttpBinding(),
    serviceAddress + "/mex"
);

I would advise to use the mex endpoint only in development environments and leave it out for production. But that’s up to you, it doesn’t really matter that much.

Add a serviceHost.Open(), run your console app and see if it properly registers itself with Azure. Once it does, you should be able to create a client and connect with it.

Creating a client to match

Creating a client follows the same principles. The client counterpart of a ServiceHost is the ChannelFactory. Because it shares the interface definition, it’s wise to keep that class in a shared library. But you could also make use of the local endpoint and the “Add Service Reference” functionality of Visual Studio, which will generate an interface class for you. As long as the interface class has the same methods and signatures as your service has, you’re good.

var cf = new ChannelFactory<ICalculatorAPIChannel>(
    new BasicHttpRelayBinding(),
    new EndpointAddress(ServiceBusEnvironment.CreateServiceUri("https", "calculator", "api")));

Now, as we did with the service, we need to specify the endpoint behaviour:

cf.Endpoint.Behaviors.Add(
    new TransportClientEndpointBehavior {
        TokenProvider = TokenProvider.CreateSharedSecretTokenProvider("owner", "<<azure_access_key>>")
    });

And with that setup, you can simply create a channel and call the method of choice!

using (var ch = cf.CreateChannel())
{
    var answer = ch.Add(10, 6);
    Console.WriteLine("Answer: {0}", answer);
}

So the cool thing is, apart from some configuration and setup, it’s really not that hard to setup a relayed service. In my opinion, this is far less complicated than convincing the firewall guys to open up ports for you ;-)

This service is secure. All the communications are encrypted via SSL and both client and server need to know the shared access key to be able to connect to the service bus. But this method of authentication is pretty limited and not really usable in mobile apps scenario’s (how do you prevent some unauthorized user from using the app?). So in the follow-up of this article I will explain how to extend the sample with ADFS integrated authentication. That article will also contain a full code sample.

Update: and here’s part two.

Installing a windows service with Visual Studio 2012

Since Visual Studio 2012, the default installer project was switched for a limited edition of InstallShield. I won’t get into the discussion whether this was a step forward or backward, but it’s there.

When you’re building an installer for Windows Service, you might get stuck in the situation where the installer is deploying your files onto the filesystem, but the actual service isn’t appearing in the services console. That’s because the installer class didn’t get called to register the service. For those of you who don’t know; you need to add an installer class to your service which registers it with Windows (you can easily do so by right clicking the service and choosing “Add installer”.

Anyways. If this is the case, go to “Files” in step 2 of the installer and open it up. Right click your project and open up the properties window. Go to the second tab “COM & .NET Settings”.

COM settings

There, you’ll find a checkbox “Installer Class” which you need to enable. Now compile your installer again and there you go: it’ll register your service in Windows again.

SP2010: Errors in content deployment

This is a topic which comes up more then once when you’re working with the content deployment feature. For those of you unfamiliar with content deployment; it’s basically a process to import and export a site collection in an automated way, across farms if you like to.

But content deployment is a tricky process in which a number of things can go wrong. Most of the solution I’m going to mention are not new, but I could not find a blog which combines them all, so that’s wat I did.

Continue reading

Auto SP Solution Installer

Update 01-02-2013 As seen below in Matthias his reaction, there is already a similar project on Codeplex which I’ve clearly overlooked. I’m currently seeing if we could join forces (although their project is already very mature). So the Auto SP Solution Installer might have a short lifetime and merge into spsd.codeplex.com.

Today I published my first Codeplex project. It’s called “Auto SP Solution Installer”, based upon the well known “Auto SP Installer” from which I borrowed some code.

The goal of the project is to easy the deployment process of solutions across farms in a DTAP environment. At a lot of my customers, I notice there’s a lack of SharePoint knowledge at the administration side. The administrators sometimes barely know what they’re doing, or they’re just doing what they are told by the developers. Or even worse: the developers are deploying stuff themselves.

Let’s be honest: the Auto SP Solution Installer can’t fix a faulty lifecycle process. But it can automate some of the steps, making sure the room for error get’s smaller.

The current feature set is as follows:

  • Adding, removing, installing and updating your WSP files
  • Deploying WSP’s to specific web applications
  • Scheduled deployment of WSPs to prevent downtime
  • Warning the farm administrator about maintenance compliancy and GAC deployments
  • Installing, uninstalling, enabling and disabling features (scoped)
  • Using the same deployment configuration across all your farms in a DTAP environment. Farm configuration is seperated from solution configuration.

Basically, you create a deployment configuration (XML) and provide some WSP’s. In a seperate configuration file, the farms (yes, multiple) are described. The script figures out on which farm it’s running, which web applications exist, etc.  and then deploys your solutions as configured. The same package of WSPs and config XML can then be moved to the next farm (test, acceptance, production) and re-used there without changing anything.

Also, the script will warn the administrator about maintenance windows and GAC deployments which will cause downtime to all of your web applications (IIS reset).

Interested? The first initial release can be found on Codeplex: http://autospsolinstaller.codeplex.com

SP2010: InfoPath, UserProfileService and 401 Unauthorized

The last few days I was working on a problem reported by a user using InfoPath Service. A browser based form had to connect to the UserProfileService.asmx webservice in order to read some profile data to populate a form. This was working untill the web application was switched to claims based authentication. After that change, the webservice stopped working and (401) Unauthorized errors occurred in the logs.

It took me quite some time to find a stable solution, and you need to check for several things. I though I’d share this solution for others to use.

First, this is how our environment is configured:

  • InfoPath Services run browser based forms (problem does not occur client side).
  • The WebApplication is a claims based app.
  • Kerberos is configured as authentication mechanism.

Now here’s what you got to do to get this to work:

  • First, configure a Secure Store entry. If you don’t have a Secure Store setup, you need to get one, there’s enough info out there on how to do that.
  • Configure the entry as type Group with a Windows username and Windows password.
  • Set the credentials for the entry, make sure your user group has access to the entry. The account you configure will need rights to the user profile service application, so you’ll probably want to use a (dedicated) service account.
  • The account you specified needs rights to be able to actually use the webservice. This might be confusing, because all authenticated accounts have enough rights to open the WSDL. But that’s not enough when you want to use the service.
  • To set the correct rights, go to your Service Application management page, click the User Profile Service instance and choose ‘Administrators’ in the ribbon. Add the previously configured account. I chose to give it full rights, but you could fiddle a bit with which rights you actually need to perform the tasks requested.

 

  • Now create your data source in InfoPath and point it to the UserProfileService.asmx webservice (/_vti_bin/UserProfileService.asmx?WSDL). In our case, the GetUserProfileByName method was used to get the users’ details.
  • Because the service will be called as the SSO user, you need to delay loading because you need to set the username as a parameter. So don’t check the checkbox which asks if the data should be loaded as soon as the form loads.
  • Instead, go to the Data ribbon tab and click “Form Load”. Now configure two new actions, first “Set a field’s value”. Choose the username parameter for the webservice method and set userName() as the value (this is a function found under the User function category.
  • As second action, set “Query using a data connection” and set the form to query the webservice.

 

  • Return to your form and click “Manage Data Connections” in the Fields toolpane.
  • Convert your datasource to a data connection file. This file needs to be stored in SharePoint in a Data Connection Library. If you don’t have one yet, create it as you would create a normal document library (but choose the data connection library type instead, obviously).
  • The file will be created as a UDCX. The last step is to open up that file and look for this line:
    <!--udc:Authentication><udc:SSO AppId='' CredentialType=''/></udc:Authentication-->

    Without authentication set, InfoPath will perform the call as an anonymous user, which results in the (401) Unauthorized exception.

  • Replace the above line with:
    <udc:Authentication><udc:SSO AppId='YourSSOAppId' CredentialType='NTLM'/></udc:Authentication>

    Now you’re telling InfoPath it needs to query the configured SSO service application, retrieve the credentials stored for application ‘YourSSOAppId’ and use them to query the webservice. And because you’ve configured an account which you added to the User Profile Service Application, this account will have enough rights to perform the request.

  • When you don’t use claims and you want to use Kerberos to delegate your user credentials, you need to check two more things. First, make sure you’ve configured local loopback checking and disabled it (either completely, or per URL).
  • Secondly, avoid double-hop issues by making sure the web front-end servers point to themselves. Do this by editing the hosts file and add records for 127.0.0.1 (hence the local loopback check) for the DNS addresses you use.
  • And to be complete; of course you need a valid Kerberos setup in that case. But you won’t be able to access your web application at all when you don’t, so that’s a different topic alltogether.

That’s it! With these steps you should be able to use the built in UserProfileService.asmx webservice in a claims (or classic) based web application from within InfoPath forms. Good luck!

 

SP2010: Whoops! I mirrored all of my databases…

So you’re building a SharePoint farm which has to have a high percentage of availability. And to get that, you decide to make your databases highly available by the techniques offered by SQL Server. Think mirroring, or AlwaysOn if you’re using SQL2012. Which technique you’re using doesn’t really matter; you have to realise that this is not supported for all databases!

The good news; the databases which don’t support mirroring aren’t vital to keeping your sites up. It’s these three:

  • Usage and Health Data Collection service application Logging database (typically called “WSS_Logging”)
  • User Profile service Synchronization database (Typically known as “Sync DB”)
  • Web Analytics Staging database (typically called “WebAnalyticsServiceApplication_StagingDB”)

Also note that search databases don’t have to be mirrored, because search has it’s own high availability mechanism. It’s doesn’t matter though, when you do have then mirrored. It’s just not nessessary.

Ok. But you didn’t consider this when you were building your farm. Eventually, you’ll run into problems; most likely when applying updates to your farm. These will fail with the message that mirroring is not supported for your databases. So then what?

Well, just use this Powershell script below and you’ll be able to change the alias for the databases which don’t support mirroring. Make sure that you first create the alias on all of your farm servers!

$alias = "sql-alias"

$uh_name = "Usage and Health Data Collection"
$uh_database = "SP2010_UsageAndHealthDB"
$wa_name = "Web Analytics Service Application"
$wa_database = "SP2010_WebAnalyticsStagingDB"
$up_name = "User Profile Service Application"
$up_database = "SP2010_UPSSyncDB"

Write-Host "Changing the database server for $uh_name"
$uh_app = Get-SPServiceApplication |? { $_.Name -eq $uh_name }
Set-SPUsageApplication -Identity $uh_app -DatabaseServer $alias -DatabaseName $uh_database

Write-Host "Changing the database server for $wa_name"
$wa_app = Get-SPServiceApplication |? { $_.Name -eq $wa_name }
$stagingDbs = ""
Set-SPWebAnalyticsServiceApplication -Identity $wa_app -ListOfStagingDatabases $stagingDbs

Write-Host "Changing the database server for $up_name"
$db = Get-SPDatabase |? { $_.Name -eq $up_database }
$db.ChangeDatabaseInstance($alias)

Source for non supported databases: http://mmman.itgroove.net/2012/03/some-databases-are-too-ugly-for-the-mirror/

Update 24-5-2013: it seems the above script leaves you with a database reference for the WebAnalyticsStagingDB. This causes exceptions with health monitoring rules which check these references for good database health. This can be easily solved by running Get-SPDatabase, selecting the correct one and issuing a Delete() command on it. This will remove the reference, making sure the health rules won’t check it again. This only happens for that single database, it seems the other ones are being cleaned up properly.