User Profile Service–List of Synchronization Connections Shows Nothing

This has happened to me a couple times now.  I go to run a full profile synchronization in SharePoint 2010, it appears to cycle fully, but in the end no user profiles get updated.  I go to look at my Synchronization Connection settings and nothing is shown in the list – just a message “”The query returns nothing.”.  Alas, I know I’ve configured the connection.

Can’t explain why this is happening, but its related to the Forefront Identity Manager Service.  It shows as startup type automatic in the Services Console, but the status is blank.  Manually start the service and the problems seem to go away.  Maybe when I have some time I’ll try to get to the root of this problem – why isn’t the service starting on its own?

Posted in Uncategorized | Leave a comment

SharePoint 2010 – The form cannot be rendered. This may be due to a misconfiguration of the Microsoft SharePoint Server State Service. For more information, contact your server administrator.

OK, so I’ve been just a little hands-off for the past couple years as I took on more project/practice management responsibilities. But here I am in my new position, eagerly getting my hands back in the dirt. I’m sure much of what I’ll post here in the beginning is common knowledge, but the blog thing for me is just as much of a personal reference as anything else.

Back to the purpose of this post. I just deployed my first custom workflow to my new SharePoint 2010 dev environment. When I tried to kick the workflow off from the browser, I got this (actually helpful) error message – “The form cannot be rendered. This may be due to a misconfiguration of the Microsoft SharePoint Server State Service. For more information, contact your server administrator.”. The guide I followed for setting up my environment didn’t mention anything about the State Service, but give it a quick Google and you’ll see that it’s quite important for InfoPath Forms Services. But how to create this Service Application? I didn’t come across anything in the Manage Service Applications interface, but thanks to Jeremy Taylor’s post, I was back up and running in no time. Here’s the PowerShell script needed to create the State Service Application:

   1: $serviceApp = New-SPStateServiceApplication -Name "State Service Application"

   2: New-SPStateServiceDatabase -Name "Dev_State_DB" -ServiceApplication $serviceApp

   3: New-SPStateServiceApplicationProxy -Name "State Service Application" -ServiceApplication $serviceApp -DefaultProxyGroup

Posted in Uncategorized | Leave a comment

More to come…

Working now on recreating my old (and much neglected) blog that previously lived on SharePointBlogs.com. I’ve found backup copies of all my posts. Hope to get them all back up here over the next few days, and even hope to start writing some new ones as I get myself back into the swing of things.

Posted in Uncategorized | Leave a comment

Sample code for adding/deleting MOSS alerts

Please somebody tell me there’s a better way to delete an alert. I’m too lazy to spend more time on this…

Create an alert…

   1: try

   2: {

   3:     string[] alertUsers = web.Alerts.GetUniqueUsers();

   4:     Guid alertGuid = web.Alerts.Add(

   5:         web.Lists[_documentLibraryName], 

   6:         SPEventType.Add, 

   7:         SPAlertFrequency.Immediate);

   8:     SPAlert alert = web.Alerts[alertGuid];

   9:     alert.User = web.SiteUsers[roleName];

  10:     alert.Update();

  11: }

  12: catch (Exception e)

  13: {

  14:     throw new Exception("Error creating document library notification for company.", e);

  15: }

Delete an alert…

 
   1: string[] usersWithAlerts = web.Alerts.GetUniqueUsers();

   2: //check to see if there is an alert configured for this role

   3: if (Array.IndexOf(userName) >= 0)

   4: {

   5:     SPList docList = web.Lists[_documentLibraryName];

   6:     for( int i = web.Alerts.Count -1; i >= 0; i--)

   7:     {

   8:         SPAlert alert = web.Alerts[i];

   9:         if (alert.List = docList)

  10:         {

  11:             if (alert.User.Name == roleUserName)

  12:             {

  13:                 web.Alerts.Delete(alert.ID);

  14:             }

  15:         }

  16:     }

  17: }

Posted in Uncategorized | Leave a comment

Super Simple Feature for Hiding the Search Scope DropDown

So I need to hide the scope drop down that shows up next to the search box in my SharePoint MasterPage. 

Me:  “That’s gotta be simple…  Just open up SharePoint designer and set some property on the search control.” 

SharePoint: “Silly little boy!  Say hello to my little friend…err… DelegateControl!”

<Enter Jesse into world of SharePoint delegate controls>

Foolishness aside, the concept behind the DelegateControl is actually pretty useful, and because of it I was able to roll a very straightforward feature permitting me to hide the scope drop down in my MasterPage.  And I didn’t even have to write one line of code… a true ode to developer sloth.

The feature….

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <!-- Copyright (c) Microsoft Corporation. All rights reserved. -->
   3: <Feature  Id="085B7E09-1D3E-41a7-9FEE-0C88F4394920"
   4:           Title="Custom Basic Search Control Feature"
   5:           Description="A feature for a search control that hides the Scope drop-down."
   6:           DefaultResourceFile="spscore"
   7:           Version="1.0.0.0"
   8:           Scope="WebApplication"
   9:           xmlns="http://schemas.microsoft.com/sharepoint/">
  10:     <ElementManifests>
  11:         <ElementManifest Location="searcharea.xml"/>
  12:     </ElementManifests>
  13: </Feature>

 

SearchArea.xml…

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
   3:     <Control 
   4:         Id="CustomSmallSearchInputBox" 
   5:         Sequence="1"
   6:         ControlClass="Microsoft.SharePoint.Portal.WebControls.SearchBoxEx" ControlAssembly="Microsoft.SharePoint.Portal, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c">
   7:     <Property Name="GoImageUrl">/_layouts/images/gosearch.gif</Property>
   8:     <Property Name="GoImageUrlRTL">/_layouts/images/goRTL.gif</Property>
   9:     <Property Name="GoImageActiveUrl">/_layouts/images/gosearch.gif</Property>
  10:     <Property Name="GoImageActiveUrlRTL">/_layouts/images/goRTL.gif</Property>
  11:     <Property Name="DropDownMode">HideScopeDD</Property>
  12:     <Property Name="SearchResultPageURL">/_layouts/osssearchresults.aspx</Property>
  13:     <Property Name="ScopeDisplayGroupName"></Property>
  14:     <Property Name="FrameType">None</Property>
  15:     </Control>
  16: </Elements>

Two important things to note here… the Id of the control (CustomSmallSearchInputBox) and the DropDownMode (there are actually a bunch of different values you can set here).  So, install your feature, reference the CustomSmallSearchInputBox in your MasterPage and you’re ret’ to go:

   1: <asp:ContentPlaceHolder id="PlaceHolderSearchArea" runat="server">
   2:       <SharePoint:DelegateControl runat="server" ControlId="CustomSmallSearchInputBox"/>
   3: </asp:ContentPlaceHolder>

Theoretically speaking, you could roll your feature with the same ID as the SharePoint feature (SmallSearchInputBox), set the Sequence attribute to something super low, install your feature, and have your customized version start showing up throughout the site.  I myself prefer to keep my changes more modular.

Posted in Uncategorized | Leave a comment

Integrating an ASP.NET Application into our SharePoint Portal

This was actually a conversion and integration effort.  Our client had a rather old and outdated MS Access application that they wanted to integrate into their soon-to-be-deployed SharePoint portal.  My good friend and coworker, Yuriy Shvadskiy, took on the tremendous effort of first converting the Access database to Sql Server 2005 and also designed/implemented the Asp.Net front-end.  Perhaps I’ll try to get him to write something up about this effort… the final product was a great conglomeration of skill and technology.

After the Asp.Net app was complete we formulated a plan for MOSS integration (with some guidance from our trusty SharePoint Guru).  As many of us know, there are a couple ways to go about this.  I think the most well known and popular is probably ye olde _layouts directory.  Pop your assemblies in the GAC (or web app bin), drop your aspx pages in 12\Template\Layouts, and… whalah – application integrated (yes, I know I’m probably missing some steps here).  My quarrel with this approach is that we end up losing a fair amount of the functionality provided by SharePoint, most importantly security.

In the end we went with an approach that Vishwas outlines in one if his whitepapers (the name and location of which escapes me now): Convert the Asp.Net front end into a series of custom publishing page layouts and deploy the page layouts to our target site.  Here’s an outline of the steps we took:

  1. Convert each Asp.Net page into one or more Asp.Net User Controls.
  2. Deploy the controls to the ControlTemplates directory.
  3. For each page in the Asp.Net app, create a custom page layout containing its respective User Control(s).
  4. Deploy the page layouts to the target site, and create a single page instance for each page layout.

