Wednesday, 22 December 2010

Happy Christmas!

Just a quick one to say have a great Christmas and New Year.

Wednesday, 24 November 2010

Blackbaud Netcommunity store / shop

I know that some people have the Blackbaud Netcommunity e-store / shop module installed that Blackbaud created themselves. We asked about this a while ago, and were told it's soon going to be a free part of Netcommunity and no longer charged for.

That was nearly a year ago, with no shop in sight as yet.

My next tutorial, hopefully in the next few weeks, will go through how to create your own online shop by using the Netcommunity API.

I've created a shop module of my own that allows you to list items, take payment, and manage stock levels. It also sends all the details through to Raiser's Edge to be processed in the Netcommunity plugin.

Making your own shop can be as complicated as you want it to be - for the purposes of the tutorial I will focus on creating a simple online shopping basket, with a checkout that takes payment and sends the transaction through to RE. The best thing is, the Netcommunity API does all the tricky bits for you in terms of card processing and transaction processing - the rest of the shop's functionality is entirely up to you to create using ASP.NET.

Blackbaud Labs
has an example of how to create a custom donation form that can easily be adapted to function as a checkout for a shop. If you take a look at that example it should give you plenty of ideas - it is in VB, however.

Thursday, 18 November 2010

Most wanted custom parts

If you could create a custom part that could do anything, what would it be? What is your most wanted feature that BBNC doesn't have?

Tuesday, 16 November 2010

Blackbaud Netcommunity says no to IE9

Irritatingly, the Netcommunity built-in text editor doesn't appear to get on with Internet Explorer 9.

More specifically, every single time you click on anything within the text editor box it throws a Javascript error. Disabling Javascript is no good, as everything is so AJAX-ified it won't even let you save changes without JS.

This appears to be an issue with the text editor (Tiny MCE) rather than Netcommunity itself, but as a customer, that's irrelevant.

Please fix this Blackbaud. IE9 will be out of Beta before you know it.

Update

The only reason I'm commenting on this is because installing the IE9 beta automatically removes all previous version of Internet Explorer - therefore it's the only IE I have.

Blackbaud's CTO Shaun Sullivan commented on Twitter that he will look into it - thanks very much.

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!

Wednesday, 3 November 2010

Role Redirect

Recently I needed to redirect all users with certain roles as soon as they landed on a specific page - in other words, if a user in X role landed on this page, they would be redirected immedately; everyone else (from all other roles) would see the page normally.

The targeted content part built-in to Netcommunity allows you to target roles specifically with different content, but it doesn't allow you to perform redirects. So I built a custom part to do the job instead. In this post I'll explain what it does - in the next post, I will upload the code so you can see it all.

Role Redirect

The first problem was that Netcommunity doesn't appear to expose the list of roles via the API. It allows you to check whether a user is in a particular role (API.Users.CurrentUser.IsInRole), but that's only useful if you already know the name of the role.

To get around this, my custom part hooks straight into the BBNC database - the Roles table is very simple. When you edit the part, it fetches the list of Roles from the database - you can then select one (or more ) roles that you want to redirect when they land on a page with the part on it.

You then choose the page you want to redirect them to by using the PageLink server control - I don't think I've posted about server controls before, so I'll explain it in more detail in the next post. They are built-in bits of functionality that Blackbaud kindly provide as part of the API - there's more information on them here. They allow you to use some of the built-in Netcommunity parts, like the query picker, HTML editor, link picker, and more.

Once you've picked your page and picked the roles you want to redirect - that's it. You save, and put the part on a page.

The next post will be quite long as this is a more complicated custom part than I've posted before - it'll be up this week.

Thursday, 30 September 2010

Netcommunity upgrade: update

I managed to upgrade Netcommunity & Raiser's Edge successfully on our test server. It's not particularly tricky, it just takes a long time. Staying on Windows Server 2003 slightly complicates things, but not much.

I'd definitely recommend doing it in a test environment first, though, as it did take a little while to go through and sort everything out.

I've documented everything I did, which I'll upload soon - right now I am busy preparing for the live upgrade, which is happening next week.

