Solutionizing .NET

  • SPDataSource Fields for Webs & ListsOfLists
  • SPDisposeCheckID Reference
  • Pages

    • SPDataSource Fields for Webs & ListsOfLists
    • SPDisposeCheckID Reference
  • Categories

    • .NET (29)
    • Books (2)
    • F# (2)
    • General (3)
    • Git (5)
    • LINQ (7)
    • PowerShell (13)
    • SharePoint (61)
      • Branding (4)
      • Community (6)
      • Features (4)
      • Object Model (42)
      • Tools (9)
      • Web Services (1)
      • WebParts & Controls (5)
    • Silverlight (2)
  • Tags

    AJAX AsSafeEnumerable BreakRoleInheritance Central Administration ContentDeploymentJob ContentDeploymentJobCollection CVINETA DataContext Debugging delegates Dependency Injection dispose Expression Trees extension method Feature Properties Functional Construction Functional Programming Hacking LINQ HCI higher-order function HttpHandler IADNUG IASPUG idiomatic code IDisposable IEqualityComparer ILazyContext ILazyQueryable Iterators JSON Kirk Hofer LazyLinq LINQ LINQ Join LINQ SelectMany LINQ to SQL ListOfLists ListViewWebPart MenuTemplate MySite NotImplementedException NUnit ParentWeb posh-git PowerShell PowerShellASP Queryable Refactor SharePoint Iowa SPAdministrationWebApplication SPDataSource SPDataSourceMode.ListOfLists SPDataSourceMode.Webs SPDisposeCheck SPExLib SPFieldLookupValue SPFile.OpenBinaryStream SPJobDefinition SPList SPLongOperation SPMenuField SPWeb SPWebApplication SPWebCollection SPWebConfigModification STSDev STSDev Solution Generator Testing Themes Typemock Isolator Unit Testing User Profile VSeWSS XPath yield return

MySite Redirect Update

December 24, 2008 — Keith Dahlby

Per Ian’s suggestion, I’ve updated the MySite Redirect solution (CodePlex) to support the Force=True parameter passed by the “My Settings” link.

I was curious how the default control handled this case, so I went hunting. The delegate control is added in the MySite farm feature (which also adds the controls for “My Site” and “My Links” to delegates GlobalSiteLink1 and 2, respectively) via _controltemplates/mysiteredirection.ascx, which loads Microsoft.SharePoint.Portal.WebControls.MySiteRedirectionUserControl. The redirect logic of the control is obfuscated, but I still got something  for my effort:

public void OnFormInit(object objOfInterest)
{
    SPListItem user = objOfInterest as SPListItem;
    if (user != null)
    {
        this.RedirectIfNecessary(user);
    }
}

It had never occurred to me that objOfInterest might actually be of interest, but it turns out to be an item from the internal users list (_catalogs/users). As much fun as it was to go hunting for the account in the control tree, I prefer the performance of a simple cast:

public void OnFormInit(object objOfInterest)
{
    var user = objOfInterest as SPListItem;
    if(user != null)
        RedirectIfNecessary(user[SPBuiltInFieldId.Name] as string);
}

I also changed ServerContext.Default to ServerContext.Current, which is shared across an HttpContext. The revised redirect logic is pretty clean:

protected void RedirectIfNecessary(string user)
{
    try
    {
        if (string.IsNullOrEmpty(user))
            return;

        bool force = false;
        if (bool.TryParse(Request.QueryString["Force"], out force) && force)
            return;

        var sc = ServerContext.Current;
        if (sc == null)
            return;

        var mgr = new UserProfileManager(sc);
        if (mgr != null && mgr.UserExists(user))
            Response.Redirect(mgr.MySiteHostUrl.Trim('/') +
                              "/Person.aspx?accountname=" + user);
    }
    catch (SPException) { }
}

Updated Source v0.2

Update 3/27/2009: Updated Source v0.3

  • Get username from Account field (Name site column) instead of Title
  • Quit early if user is empty
Advertisement
Posted in Object Model, SharePoint. Tags: IFormDelegateControlSource, MySite, OnFormInit, User Profile. 4 Comments »

User Profile MySite Redirect via Delegate Control

December 8, 2008 — Keith Dahlby

Ian Morrish recently posted a solution to the problem that _layouts/userdisp.aspx, the default destination of user links in SharePoint, won’t redirect to the user’s MySite in certain situations. His code works great, but there’s a bit of a snag: it breaks supportability. However, SharePoint’s delegate control functionality provides an opportunity to reproduce his results without breaking the rules. But first, we need to make a few tweaks to let his code work as a delegate.

Since the UserListForm property is protected (sigh), we need to find the control ourselves. FindControl doesn’t search down the control tree, so we need a method that does:

public static T FindControl<T>(this Control root, string id) where T : Control
{
    Control c = root;
    Queue<Control> q = new Queue<Control>();

    if (c == null || c.ID == id)
        return c as T;
    do
    {
        foreach (Control child in c.Controls)
        {
            if (child.ID == id)
                return child as T;
            if (child.HasControls())
                q.Enqueue(child);
        }
        c = q.Dequeue();
    } while (c != null);
    return null;
}

This iterative implementation should perform better than its recursive alternative, particularly on a deep tree like that which SharePoint generates.

Next, we build our delegate control. Rather than reinvent the wheel, I used Zac Smith‘s example as a starting point:

public class ProfileMySiteRedirectControl : UserControl, IFormDelegateControlSource
{
    public void OnFormInit(object objOfInterest)
    {
        Redirect();
    }

    public void OnFormSave(object objOfInterest) { }

    protected void Redirect()
    {
        try
        {
            var s = Page.FindControl<FormComponent>("UserListForm");
            var sc = ServerContext.Default;
            if (s == null || sc == null)
                return;

            var account = s.Item["Account"] as string;
            var mgr = new UserProfileManager(sc);
            if (mgr != null && mgr.UserExists(account))
                Page.Response.Redirect(mgr.MySiteHostUrl + "/Person.aspx?accountname=" + account);
        }
        catch (SPException) { }
    }
}

Finally, we need a feature to activate the control. Delegate controls are attached through features scoped at either the Farm or the WebApp level, with an element manifest containing something like this:

<Control Id="ProfileRedirection"
    Sequence="50"
    ControlAssembly="Solutionizing.ProfileMySiteRedirect, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9f549a4d9093d696"
    ControlClass="Solutionizing.ProfileMySiteRedirect.ProfileMySiteRedirectControl"
    />

The ID matches the ControlID set on the delegate control in userdisp.aspx:

<SharePoint:DelegateControl runat="server" id="DelctlProfileRedirection" ControlId="ProfileRedirection" Scope="Farm" />

Because the delegate has Scope=”Farm”, our feature needs to be Farm-scoped as well.

Not as simple as Ian’s fix, but once it’s built you can reuse it anywhere with all the advantages of a solutionized customization.

Full solution on CodePlex:

  • Code
  • WSP

Update 12/23/2008: New version: User Profile MySite Redirect 0.2

Update 3/27/2008: New version: User Profile MySite Redirect 0.3

Posted in Features, Object Model, SharePoint. Tags: Delegate Control, MySite, User Profile. 13 Comments »
Blog at WordPress.com.
  • RSS Creative Commons License
  • Recent Posts

    • Find Me On Los Techies
    • posh-git Release v0.3
    • RenderAction with ASP.NET MVC 3 Sessionless Controllers
    • Code Review with Git Patches and Outlook via PowerShell
  • Top Posts

    • PowerShell Dispose-All
    • Is SPList.ParentWeb a Leak?
    • LINQ Tip: Enumerable.OfType
    • Generic Method Invocation with Expression Trees
Privacy & Cookies: This site uses cookies. By continuing to use this website, you agree to their use.
To find out more, including how to control cookies, see here: Cookie Policy
  • Follow Following
    • Solutionizing .NET
    • Already have a WordPress.com account? Log in now.
    • Solutionizing .NET
    • Customize
    • Follow Following
    • Sign up
    • Log in
    • Report this content
    • View site in Reader
    • Manage subscriptions
    • Collapse this bar