Pretty simple, really.  Our final product was a SharePoint solution consisting of two features:  one for the system master page and file dependencies (stylesheets, etc) and another for the custom  page layouts.  The solution also packaged the system assemblies, web services, and custom User Controls. But, as we all know, the devil is in the details.  Creating a robust and usable product required us to do more than just deploy the layouts.  I’ll try to supply a couple of the points and snippets that I found to be the most useful.  Please let me know if there’s something you think that I should cover that I haven’t and I’ll fill in the details.

The Custom Page Layouts

If you open up SharePoint Designer (I know, painful), you’ll find all the OOTB layouts in the MasterPage Gallery.  A closer look at many of these reveals that none of them are exactly simple.  So, here’s (what I think to be) the foundation mark-up for a blank page layout:

   1: <%@ Page language="C#"   Inherits="Microsoft.SharePoint.Publishing.PublishingLayoutPage,Microsoft.SharePoint.Publishing,Version=12.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c" %>
   2: <asp:Content ID="Content2" ContentPlaceholderID="PlaceHolderAdditionalPageHead" runat="server"></asp:Content>
   3: <asp:Content ID="Content3" ContentPlaceholderID="PlaceHolderPageTitle" runat="server"></asp:Content>
   4: <asp:Content ID="Content4" ContentPlaceholderID="PlaceHolderPageTitleInTitleArea" runat="server"></asp:Content>
   5: <asp:Content ID="Content5" ContentPlaceHolderId="PlaceHolderTitleBreadcrumb" runat="server"></asp:Content>
   6: <asp:Content ID="Content6" ContentPlaceholderID="PlaceHolderMain" runat="server"></asp:Content>

To take it a step further, here’s one of our ‘production ready’ custom page layouts.  You’ll see that it registers some additional SharePoint assemblies, registers some additional CSS, and puts a breadcrumb control on the page.  Also notice that we register our custom user control and place it in the main content area.

   1: <%@ Page language="C#"   Inherits="Microsoft.SharePoint.Publishing.PublishingLayoutPage,Microsoft.SharePoint.Publishing,Version=12.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c" %>
   2: <%@ Register Tagprefix="SharePointWebControls" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
   3: <%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> 
   4: <%@ Register Tagprefix="PublishingWebControls" Namespace="Microsoft.SharePoint.Publishing.WebControls" Assembly="Microsoft.SharePoint.Publishing, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> 
   5: <%@ Register Tagprefix="PublishingNavigation" Namespace="Microsoft.SharePoint.Publishing.Navigation" Assembly="Microsoft.SharePoint.Publishing, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
   6: <%@ Register Src="~/_controltemplates/AisHelloWorldControl.ascx" TagName="AisHelloWorldControl" TagPrefix="uc1" %> 
   7: <asp:Content ID="Content2" ContentPlaceholderID="PlaceHolderAdditionalPageHead" runat="server">
   8:     <SharePointWebControls:CssRegistration ID="CssRegistration1" name="<% $SPUrl:~sitecollection/Style Library/~language/Core Styles/rca.css %>" runat="server"/>
   9: </asp:Content>
  10: <asp:Content ID="Content3" ContentPlaceholderID="PlaceHolderPageTitle" runat="server">
  11:      Travel List
  12: </asp:Content>
  13: <asp:Content ID="Content4" ContentPlaceholderID="PlaceHolderPageTitleInTitleArea" runat="server"></asp:Content>
  14: <asp:Content ID="Content5" ContentPlaceHolderId="PlaceHolderTitleBreadcrumb" runat="server">
  15:     <div class="breadcrumb">
  16:         <asp:SiteMapPath ID="siteMapPath" Runat="server" SiteMapProvider="CurrentNavSiteMapProviderNoEncode"
  17:             RenderCurrentNodeAsLink="false" SkipLinkText="" CurrentNodeStyle-CssClass="breadcrumbCurrent" NodeStyle-CssClass="ms-sitemapdirectional"/>
  18:     </div>
  19: </asp:Content>
  20: <asp:Content ID="Content6" ContentPlaceholderID="PlaceHolderMain" runat="server">
  21:         <uc1:AisHelloWorldControl ID="ucMain" runat="server" />
  22: </asp:Content>