For now, here are some tips for if you're upgrading in a test environment - they should save you a bit of hassle:
  • Back everything up (obv)
  • Upgrade Netcommunity before Raiser's Edge
  • Be prepared to wait for ages whilst BBNC updates
  • If you're using Windows Server 2003, once BBNC is upgraded, run the AppFx config utility (in the Blackbaud program files folder). Select the Add Users function, and add NT AUTHORITY\NETWORK SERVICE as a database administrator user. Otherwise you will get permissions errors.
  • Use the testconfig.aspx page - if everything on there has a green light, there shouldn't be much more to do. http://localhost/netcommunity/testconfig.aspx
  • Check the web.config files in BBNC root folder, AppFx\vroot folder, and the various web service / plugin folders in the Blackbaud program files folder if you're getting errors.
  • When you set up a default site, BBNC requires a URL to a 'valid Netcommunity installation'. Putting in the IP address or hostname of your test server won't work - instead, edit the Windows HOSTS file (Start > Run > "drivers" > etc > hosts) and put the following on a new line:

    127.0.0.1 http://www.bbnctest.com

    Enter http://www.bbnctest.com/netcommunity/ as your valid URL.

Wednesday, 15 September 2010

Netcommunity upgrade: update

I'm currently upgrading Netcommunity & Raiser's Edge on our test server. It's taking absolutely bloody ages.

I imagine it'll take even longer on our live servers... the site will be down for the entire day at least, I reckon.

If you're one of those people who is rushing to upgrade to Blackbaud Netcommunity 6.10 / 6.15 before October 31st then I recommend making sure you have at least a whole day set aside just to let the upgrade run, let alone if anything goes wrong!

Tuesday, 14 September 2010

Netcommunity upgrade deadline

We got an email at the end of August from Blackbaud telling us that we have until October 31st this year to upgrade to Blackbaud Netcommunity 6.10 (at least), or we will no longer be able to take payment via our website.

The first issue with this is the ridiculously small amount of notice we've been given - 2 months is not a generous amount of time, for reasons I'll explain in a second. Blackbaud really need to sort out their communication with customers. No call from our account manager, no heads-up email - just a one-off mailshot at the end of August from some bloke I've never heard of. Not acceptable.

I understand the reasons behind the upgrade - there are some new credit card regulations (PCI DSS) that Blackbaud want to stay on the right side of, and only BBNC 6.10 and above handle transactions in a way that is compliant. It's just the way Blackbaud have gone about it that has narked me off, and it's just another annoyance that makes me wonder whether we'd be better off using open-source tools to build our website. One of the main benefits of BBNC is the supposed integration with Raiser's Edge - whilst it is handy, it still requires an element of human intervention to process transactions, and I'm not convinced whether the convenience of partial integration outweighs all the negatives that BBNC brings along.

Whilst I've grown to really like using ASP.NET, having never used it before, the nature of BBNC means that it really is quite a pain in the backside to make the kind of changes to how it works that wouldn't be a problem with an open source CMS like (for example) Joomla. With Joomla, any bugs or annoyances get solved by the community, and quickly - Blackbaud have shown themselves to not be particularly speedy when it comes to implementing even the most basic of features that have been requested by the community.

It would be possible to import transactions from Joomla in a partially-automated fashion, in much the same way BBNC works - without the extensive costs of BBNC and the hassle of development.

BBNC has lots of great features, but it's lacking in so many of the most simple areas that when things like this happen I start to wonder whether it's worth the hassle for a minimal amount of extra convenience on the database side.

Upgrade

At the moment however, I can't think too much about the above, as the impending deadline
means that I just have to get on with upgrading Netcommunity and Raiser's Edge so that we can continue to take online payments. We're currently running BBNC 5.6 and RE 7.85 - we need to be running at least BBNC 6.10 and RE 7.91.

This means we need to upgrade our Netcommunity SQL Server from 2005 to 2008 (which may possibly break some of the other web applications we have running on that server), upgrade Netcommunity, and then upgrade Raiser's Edge and roll it out to the workstations.

The scary bit for me is upgrading Netcommunity - a lot of our custom parts were created before I started here, and many of them use parts of the API that they shouldn't. My concern is that upgrading may break some (or all) of these parts, and I'll have to figure out how to fix them.

For example, our entire site navigation is generated using a custom part that hooks in to parts of BBNC that it shouldn't - the Menu part in Netcommunity was found to be unfit for purpose at the time, so being sneaky was the only viable choice. If the custom menu breaks, I'll either have to fix it or convert the site navigation over to Menu 2.0. A lot of hassle with not a lot of time.

Anyone else in this position?

Tuesday, 31 August 2010

Tutorial: Fetching constituent data from Raiser's Edge in Netcommunity

Previous posts have illustrated how to make simple, custom forms that allow you to capture data from your users and then use that data for your own purposes.

Assuming you can identify the user who is filling in your form, however, you can also fetch data on that person from Raiser's Edge and use it in Netcommunity. There's a number of uses for this - the most obvious is that you could pre-fill certain bits of the form (in the same way that the built-in Blackbaud parts often do). This will make life easier for your website visitors, particularly if you've got a lot of forms.

Once you have a form set up (see previous posts for explanations on how to do this), then first of all you need to check if the current user viewing your form is logged in (and therefore identifiable):

if (!API.Users.CurrentUser.IsAnonymous)

Assuming they are not anonymous, you can then use the API to create an object containing any available data held on that user:

BBNCExtensions.API.Transactions.PaymentArgs p = this.API.Transactions.CreatePaymentArgs(true);

The 'true' argument loads the default set of data. To have a peek at what that contains, open up your references in Visual Studio (top right, usually) and double-click on BBNCExtensions and browse to BBNCExtensions.API.Transactions > PaymentArgs.

So now you have an object you can use in your form - for example, if you have a text box called 'box_name', you can pre-fill it with data assuming that the data exists in Raiser's Edge:

if (p.FirstName!=null) box_name.Text = p.FirstName;

Or, if you have a text box called 'box_address':

box_address.Text = (p.DonorAddress.StreetAddress + System.Environment.NewLine + p.DonorAddress.City);

The same goes for email address, telephone number, and all sorts of other things. Wahey!

Friday, 27 August 2010

Web security

If you're reading this then hopefully you will have at least a partial interest in keeping websites and web applications as secure as possible.

Google created something a while ago that might be useful, or at least interesting: Google Gruyere

It's a website they have developed to be deliberately insecure, and you are encouraged to try and attack and exploit it as much as you can, in order to learn a bit more about the common tricks that can be used against your website if you haven't secured it properly.

It's good fun. To some extent, a lot of the security holes in Gruyere are unlikely to apply to Blackbaud Netcommunity (or ASP.NET websites in general), as Microsoft have done a pretty decent job at covering your backside if you forget something (unlike PHP), but it's definitely worth looking at for educational purposes. Especially if you have third party code running on your server.

See how many holes you can find.

Speaking of PHP, does anyone use it on a day-to-day basis? I've been using it a bit recently, and I've really been missing the convenience of Visual Studio and the general nice-ness of C#. PHP feels very clumsy and awkward to me.

Friday, 2 July 2010

Tutorial: Including Javascript in Blackbaud Netcommunity pages

Someone commented on one of the previous blog posts that they wanted to know how to include external Javascript files into a Netcommunity page properly, so I thought I'd write a post about it.

Depending on the Javascript you want to include, it can be quite easy - just put some script tags in the HTML of a Formatted Text part. For example:

<*script type="text/javascript">
function doStuff() {
alert("Do some stuff");
}

<*/script>

Don't include the asterisks. Or, if you want to load an external JS file:

<*script type="text/javascript" src="javascript_file.js"><*/script>

Bear in mind that, depending on where you place it, your Javascript is likely to be loaded before the page (and the DOM) has finished loading, so you won't be able to access elements with Javascript that are after the place where you have included the Javascript. In other words, something like this probably wouldn't work (ignore the asterisks):

<*script type="text/javascript">
// this will probably throw an error
var get_paragraph = document.getElementById("my_paragraph");
<*/script>
<*p id="my_paragraph">Hello<*/p>


The above probably won't work, because the Javascript is executing immediately and attempting to access an element of the page that may not have been loaded into the DOM yet. I say maybe, because... just try it, and see if it works.

Assuming you have some Javascript that needs to be loaded in the <*head> of the page - that's a problem, because Netcommunity gives you no access to that. Luckily, you can do it with a custom part.

Adding Javascript (or anything else) to the page HEAD of a Netcommunity page

In order to be able to do this, you'll need to be able to create and publish a custom part to Netcommunity. If you can't do that, then look at some of the earlier blog posts.

First you need a skeleton custom part put together in Visual Studio / Visual Web Developer (i.e. An Editor ascx and Display ascx file, with corresponding code-behinds, with links to BBNCExtensions).

Once you've got that, then add an ASP.NET placeholder to the Display ASCX file. Stick whatever you want to be included in the page head inside that - Javascript files, CSS, or whatever else you might want. Give the placeholder an ID - you'll need it in a second.

With that done, open up the code-behind for the Display part, and enter something resembling this:

// assuming the ID of the placeholder is 'my_place'
this.Page.Header.Controls.Add(this.my_place);

If you don't want it to happen when the page is in design mode, or if you want something different to be included, just check for design mode as per previous posts:

if (this.Content.InDesignMode) { }

Give it a try, it'd be good to know how you get on!

Friday, 11 June 2010

Auto-publish custom parts to Blackbaud Netcommunity

I always found it to be a bit of a pain to publish custom parts to Netcommunity - build the project, publish it, move the .dll file to the \bin folder and the .ascx files to the Custom folder etc. So I've made a little tool that will hopefully make it a bit easier.

It's a C# console application - the first time you run it, it asks for the paths to your Netcommunity \bin and \custom folders, and the path to your Visual Studio projects folder. Once you've done that once, it will store them for next time you run it.

It then asks you for the name of your Project - it searches for that project, and if it finds it the files (including .dll) are copied to the right places in the Netcommunity folder.

The best thing is that you can set up Visual Studio to run the program automatically every time you build a project - the program recognises that it is being called from Visual Studio, and does everything without asking for confirmation, automating the whole process.

As long as you run the file once by hand to set up the paths it needs, from then on you can get Visual Studio to run it automatically - here's how:

Adding Build Events to Visual Studio

In Visual Studio, go to 'Project' then '[Project Name] Properties'.
Click the Build Events tab.
In the 'Post Build Events' box, type the following:

cmd
cd C:\BBNC_Pub
BBNC_Copy_Data $(ProjectName)

The one bit you'll need to change is "C:\BBNC_Pub" - put in whatever directory you've stored the program in.

The above simply opens a command line, changes to the folder where the copying program lives, and then runs it with the name of your project as an argument. This causes the program to automatically find and copy the project files to the Netcommunity folder.

Do that for every project you create, and you're good.

Disclaimer - the program was quickly hacked out, probably has lots of bugs, etc etc. If it wrecks your computer, then that's too bad.

You can download it here - it's an .exe file. Save it to somewhere like C:\BBNC_Pub\, then run it and enter in the relevant paths. Once you've done that, you can either open the program manually and search for a Project, or get Visual Studio to run it automatically for you.

Let me know if you try it!

Friday, 4 June 2010

Setting up a Blackbaud Netcommunity / Raiser's Edge test environment

In steps, how we went about setting up a test environment for Blackbaud Netcommunity & Raiser's Edge, that duplicated (as close as possible) our live setup.
  • Get the hardware to run it on
Our live setup is three servers - a Netcommunity application server (holding the application & web services), a Netcommunity database server, and a Raiser's Edge server. We're still running Netcommunity 5.6, so all three of those servers are running Windows Server 2003.
For the test environment, we decided to go down the route of using Virtual Machines - 3 VMs that are running Windows Server 2003, running on the host server which is a powerful Windows Server 2008 R2 server. The VM software we are using (Hyper-V, which is built into Server 2008) is great, you can easily take snapshots of the state of the servers and restore to them later, and make all sorts of changes.
  • Install the operating systems onto the hardware
