Thursday, 4 November 2010

Tutorial: Role Redirect

This will be a long post. By the end of it you should be able to create a custom part that allows you to redirect members of certain Netcommunity roles automatically when they land on a certain page. Important: remove asterisks before copy & pasting code.

Create a skeleton custom part

Go back to earlier posts if you're not familiar with how to set up a bare-bones custom part - you'll need an Editor web user control and a Display web user control, along with references to BBNCExtensions in the appropriate places.

Add a new code file

Right-click on the project name and add a new C# code file. In this new file, create a new class:

public class rr_data {
public int pid;
public string roles;
}


This class will be saved in the Netcommunity data store, and will hold the page that you want to redirect users to, and the roles that the redirect applies to. A string is not the best format to hold the roles in, but I don't think the Netcommunity API will allow you to save more complex data types.

Design the Editor part

Open up the design part of the Editor control. Add this below the first ASP.NET statement at the top:

<*%@ Register TagPrefix="bbnc" Namespace="BBNCExtensions.ServerControls" Assembly="BBNCExtensions" %>

This allows you to use some of the Netcommunity server controls that are built-in to the API - in this case, we are going to use the PageLink control to hook into the link selecting functionality in BBNC.

Somewhere on the page, add this in:

<*bbnc:pagelink id="_pid" runat="server"> <*/bbnc:pagelink>

This will create a PageLink server control that allows the user to link to a BBNC page, document etc. Very useful. You might get 'unknown' errors but ignore them - this should work on the server.

Next, drag a CheckBoxList from the toolbox onto the page. Give it an ID of 'role_list'. This element will eventually be populated with all the roles that exist in the BBNC database, so the user can tick which ones they want the redirect to apply to.

Editor code

Now it's time for the Editor code-behind. Add a using statement at the top to System.Data.SqlClient.

In the OnLoadContent() method, add the following - you should be able to copy & paste it in:

// Fetch the data (if any):
rr_data get_data = base.Content.GetContent(typeof(rr_data)) as rr_data;
string[] _roles = null;

if (get_data!=null)
// Get the page ID from the BBNC data store
// and use it to pre-select the page in the PageLink control
_pid.PageID = get_data.pid;

// The roles are stored as a string, seperated
// by the ^ character - split up the string.
_roles = get_data.roles.Split('^');

try {

// Create a new SQL connection to the BBNC database
// You will need your own connection string -
// look in the web.config file in the Netcommunity folder
// on your web server for clues
SqlConnection sql = new SqlConnection("CONNECTION STRING HERE");

// Open the connection
sql.Open();

// Select the names of roles from the database
SqlCommand cmd = new SqlCommand("SELECT Name FROM dbo.ClientRoles", sql);

// Read the data in
SqlDataReader data = cmd.ExecuteReader();

// Create a new list item collection for the roles
ListItemCollection item_list = new ListItemCollection();

// Add each role to the collection
while (data.Read()) {
item_list.Add(data.GetValue(0).ToString());
}

// Close the connections
data.Close();
sql.Close();

// Add the roles to the CheckBoxList
for (int i = 0; i <* item_list.Count; i++) {
role_list.Items.Add(item_list[i]);
}


// If there are pre-selected roles in the data store
if (get_data.roles.Length > 1)
{

// Loop through each role and check for matches against
// the loaded data

for (int j = 0; j <* role_list.Items.Count; j++) {
for (int k = 0; k <* _roles.Length; k++ ) {
if (role_list.Items[j].Text == _roles[k])
{

role_list.Items[j].Selected = true;
}
}
}

}

} catch {

// Error checking etc goes here

}

In the OnSaveContent() method, add the following:

// Create new data object for the part
rr_data save_data = new rr_data();

// Save selected page from PageLink control to object
save_data.pid = _pid.PageID

// Loop through the list of available roles
// Stitch selected roles together with the ^ character
string selected_roles = "";

for (int i = 0; i <* role_list.Items.Count; i++)

{
if (role_list.Items[i].Selected)
{

selected_roles += (role_list.Items[i].Text)+"^";
}
}
// Save ^ seperated string to object
save_data.roles = selected_roles;


// Save the object to the data store
base.Content.SaveContent(save_data);
return true;

In the Page_Load() method of the Display part code-behind, add the following:

// Load data from the store
rr_data get_data = base.Content.GetContent(typeof(rr_data)) as rr_data;

if (get_data!=null)
{
// Split roles
string[] _roles = get_data.roles.Split('^');
int pid = get_data.pid;

bool _roles_match = false;

// Check for any role match
for (int i = 0; i <* _roles.Length; i++)
{
if (API.Users.CurrentUser.IsInRole(_roles[i]))
{
_roles_match = true;
}

}

// If match found
if (_roles_match)
{

// Redirect to specified page
string link = API.Navigation.GetPageURL(pid, 0);
Response.Redirect(link);
}

get_data = null;

That's it. Bit of a long post - even if the part is useless to you, hopefully there will be some stuff in there that will be useful to you.

Bear in mind that this is just an example - you should go through it yourself and ensure that all errors are being captured and dealt with properly, especially if you are hooking into the main BBNC database via SQL. It may be worth creating a new SQL user that only has access to the Roles table, for extra security.

If anyone tries any of the above then please post a comment!

1 comments:

  1. This would have been perfect a few weeks ago when I was rebuiling site but had to redesin a section of site to get what this part would allow me to do! Great work :) I will look into this more when I have a bit of free time.

    ReplyDelete