The Feature

The feature consisted of two components:  the file modules used to deploy the layouts to the target site, and the feature activation code which we used to provision the pages (more on that in a bit). Chris O’Brien has a great post as part of his series on deploying SharePoint artifacts as features that really helped to guide the way on this and explain some of the peculiarities.  Here’s a snippet from our ElementManifest showing how to package a single page layout:

   1: <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
   2:     <Module Name="AisCustomPageLayouts" Url="_catalogs/masterpage" Path="." RootWebOnly="TRUE">
   3:         <File Url="AisHome.aspx" Path="AisHome.aspx" Type="GhostableInLibrary">
   4:             <Property Name="Title" Value="Travel System Default Page" />
   5:             <Property Name="ContentType" Value="$Resources:cmscore,contenttype_pagelayout_name;" />
   6:             <Property Name="PublishingPreviewImage" Value="~~SiteCollection/_catalogs/masterpage/$Resources:core,Culture;/Preview Images/WelcomeSplash.png, ~SiteCollection/_catalogs/masterpage/$Resources:core,Culture;/Preview Images/WelcomeSplash.png" />
   7:             <Property Name="PublishingAssociatedContentType" Value=";#Page;#0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF39;#"/>
   8:         </File>
   9:     </Module>
  10: </Elements>

The idea here was to create a one shot deployment, so we aimed at eliminating as many manual steps as possible via some FeatureReceiver code.  The following snippet shows how we created the system’s own subsite  and  pages.  You’ll also notice that the code strips security permissions from the custom page layouts.  This was done to prevent the custom page layouts from showing up as options on the ‘Create Page’ page.  Wouldn’t want anyone hacking our system by creating duplicate pages outside of the locked-down site…  The snippet is kinda long and unorganized (like this post), so let me know if you need any clarification on what I’ve got here.

   1: public override void FeatureActivated(SPFeatureReceiverProperties properties)
   2: {
   3:     try
   4:     {
   5:         using (SPWeb web = ((SPSite)properties.Feature.Parent).OpenWeb())
   6:         {
   7:             //create the travel system subsite, its groups, and pages.
   8:             CreateSiteAndPages(web);
   9:  
  10:             //strip perm's on layouts so that regular content authors/editors cannot create instances of our custom page layouts
  11:             //(if permission has been removed the page won't show up in the CreatePage list of layouts.
  12:             StripLayoutPermissions(web);
  13:         }
  14:     }
  15:     catch (Exception e)
  16:     {
  17:         System.Diagnostics.EventLog.WriteEntry(this.ToString(), "An error occurred during the FeatureActivated event." +
  18:             Environment.NewLine + e.ToString(), System.Diagnostics.EventLogEntryType.Error);
  19:     }
  20: }
  21:  
  22: private void CreateSiteAndPages(SPWeb web)
  23: {
  24:     //create the travel system site collection.
  25:     SPWeb aisSystemWeb = web.Webs.Add(@SiteUrl,SiteName, "AIS System Site Architecture Prototype", Convert.ToUInt16(1033), web.WebTemplate, true, false);
  26:  
  27:     //create site groups (if they don't already exist) and assign proper permissions.
  28:     CreateAllSiteGroups(web, aisSystemWeb );
  29:  
  30:     PublishingWeb aisSystemPublishingWeb = PublishingWeb.GetPublishingWeb(aisSystemWeb );
  31:     //create the root level pages. 
  32:     CreateAndPublishPage(aisSystemPublishingWeb , "AisHome.aspx", "AIS System Home", true);    
  33: }
  34:  
  35: //create a single publishing page for the specified page layout.
  36: private PublishingPage CreateAndPublishPage(PublishingWeb publishingWeb, string layoutName, string pageName, string title, bool inludeInNav)
  37: {
  38:     //get a list containing all my custom page layouts
  39:     Dictionary<string, PageLayout> layouts  = GetPageLayouts(publishingWeb);
  40:  
  41:     if (!layouts.ContainsKey(layoutName.ToUpper()))
  42:     {
  43:         System.Diagnostics.EventLog.WriteEntry(this.ToString(), String.Format("Unable to create page because the layout '{0}' was not found.", layoutName), 
  44:             System.Diagnostics.EventLogEntryType.Error);
  45:         return null;
  46:     }
  47:  
  48:     PageLayout layout = layouts[layoutName.ToUpper()];
  49:  
  50:     if (pageName == null)
  51:         pageName = layoutName;
  52:  
  53:     PublishingPage page = publishingWeb.GetPublishingPages().Add(pageName, layout);
  54:     page.Title = title;
  55:     page.IncludeInCurrentNavigation = inludeInNav;
  56:     page.IncludeInGlobalNavigation = false;
  57:     page.Update();
  58:     page.CheckIn("");
  59:     page.ListItem.File.Publish("");
  60:     try
  61:     {
  62:         page.ListItem.File.Approve("");
  63:     }
  64:     catch (SPException) { }//not all sites require content approval, but I don't know how to check for this🙂
  65:     return page;
  66: }
  67:  
  68: private  Dictionary<string, PageLayout> GetPageLayouts(PublishingWeb web)
  69: {
  70:     //get a (hardcoded) list of all my custom page layout names.
  71:     Dictionary<string, string> allLayoutNames = GetPageLayoutNameLookupList();
  72:     Dictionary<string, PageLayout> layouts = new Dictionary<string, PageLayout>();
  73:     //this is the content type id for the 'Page' content type
  74:     const string PageLayoutContentId = "0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF39";
  75:     SPContentTypeId pageContentTypeId = new SPContentTypeId(PageLayoutContentId);
  76:  
  77:     foreach (PageLayout layout in web.GetAvailablePageLayouts(pageContentTypeId))
  78:     {
  79:         if( allLayoutNames.ContainsKey(layout.Name.ToUpper()))
  80:             layouts.Add(layout.Name.ToUpper(), layout);
  81:     }
  82:  
  83:     return layouts;
  84: }
  85:  
  86: private void StripLayoutPermissions(SPWeb web)
  87: {
  88:     Dictionary<string, string> allLayoutNames = GetPageLayoutNameLookupList();
  89:     PublishingWeb pubWeb = PublishingWeb.GetPublishingWeb(web);
  90:     SPContentTypeId pageContentTypeId = new SPContentTypeId(PageLayoutContentId);
  91:  
  92:     foreach (PageLayout layout in pubWeb.GetAvailablePageLayouts(pageContentTypeId))
  93:     {
  94:         if (allLayoutNames.ContainsKey(layout.Name.ToUpper()))
  95:         {
  96:             SPListItem item = layout.ListItem;
  97:             item.BreakRoleInheritance(false);
  98:         }
  99:     }
 100: }