As above, we are currently still on BBNC 5.6, so we're using Windows Server 2003. We're going to use this test environment to upgrade to the latest version soon, and see how it goes - that's the great thing about virtualisation. If it doesn't work out, we just restore the old VMs.
  • Install Raiser's Edge onto RE server
Once all the server OSs have been patched up fully, install Raiser's Edge onto the RE VM. This was relatively painless, but took a little while. We did have problems with the installation detecting our existing Raiser's Edge installation (the live one) and confusing itself (the VMs are on the same network as our live setup) - we then had to uninstall it and run the process again. Blackbaud support were helpful with that.
  • Install Raiser's Edge client onto Netcommunity application server
This needs to be present in order for the web services to work properly - pretty straightforward to install, we didn't really have any problems.
  • Install Netcommunity database onto Netcommunity database server
This was also pretty straightforward - installing the BBNC DB is simply a case of running the BBNC installation file and choosing 'custom' to just install the database.
We did have to do some messing around with the database later on, once the Netcommunity application was installed properly - the recovery mode of the database needs to be set to 'simple' and a backup needs to be performed. Other minor configuration tweaks might be needed, but the best thing to do is either check Blackbaud's knowledge base or give them a ring.
  • Install the rest of Netcommunity onto the application server
Next, we installed the rest of Netcommunity onto the application server - the application itself, the web services, etc. Once that was done, I tried to open the Netcommunity admin page. It failed straight away. Eek.
In order to get it to work, we needed to grant permissions to various files & folders to an account named NETWORK SERVICE. We also had to change the recovery model of the database (as above), and we had a few problems with the Netcommunity installation package not working properly - uninstalling Netcommunity, removing all the temporary files it leaves behind, and trying again seemed to sort that one out.
Once the admin page came up successfully, I loaded the testconfig.aspx page (your-url.net/netcommunity/testconfig.aspx) to see if anything else was awry. During the application installation process it asks you for Blackbaud Services login details - we didn't need to use this, so we just put gibberish in instead. I understand that installing a more recent version of Netcommunity requires you to enter Blackbaud Payment Service info - I guess you may have to put the live info into there for it to work. We also had a few problems with the web.config file that needed to be adjusted, but again, the knowledge base was very helpful with sorting it out.
  • Restore the live databases to the servers
The next, and optional step is to backup the live databases for both Raiser's Edge and Netcommunity, and restore them to the databases in the test environment. That way you will have a relatively recent version of your live setup, duplicated onto your test servers.
Bear in mind that things like customisations are not stored in the database and will therefore need to be copied across manually.
Our next step is to trial out the latest version of Netcommunity, and see how we get on - we have a lot of custom parts that could potentially get broken. Hopefully not.

Tuesday, 25 May 2010

Test environment: update

