Creating a Client Application to Export Users in Sitecore

The User management options available in Sitecore are basic: the User Editor, Role Editor, Security Editor etc, but organisations sometimes want to export the users for import into other systems. Recently a client needed the ability to export sets of Users periodically from Sitecore, and requested an application be added to the Sitecore Client to do so. (It would be quite easy to extract this information from the databases directly, but the client did not want to do this).

Basically, the problem has two parts:

1.) Creation of the Desktop Application
2.) Creation of the extraction code

Sitecore Applications come in two flavours: Sheer UI applications and .aspx based applcations. This application uses the .aspx method which should be easy for anyone who has done any Web Forms programming, rather than the Sheer UI method which I have found to be problematic and difficult to debug. Sheer UI is being superseded by SPEAK technology, apparently, too.

1.) Log in to the Desktop
2.) Select the core database
3.) Go into Developer Center, create a Layout (.aspx), complete all dialogs
4.) Open the Content Editor, select the Applications node, right mouse click to Add Application
5.) Select Presentation Details from the ribbon, Edit, Add the Layout just created
6.) Navigate to /sitecore/content/Documents and settings/All users/Start menu/Left
7.) Right Mouse click to create an Application Shortcut
8.) Populate Application field pointing to the Application created in step 4
9.) Add a Display name
10.) Exit from the core database, the Application should be visible in the desktop menu.

This process should have created a .aspx file in your Sitecore solution to which the code to export can be added. In this example I have decided to export just the Users for a particular Role:
“extranetClub”. Having created a basic form with a TextBox for the filename and a Submit Button the following code can be used:

protected void SubmitButton_OnClick(object sender, EventArgs e)
{
   var userList = Roles.GetUsersInRole("extranet\Club").Select(Membership.GetUser).ToList();

   var exportData = userList
   .Select(membershipUser => Sitecore.Security.Accounts.User.FromName(membershipUser.UserName, true))
   .Select(sitecoreUser => sitecoreUser.Profile)
   .Aggregate("", (current, sitecoreProfile) => current +
   string.Format("{0},{1}{2}", ParseFirstLastName(sitecoreProfile.FullName),
   sitecoreProfile.Email, Environment.NewLine));

   DownloadFile(exportData);
}

In order to access these users a combination of Membership API calls and Sitecore Security calls are required, which means that some qualifying namespaces are needed to avoid ambiguity for Objects like User which exist in the membership library and in the Sitecore Security library.

The Username in this system contains a single string with the first and last names separated with a space, so the ParseFirstNameLastName method breaks this out to separate fields:

private string ParseFirstLastName(string fullName)
{
   var offset = fullName.Trim().IndexOf(" ", 0, StringComparison.InvariantCultureIgnoreCase);
   return offset != -1
   ? string.Format("{0},{1}", fullName.Substring(0, offset), fullName.Substring(offset))
   : string.Format("{0},", fullName);
}

Then all that remains is to cause the resulting string to download as a CSV file:

private void DownloadFile(string exportData)
{
   Response.ContentType = "text/csv";
   Response.AddHeader("Content-Disposition",
   string.Format("attachment;filename={0}",
   Filename.Text));

   Response.AddHeader("content-length",
   exportData.Length.ToString(CultureInfo.InvariantCulture));
   Response.Write(exportData);
   Response.End();
}

And there you have it. Obviously this can be easily extended if the implementation has additional custom fields, and I have concatenated these to the output using another private method:

private string GetCustomJobFields(UserProfile sitecoreProfile)
{
  var jobFunction = sitecoreProfile.GetCustomProperty("Job Function");
  var companyName = sitecoreProfile.GetCustomProperty("Company Name");
  return string.Format("{0},{1}", jobFunction, companyName);
}

Done.