Community Server SDK Overview & Customization

One of the first things I hear from people working with CommunityServer for the first time is "where are all the codebehind files?" As an educational process, I thought I would trace some of the Community Server 2007 functionality through a page lifecycle and highlight some of the systems involved. This overview is written for the CS 2007 SDK, or version CS2007.1_3.1.20917.1142.sdk

We'll start with a simple request to page login.aspx in the home directory.

Here is an overview of how Chameleon, the CS2007 theme engine and the URLRewrite module handles the request and how the URL re-writing works.

  1. Request for login.aspx reaches server
  2. ASP.NET gets passed the request.
  3. CSHttpModule intercepts the request as it is processed.
  4. URL path is rewritten (look at the SiteUrls.config file for details of this. This is where the /themes/[currenttheme] path is injected).
  5. Appropriate Theme page is redirected to
  6. ASP.NET resumes processing the request.

So one of the things incorporated in this model is a great deal of flexibility control over how a particular theme that is coded is laid out and works.

Next, let's continue digging into the request.

At step 5, the theme page is redirected to. Here we end up at (for example), at /themes/default/common/login.aspx. Login.aspx has the master page of master.Master, which contains an OnInit() function with code setting up the left or right columns if present in the theme definition. Note the following 2 lines at the top of most of the .aspx / .ascx files:

<%@ Import Namespace="CommunityServer.Components" %>

<%@ Import Namespace="CommunityServer.Blogs.Components" %>

These settings import the controls compiled in the CommunityServerComponents project and the CommunityServerBlogs project.

At this point it's useful to point out a feature in the Chameleon engine – each Chameleon control has contextual, implicit data-binding. Chameleon control context begins at the page level, using the URL of the current page, and recognizes query string properties such as GroupID, SectionID, App, userID, PostName, etc. So a PostListing Chameleon control has wrapped within it it's own databinding. The same with a UserListing or UserData Chameleon control. Because of this implicit databinding, the Community Server Chameleon controls know from their context what to load in them.

The advantage of this is a great deal of re-use of these controls throughout the whole CommunityServer product. The disadvantage is that individual modifications have global impact, and also they are a little more complex.

In customizing CommunityServer, this design tradeoff should be weighed. If there are core modifications to a blog post that are necessary for re-use throughout the whole product, the appropriate place for modification is in the Chameleon controls. If they are unique to one area, but should display differently in another area, perhaps inheritance and extension principles can allow for this. Controls that are being developed that do not have a great deal of changing context surrounding them do not need the benefits that the Chameleon engine provides.

Continuing on the journey through Login.aspx, the master.Master page has content placeholders and a CSUserControl:UserWelcome control. The UserWelcome.ascx control is a file in the same Themes/default/Common directory, and contains several nested CSControl:UserData controls. If you are wondering where the "CSControl" prefix comes from, it is a global tag prefix defined in web.config:

<add tagPrefix="CSControl" namespace="CommunityServer.Controls" assembly="CommunityServer.Controls" />

This shows what namespace and assembly the controls are loaded from. Here it is the assembly compiled in the CommunityServerControls20 project.

The UserData control is in the /User folder – UserData.cs. One element here I will highlight is the method of implicit data-binding in this Chameleon control. The UserData control inherits from the CommunityServer's ObjectDataBase.cs control in /Base folder, which has a BindDefaultContent method in it.

Where the data is populated in the UserData.cs control is that control has a DataSource property in it, which is used in the parent's BindDefaultContent method. Look for this line in the DataSource getter:

CSControlUtility.Instance().GetCurrentCSContext(this.Page).User

From there, you go to the definition of User in CSContext, which loads the User definition from the Users.cs file in CommunityServerComponents20 project.

The Users.cs User class has all data operations encapsulated. The GetUser function passes to the function which looks up User data in the Cache first, then if not present, gets the user from the Data provider in GetUserFromDataProvider. This value for the data provider is injected from web.config, and is from the CommunityServer.ASPNet20MemberRole.dll. There is not source published for this in CS2007, but was in an old SDK download. The User data access is a unique one in this respect. For modifications on this on can inherit from the ASPNet20Membership class, and extend it to use another extension to user profile contained in a separate table, not the built-in aspnet_User tables and built-in ASP.NET Membership provider.

Other examples of items with data binding roll down to the SQLDataProvider20 project and classes.

So for a complete overview, each individual control has its own data source, which uses a data provider, which is injected from the context and configuration. This is a classic provider model, which uses a Dependency Injection IOC (Inversion of Control) container. It is self loading from context, and has built-in caching.

There is a little overview of Chameleon controls and the CS 2007 framework.

 

 

 

 

 del.icio.us  Stumbleupon  Technorati  Digg 

 

What did you think of this article?




Trackbacks
  • No trackbacks exist for this entry.
Comments

Leave a comment

Submitted comments will be subject to moderation before being displayed.

 Enter the above security code (required)

 Name

 Email (will not be published)

 Website

Your comment is 0 characters limited to 3000 characters.