We have the test server, at last - now in the process of putting software onto it (including Raiser's Edge and Netcommunity).

We've got 3 virtual machines running on the server, a Netcommunity VM, a Netcommunity database VM, and a Raiser's Edge VM (this mirrors our live website environment). Pretty impressed with the server so far - it's a quad core with 10gb of RAM and it seems to be pretty damn fast.

Should come in useful.

Thursday, 15 April 2010

Netcommunity test environment

We haven't got a Netcommunity test environment - I do all development on my workstation PC, and then transfer all the files over to the live server to see if they work. Which is pretty stupid, as I have no idea whether anything works until I publish it to the live server - coding blind, in effect.

Most of the time it's ok, mainly because I'm not doing anything particularly complicated, but occasionally I really get it wrong and knock out the whole site - like the other day, when I managed to trigger a stack overflow and we had to restart the web server. Oops.

Thankfully, we are going to be getting a test environment in the near future, which will mean I'll be able to do a lot more without having to worry about wrecking anything. I can't believe we didn't have one anyway.

Does anyone have a test environment themselves?

I'm going to document how I get on with setting ours up and so on, on the offchance that anyone is interested / is trying to do it themselves.

Bonza.

Tuesday, 30 March 2010

Blackbus.org hacked!

I logged on this morning to check Blackbus.org (a useful site for users of Raiser's Edge / Netcommunity / other Blackbaud products), and discovered that it seems to have been hacked.

I'm hoping that everyone else who logs on spots the problem - our firewall / anti-virus intercepted the nastiness before it got to us.

An iframe is being injected into every page on the site, after the closing HTML tag, linking to "ramualdo.com/lib/index.php" (don't go there).

What does it do? I have no idea, as it's being blocked here at work. I'm going to have a peek when I get home, but I would advise anyone reading this not to go to Blackbus, especially if they are using IE6/7/8 or a version of Chrome or Firefox that isn't up to date.

There's lots of nasty IE bugs around at the moment that it might be trying to exploit, and countless other exploits with third party software like Adobe Reader / Flash. So I'd stay away for a little while unless you're confident you're not going to get infected.

Hopefully Blackbus will sort it out soon.

Update: It's fixed!

Tuesday, 23 March 2010

Javascript setTimeout function parameters

Not really related to Netcommunity, but this might be useful to anyone struggling with Javascript timers, and more specifically calling a function with arguments from a timer.

Calling a function from a Javascript timer usually goes something like this:

timer = setTimeout('myfunction()',10);

Call myfunction() after 10 milliseconds. But what if you want to include some arguments in the function call? Surely this would work - x is a string:

timer = setTimeout('myfunction(x)',10);

For some irritating reason it doesn't. So I did some poking around to try and find a solution, and there are some, including using closures - but then I found this solution that seems to work nicely:

timer = setTimeout('myfunction("' + x + '"),10);

My particular use of this is as follows:

box = function(id,x,y) {
this.id = id;
this.x = x;
this.y = y;
this.timer = function() {
timer = setTimeout('animate("'+this.id+'")',10);
}
this.prepare = function() {
moveto(this.id, this.x, this.y);
}
}


boxone = new box("myid",50,50);
boxone.prepare();
boxone.timer();

I created a constructor function for a box; I then created a new box and then called the prepare function to put the box somewhere and the timer function to fire off a timer that starts an animation. It was that timer, contained within the constructor, that I was having trouble with - I couldn't pass arguments through to the next function.

I think that for some reason Javascript can't evaluate function arguments that are being called from a setTimeout in that way - so therefore you have to evaluate them before passing them into the function. That is why breaking up the string and sticking it all together with + works - it's asking Javascript to work out what your argument actually is before calling the function.

Does that make any sense? Probably not. I felt like writing it down anyway.

Monday, 1 March 2010

Netcommunity to Raiser's Edge

I've been half-heartedly attempting to send stuff from Netcommunity to Raiser's Edge today. There's an example on Blackbaud Labs that shows you how to update someone's Raiser's Edge record from Netcommunity. That particular example is a form that collects a couple of details from a user, and saves them as a Custom Transaction. The Custom Transaction is then processed by a Raiser's Edge plugin written especially for the task.

That all sounds a bit tricky and complicated to me, and I assumed (foolishly) that there would be some kind of in-built method in Netcommunity that would allow you to do stuff like that without having to go to all the hassle of writing a plugin. If there is, I can't get it to work though.

I've been trying to make use of this:

BBNCExtensions.API.Transactions.Profiles.ProfileUpdateArgs p = new BBNCExtensions.API.Transactions.Profiles.ProfileUpdateArgs();

It looks pretty good - if you create an object of the type above, it has some methods and properties that look perfect for what I want to do, for example:

// get the id of a custom attribute in raiser's edge
int att_id = p.Data.Attributes.GetAttributeTypeIdFromName("my attribute");

// set the value of the attribute to something
p.Data.Attributes.SetValue(att_id, "my value");

// fire it off to raiser's edge... please?
this.API.Transactions.RecordProfileUpdate(p)

Or not, as it doesn't work. Hmmm. Any ideas?

I read somewhere on Labs that at the moment Blackbaud only support Donations in this manner, and not Profile Updates or anything like that, but if the methods are there then why not? Or am I just being rubbish and not understanding how this works?

Thursday, 18 February 2010

Tutorial: Netcommunity design mode, and Javascript

Not sure if anyone else has encountered this, but occasionally when I am editing a page and include a custom part, I'm unable to rearrange other parts on that page or add new ones.

Normally, you can move parts up or down, insert existing parts, or create new parts when you're editing a Netcommunity page. However, quite frequently I'm unable to do this after including a custom part.

I'm not quite sure why, I have a suspicion it's because a lot of my custom parts are forms that have validators in them (to check form fields have been filled in), and I think the validators might somehow be interfering with how Netcommunity's design mode works (lots of AJAX jiggery pokery, from the look of it). That's just a guess though.

Thankfully there's a simple way to get around it - instruct your custom part to check if it's being viewed in Design Mode, and if it is, don't bother displaying your part properly. Pop this into your page_load event in the Display control of your custom part:

if (this.Content.InDesignMode)

If that returns true, you can display a simple message or a dummy form, as it's not necessary to do all the legwork as the user is viewing the page from the Netcommunity admin. Remember you don't need to explicitly check if a bool returns as true - merely including a method that returns a bool in the conditional part of an if statement (the brackets) is enough. No need for "if (this.Content.InDesignMode == true)".

Bear in mind though, that the above isn't always the case - methods that return an int, for example, will cause Visual Studio to squeak at you if you try to evaluate them as a bool.

That's why Javascript is so lovely - because it does its best to evaluate everything as a bool:

javascript:if(document){ alert('true'); }else{ alert('false'); }

If the document object is present, the first block is executed. If it isn't the second block is executed. That's why Javascript is so well suited to checking if certain features are enabled in any particular browser - rather than the old practice of browser sniffing.

Because Javascript is weakly typed, you can do the same with an int:

javascript:if(1){alert('true');}else{alert('this will not be alerted');}
javascript:if(0){alert('this will not be alerted');}else{alert('false');}

I like Javascript.

Does anyone else like Javascript?

Thursday, 11 February 2010

Tutorial: Custom RSS reader for Netcommunity

Hello, it's been a while - sorry about that. Will try and post more regularly.

One thing I wanted to do recently was display some RSS on our intranet (powered by Netcommunity) - however, as you might know, the built-in RSS reader is a bit rubbish and quite inflexible in terms of displaying content. All I wanted was very simple - fetch the weather from the BBC, and display the forecast for the next 3 days in brief text format. Netcommunity's RSS reader is way too overcomplicated to accomplish something like that, so I built a very simple custom part to do the job instead.

I'll post up the full source code later on, but for now here's some snippets.

Firstly, I created a new Xml document object:

System.Xml.XmlDocument doc = new System.Xml.XmlDocument();

Load in an RSS feed from wherever you choose:

doc.Load(http://www.myrss.com/rss.xml);

This bit is quite specific to what I wanted to do - fetch all of the 'item' tags:

XmlNodeList getitems = doc.GetElementsByTagName("item");

Loop over all the item tags and display them:

for (typical loop stuff) {
displaylabel.Text = displaylabel.Text + getitems.Item(i).FirstChild.InnerText;
}


Obviously depending on the XML you're dealing with, you'd need to parse it in different ways, but for this particular example (BBC weather 3-day forecast), the above is enough to print out 3 days of weather. You can then go on to customise how the text looks, by splitting the XML strings into chunks and dealing with them that way.

You can do this in any Netcommunity custom part - so for example, if you have a forum, you could create a custom part that grabs an RSS from the forum (latest posts, for example), and displays it on your homepage. Nifty.

Will post full sourcecode soon, but it will be very specific to the BBC Weather 3-day forecast - using the above, why not try it yourself? Let me know if you manage to get something working, or if you know of a better / more efficient way of fetching an RSS feed.