Tuesday, August 22, 2006

Community Server Customization - Expanded Member Search Part 1

You can search several user parameters in Community Server in the default implementation of the UserSearch control, but if you have added some custom attributes or fields for member profiles, then you'll need to customize the search. In this case, I am not just talking about customizing the UI to support the params, but the search functionality itself.

The default search functionality is carried out in the UserSearch control, which is displayed on the ForumMembersView control from the Discussions namespace (Note: the UserSearch control shares some functional similarity to the CSSearch (SearchBarrel) implementation, but is distinct).  When you click on the Search button the page posts to itself, turning your query into a set of query string parameters. The existing parameters are as follows:

  • 'Search=1' = Perform Search
  • t = Search text
  • st = search type to perform (for admins only) [search by username or by email; provides values of all/username/email]
  • 'su={0}' = search by username (boolean 1 or 0)
  • 'se={0}' = search by email (boolean 1 or 0)
  • 's={0}' = include accounts with active or inactive status.
  • r = role to limit search
  • jc = join data comparer (gt/lt, etc)
  • jd = join date
  • pc = post date comparer
  • pd = post date
  • sb = sort column
  • so = sort by order (ASC/DESC)

Specifically, the ForumMembersView control populates it's user list during data binding by calling GetUsersAndBindControl on the UserSearch control referenced by the view.  Within the UserSearch control, searches are turned into query strings which in turn are turned into a UserQuery object which is eventually passed to the static Users.GetUsers function to populate the list of users found by the query.

In order to tweak this functionality we'll need to customize the SearchButton_Click event handler and GetUsersAndBindControl functions on the UserSearch control. These methods aren't available to be overridden, so we'll need to copy them into our new class that extends the provided class, and we'll change the skin/view to include our control instead of the CS provided control. Unfortunately, we can't allow the original class to receive the button click event because it redirects the response, so we'll need to override and copy the contents of AttachChildControls (where the event is wired up to the search button) as well. This is a common problem in implementing sub-classes of CS controls that could be solved by setting the event handlers as protected virtual members.

In any case, once we have our custom UserSearch control (not yet customized) we need to add field selectors to the UI of the Skin-UserSearch.ascx skin, and update the View-ForumMembers.ascx skin to reference our UserSearch control instead of CS'.

Having added the search selector fields, we need to update the SearchButton_Click event handler to add our new fields to the query string. To do this, choose a moderately descriptive shorthand for your item that isn't already in the list above; ie. 'ec' for an "Eye Color" attribute. Likewise, you'll need to modify the GetUsersAndBindControl method to recognize your new attribute in the query string, and add it to the UserQuery object. You will need to subclass UserQuery and add your custom properties directly to the class. 

Your query-string writing code in SearchButton_Click might look like this:

if(this.eyeColorSelector != null && this.eyeColorSelector.SelectedIndex != 0)
{
    url.AppendFormat("&ec={0}", HttpUtility.UrlEncode(this.eyeColorSelector.SelectedValue));
}

And, your retrieval code in GetUsersAndBindControl might look like this:

string eyeColor = context.QueryString["ec"];

if(!Globals.IsNullorEmpty(eyeColor))
{
    query.EyeColor = eyeColor;
}

Next time let's look at the details of updating the data provider to use the new query value, and a more flexible way to handle multiple custom attributes without adding every one to the UserQuery.

Submit this story to DotNetKicks

No comments: