Tuesday, October 28, 2008

Code Smart & Fast: Working with custom server controls in v5.5

In NetCommunity v5.5 there is native support for Custom Server Controls. A custom server control for those that aren’t familiar with them simply allows you to modularize bits of functionality so it can be re-used in other applications without having to re-write the same code again.

In NetCommunity v5.5 these custom server controls have been exposed via that API so they can be easily used in any custom part. As a developer this offers two benefits in addition to saving time writing code. Your NetCommunity users are probably familiar with some of these server controls since they are already using them in various parts of NetCommunity. The learning curve will be smaller if you utilize these custom server controls in your custom parts. The second benefit is stability. Since they are part of the core NetCommunity product they are put through the QA process. This means there is less of a chance that an upgrade will break a custom part. Being able to quickly and easily add canned functionality is the real benefit though.

So what are some specific examples of the custom server controls that are available in v5.5? Well, here is a nice list, courtesy of Labs.
  • AddressUI - Offers the form for entering an address, taking into account the selected country and morphing itself appropriately such as changing a field caption from City to Suburb.
  • CFAPicker - Offers a modal UI for selecting a Campaign, Fund, or Appeal from the back office, making the appropriate web service calls to populate a search form, and return the selected item.
  • EmailEditor - Offers the HTML editor in email edit mode, allowing you to specify a field provider for populating the merge fields drop down. Choices include Profile fields, Donation fields, User Registration fields or none. You can also provide a set of custom merge fields that your custom transaction part may provide the data for at runtime. Very useful for designing email acknowledgments for custom transaction forms.
  • HtmlEditor - Offers the HTML Editor including the appropriate dialogs for link picking, and image selection. Handles the processing of the content for safe storage, including the translation of all links from actual to relative.
  • HtmlDisplay - Use this control whenever you want to display HTML that was edited with the HTMLEditor control. It handles the translation of links from relative back to fully qualified, among other things.
  • ImageSelectButton - Renders an ASP Button control that summons the Image select modal dialog. This is the same dialog used by the platform and honors security of the current user to offer the ability upload new images if allowed as well as controlling access to only those images the user has access to.
  • PageLink - This control allows the user to select a link. It shows the link currently selected and offers the standard modal dialog for selecting a link either from the site, to a document, or a manually entered URL.
  • PartEditButton - Renders an ASP Button that summons the modal dialog for editing any part instance.
  • PartSelectButton - Renders the UI for selecting another part, showing the part name currently selected. Can be set to only allow selection of a certain part type.
  • QueryPicker - Renders the UI for selecting a back office Query, showing the one currently selected. Offers the same modal dialog for searching and selecting a Query that is available in the system. Options include limiting the type of Query that can be selected and whether to look at The Raiser's Edge/eCRM or The Education Edge (if applicable).
  • TimeZonePicker - Renders a dynamic drop down that is populated with all of the available world time zones.
Over the next few posts I’m planning on getting into some specifics about how to uses these new custom server controls. I'll try to include some code samples where applicable and possibly even some working projects you can download.

For this post I’m going to touch on the HTMLEditor & Display because it’s probably one of the controls that most people will want to implement. The basic concept will apply to all of the server controls so if I don't get to one of the ones you'd like to play with you should be able to get the hang of it.

Before I get started, I wanted to thank Michael Andrews at Blackbaud for helping me out with this post. Blackbaud has made leaps and bounds in the last year building up the developer's network around NetCommunity. For those of you that have been working with NetCommunity for a while you'll remember the days when the SDK was a 5 page Word Doc. That was less than 2 years ago. As a developer it's nice to have solid resources and an energetic developer community. It's makes working much easier and a lot more fun.

OK, enough with the sentimental stuff.

So start up Visual Studio and setup a project. If you have no clue how to do that you can check out some of the previously mentioned developer resources here.

HTMLControlEditor.ascx (Design View)
<%@ Control Language="vb" AutoEventWireup="false" CodeBehind="HTMLControlEditor.ascx.vb" Inherits="HTMLControl.HTMLControlEditor" %>
<%@ Register TagPrefix="bbnc" Namespace="BBNCExtensions.ServerControls" Assembly="BBNCExtensions" %>

Here you are basically registering the ServerControls and then adding the HTMLEditor custom control to your page. There are some configuration options for the HTMLEditor but I'll handle that in the code behind.

HTMLControlEditor.ascx (Code Behind)
Imports BBNCExtensions
Imports BBNCExtensions.Interfaces.Parts

Partial Public Class HTMLControlEditor
Inherits BBNCExtensions.Parts.CustomPartEditorBase

Public Overrides Function OnSaveContent(Optional ByVal bDialogIsClosing As Boolean = True) As Boolean
Dim oProperties As New Properties
With oProperties
.html = HTMLEditor1.StorageHTML
End With
Return True
End Function
Public Overrides Sub OnLoadContent()
Dim oProperties As Properties
If Not Page.IsPostBack Then
oProperties = CType(Me.Content.GetContent(GetType(Properties)), Properties)
If Not oProperties Is Nothing Then
With oProperties
HTMLEditor1.StorageHTML = .html
HTMLEditor1.FeaturesMode = 1
End With
End If
End If
End Sub
End Class

Properties.vb (Custom part properties class)
Public Class Properties
Public html As String
End Class

So here we are really doing two things. The OnSaveContent() is used to take the HTML that is in HTMLEditor1 and save it to oProperties.html which is just a String. Then it saves all the oProperties for this custom part to be loaded later by the display.

In OnLoadContent() we are simply retrieving the previously saved values for this part and popping HTMLEditor1.StorageHTML. I'm also defining other properties for HTMLEditor1 here, specifically FeaturesMode = 1. This is a canned set of buttons that are available on the editor. Here is how those break out.
  • 1 = basic formatting and styling options
  • 2 = more advanced options like links and photos.
  • 3 = everything available.
Best option is to just play with the features you need for how you are using the HTMLEditor.

One thing to be cautious about though is that if you are planning on using the HTMLEditor on a custom part where non-admin will have access do NOT used FeaturesMode = 2. This will expose them to your NetCommunity images and all your content pages if they try to insert an image or a link. I'd like to see another option exposed in a later release that lets us control that with the API. Might be a good IdeaBank post :D

HTMLControlDisplay.ascx (Design View)

<%@ Control Language="vb" AutoEventWireup="false" CodeBehind="HTMLControlDisplay.ascx.vb" Inherits="HTMLControl.HTMLControlDisplay" %>
<%@ Register TagPrefix="bbnc" Namespace="BBNCExtensions.ServerControls" Assembly="BBNCExtensions" %>

Same deal here with the editor but the HTMLDisplay is just used to display the contents saved in the HTMLEditor control.

HTMLControlDisplay.ascx (Code Behind)
Imports BBNCExtensions

Partial Public Class HTMLControlDisplay
Inherits BBNCExtensions.Parts.CustomPartDisplayBase

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
End Sub

Private Sub getProperties()
Dim oProperties As Properties 'class contating the availible properties
oProperties = CType(Me.Content.GetContent(GetType(Properties)), Properties) 'this is a BBNC method
If Not oProperties Is Nothing Then
With oProperties
HtmlDisplay1.StorageHTML = oProperties.html
End With
End If
End Sub
End Class
Here we are just retrieving the stuff that was saved in the Editor and displaying it using HTMLDisplay1.storageHTML. Nothing too fancy.

So that's pretty much it. It's really straight forward and again you can apply this to any of the other controls. If there is a specific control you want me to do a post on just drop me a line. Oh and for those of you that are too lazy to copy and paste this into your project, you can download the project here. :D

Don't forget to follow me on Twitter and to join the FaceBook group.

Monday, October 13, 2008

sorry for the silence...

I know I have been neglecting my duties when it comes to timely blog posts. It's a busy time of year for us and I've been wrapping up a few major projects.

Tomorrow we are slated to go live with our latest customization to NetCommunity, an application that handles our national membership. This has been in the works for several months. It's probably been one of our more challenging customizations but it's been fun at the same time.

I've also finished up my entry for the Blackbaud Developer's Contest. I'm not giving away any info on that one though. The winners will be announced at the Conference in Charleston. I'll do a post on the winner after that.

Hopefully I'll have some time in the near future to do a post with some substance. In the mean time don't forget to follow me on Twitter and join the Facebook group.