Using the Ajax Control Toolkit

I sure as…. uhm…. wouldn’t be the first guy to blog about the challenges and hoops you must jump through to get the toolkit working in SharePoint, so I won’t blather on about it.  I will say, however, that there are definitely some useful posts out there – this post by Mike Ammerlaan being the one that we found most detailed and useful. 

The biggest gotcha we faced was using the <asp:ScriptManager>.  Each of our custom page layouts consisted of one custom User Control.  That User Control registered the required single instance of the ScriptManager.  This worked just fine until we came to integration testing, at which point we realized the portal master page was also the Ajax Control Toolkit, and was registering another ScriptManager on the page.  It took us awhile (and a bunch of ‘Unknown Error’ messages) to chase this down, but in the end we decided to remove the ScriptManager from the user controls and count on the master page always registering the required single instance.

There are some obvious problems with this approach.  Ideally, I would have preferred to make the user controls smart… have them figure out if the ScriptManager already existed in the page, and if not, do so.  I had no luck with coding something like this, so please chime in here if anyone out there has.  The real problem here is that using the custom page layouts outside of our portal (which uses our custom master page) will always require some type of additional customization/manual configuration.  Yuck.

 

Well… that turned out being much longer than I had originally anticipated, and I feel like there are things I didn’t cover that I should have.  Feedback please!

Posted in Uncategorized | Leave a comment