Monday, December 12, 2016

...and I'm back, almost 6 years later.

Back in May, 2016 I returned to the US Naval Academy Alumni Association & Foundation. After taking a few months to get settled I've decided to start up this blog again.

So what's changed?

Well, a lot. For one, Blackbaud is a different company. It's larger for sure and for us I think that's a good thing. It means we're part of a bigger, stronger development community. The resources provided by Blackbaud are a far cry from the "SDK" I started with in 2005 that consisted of a zip file w/ some user controls and a word document. We have more APIs to chose from as well as we move into the BBIS/CRM world.

Since Blackbaud has changed I think this blog will need to as well. For one I have changed the name from "customizing NetCommunity" to custom:baud. It's a bit more modern and isn't BBNC specific. The content here will cover many of their APIs and not be limited to a single product. For those that picked up on it, it's also a throwback to the .net web forms roots where this community started.

We're developers and it's always about the code. Whenever possible, I'll provide working code samples on GitHub for anyone to use, freely. But it's also about more than the code. In the world of non-profits where resources are so important, we all wear many hats. You can expect posts on topics like devOps, architecture, testing, CI/CD, automation and more.

I have a few post ideas in the works and you should see more of those in the coming months as Navy finishes up it's CRM conversion.

For now, I'm happy to be back and looking forward to contributing again to this great community.

Friday, May 6, 2011

customizing NetCommunity, last post from me.

Well this is going to be my last post on customizing NetCommunity. I have taken a new job outside the non-profit space so I won't be working with Blackbaud or NetCommunity after next week.

I hope others have found this blog as useful to read as it's been for me to write. I'm going to continue to keep it online for the foreseeable future so others can continue to use it as a resource.

I know I have enjoyed working with many of you, both in and outside of Blackbaud, over the last 5 years. It's been a rewarding experience and one I'm not going to forget. I hope all of you will keep in touch.

If anyone wants to be a contributor just drop me a line and I'll set you up with access.

Tuesday, December 8, 2009

iPhone Support in Blackbaud Enterprise CRM

Below is a short screen cast from Shaun showing off some of the new iPhone support that'll be in the Q1 release of the Blackbaud Enterprise CRM.

I have to say that this, and the prospect of using BBEC & RE in the Cloud, is a great direction for Blackbaud to be moving in and I think it really outlines just how agile the Infinity platform really is.

Anyway, have a look!

Tuesday, August 4, 2009

Social Networking in NetCommunity

I know it's been a while since my last post. Things have just been very busy all around and I haven't been able to make time to blog.

Today I wanted to showcase one of our latest (and biggest) projects, the new Social Networking app, USNAConnect. We're making use of NetCommunity's User Networking Manager part here but we have customized many aspects of it. I need to give credit where credit is due, this was a massive project in development since December 08 and we have a lots of sharp folks here that have been part of it. Props to Kate, Nick & Larry for all their help.

For those not familiar, the User Networking Manager part is a Social Networking app that leverages your NetCommunity database. It was released in v5.5. This part is a little different from many older NetCommunity parts because it was designed to allow developer's to integrate their custom parts very tightly with it. It's actually pretty hard to tell what is custom and what is out of the box unless you are familiar with the User Networking Manager part. Props to Blackbaud on this one, I really hope this ends up being the design model moving forward for other NetCommunity parts.

Just a quick note about "private" or closed social networks. We're not trying to compete with Facebook. We want to leverage our database in a way Facebook just can't and offer functionality that is unique to our constituents. We're still on Facebook and at some point even envision a layer of integration between our two networks. So don't think we're expecting to grow to 300 million users in 4 years, but that would be nice. :D

So before I try to explain what exactly we're talking about here lets just have a look at the application.

This is the page you see when you first enter USNAConnect right after logging into our website. One of the main requirements for this project was to design a page with the constituent in mind. It needed to be Web 2.0 and user centric.

  • Greeting - If you look at the top we have customized how we address each person based on their chosen preferences. We are a military organization so you can imagine that can add a layer of complexity to the whole bit about greeting. We give people the option to choose if they prefer to be greeted with their military or civilian titles and if they have chosen a nick name we also honor that. That greeting is completely custom to each user that logs in and they can change it at any time.
  • Information Box - At the top we display various messages that are targeted to the logged in user. These can range from information about a chapter event in your area to a link to your class reunion page. We allow you to hide that box for up to 30 days. This saves some real estate on the screen for your gadgets if you have already read all the messages. At any time you can show the box again if you want to. Each messages can be targeted using NetCommunity roles. We also pre-populate a few messages if your profile or other information is out of date and ask that you update it.
  • Gadgets - This custom part is modeled after iGoogle functionality. A gadget is actually it's own little custom part. This page is basically designed to consume both custom and non custom parts and display them to the user. Each of those gadgets can be dragged and dropped where you want them and the order is saved so when you return your gadgets are where you put them. As we make more gadgets available they can be added from the bottom section. If you are not interested in a gadget you can simply remove it. The goal here was really to allow users create their own landing page with the content they care about. Check out the video below to see that in action.
    • Suggested Friends - This gadget uses some back-end SQL to determine other USNAConnect users that you might know. You can choose to "view/add" them or if you wish, "hide" them.
    • Your Membership Info - Displays your current membership information from The Raiser's Edge and it will prompt you to upgrade or renew if you are close to expiring.
    • Top pages - Shows the top pages on our website in the past 30 days.
    • Top New Articles - Displays the top news articles from our site in the last 30 days.
    • Interactive Tools - This is actaully a menu 2.0 part in NetCommunity and we're using some of the new API stuff in v5.5 that lets you pull the XML out and parse it up. Coolest part? It honors NetCommunity roles so it won't show you a link if you aren't in a role that can access it. That saved us a lot of development time. There is an open source example of this on Labs if you want more information. This one just displays some links to a few apps that we really couldn't work into this page.
    • Your Friend Map - Shows a map of all your friends that can be geo-coded in our database. It honor's their privacy settings so if their address is private we don't display their location.
    • Your Events - Displays all of the upcoming events you have registered for with us and the most recent 5 other registrants that have also signed up for that event. Best part? You can subscribe to the feed of registrants with RSS so you can easily monitor the event as other people sign up. This is great for reunions.
    • Volunteer Leadership - This is another menu 2.0 part that shows a lot of the apps specific to our volunteer leadership folks.
    • My Top Pages - Shows a list of the most recent pages that you have visited. This is great for folks that use one feature of our site a lot and if you recently found a page and need to locate it again.
    • Alumni Lookup Lite (Not Shown) - This feature is only open to Alumni. It allows you to do a quick search for any alum in our database by name and class year. This is one of the most popular activities on our site so we wanted to provide an easy way for our alumni to search from their USNAConnect landing page.
    • My Class News (Not Show) - Here is another feature only open to our Alumni. Similar to Top News Articles but it's filtered on only news specific to the class year of the logged in user.

USNAConnect Drag and Drop Demo (Full Video)

One final point about these gadgets. The development time is low because most of the framework is built into USNAConnect the only thing I need to do is write a web service that returns an object with the information to display. This has made development cycles for the gadgets very agile.

If you look across the top of the page above there are a few other tabs. These are all out of the box features in the User Networking Manager part with the exception of the last one, View/Edit My Profile. Another great feature of the User Networking Manager is that you can add tabs. So if there is something that it doesn't have you can build it and then integrate it right into the menu structure.

Messages - This allows you to handle in networking messaging amongst users.

Friends - Displays a list of all of your friends and allows you to search by name for any one else in the system.

Photos - Shows your photo gallery and lets you choose a profile picture from it.

Preferences - Just a few options that each user can change for their account.

Administration - A list of administration options that all site administrators have access to.

View/Edit My Profile - Links off to my profile page where I can make any changes. Something not shown is that if you are viewing someone else's profile, it'll display any mutual friends that you have. That is out of the box NetCommunity functionality, not custom.

It's worth pointing out one final bit about the User Networking Manager part. It's 100% customizable from a style and verbiage perspective. If you don't like the word "friends" you can change it everywhere in the application to whatever you want to call them instead. You'll also notice that "groups" aren't displayed in the examples that I showed you. That's because for the time being we have decided to not include them. It's a very flexible application and I gotta hand it to Blackbaud for going this route again.

USNAConnect is technically still in public beta but we're planning on going live with it in early October.

So that's pretty much it. I'm going to try to get back on a regular posting schedule but I can't make any promises.

As always be sure to check out the Facebook page.

Wednesday, February 18, 2009

Blackbaud releases an iPhone emulator

Today Shaun Sullivan posted an article in Labs discussing his latest project, an iPhone emulator. 
I've been playing with it and it's really pretty cool! You can use it to develop a mobile version of your website right from your desktop. That makes things much easier. 
If you want to check it out have a look here

Saturday, February 7, 2009

Open Source REAPI Project

Earlier this week AJParise made me aware of an Open Source project that he started for the REAPI on CodePlex. There is some pretty slick stuff there for those of us that have purchased The Raiser's Edge API. 
AJParise wrote: In January 2008, I started working extensivley with the REAPI.After a year of headaches and mindnumbing research I've developed some very handy classes for .NET developers using the 3.5 framework looking to integrate with the REAPI. 
This represents a pretty significant mile stone in the growth of Blackbaud's developer's community. There are many open source components on Labs but this is the first that has sprung up outside of Blackbaud. I can only hope that others begin to contrbute to the work that AJParise has started. 

Be sure to check out the project on codeplex when you get a chance and if you can, please contribute. 

Saturday, January 17, 2009

Geo-coding Your Constituents

Everyone likes maps & map mash-ups. There seems to be something very appealing about being able to see things visually compared to textually. Since we launched our Interactive Class Map about 8 months ago it's become one of the longest viewed pages on our website. The average constituent spends almost 4 minutes and 30 seconds doing nothing but panning and zooming around the map looking at their classmates. We have had a simple NetCommunity Directory Part that displayed the same information just in list form for years. It's still widely used but users don't spend anywhere near the amount of time viewing it as they do the Interactive Class Map. 

In this post I'm going to cover what is really the most important part of working with maps on your NetCommunity website, geo-coding. So, what is geo-coding? It's the process of taking an address and finding its latitude and longitude. Once you have done that it becomes much easier to display that location on a map. Just a warning, this is going to be a bit technical. 

I hacked out a quick and dirty webservice that I'll make available at the end of this post for download. It uses the REAPI to get a constituent’s address from RE and then uses Google to find the lat/lng. I'll take you through the code step by step. 

CAUTION: This method is NOT the best approach if you are planning on processing a lot of records. Google imposes a 15K limit on the number of requests per day from a single IP address. They also frown upon making requests too quickly and may block you for that. If you are planning on using this method to process your entire database you really should batch it up in small chunks over the course of a few days. Also be sure your timer makes each request to Google a few seconds apart. The code I'm going to show you does not do that, but it wouldn't be too hard to add. Since you have the source code you should be able to add that functionality.

So let’s get started.

The first step is to create a new Web Service project in Visual Studio 2008. The idea behind this project is that other NetCommunity custom parts could use it. If you are planning to bulk geo-code your constituents you could also use it in something like a Windows Service that runs over a few days to process your whole database.

Now that the webserivce project has been created we want to go ahead and start setting up the two functions we're going to use.

We're going to need to import these references;
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.ComponentModel
Imports Blackbaud.PIA.RE7.BBREAPI
Imports System.Xml
Imports System.Net
Imports System.IO

You'll probably need to add Blackbaud.PIA.RE7.BBREAPI to your project. If you don't have the REAPI you'll need it. Otherwise you'll have to modify this code to use the NetCommunity API which is free. I know the REAPI better for this stuff which is why I used it. 

    ''' this method will take a REID and get the address
    ''' then it will use google maps to lookup that address address
    ''' note: the value of the returned array with the lat/lng is nothing if
    ''' either the address coudln't be geocoded or it wasnt' specific enough to get back a single result
    Public Function getConstitLatLng(ByVal sREID As String) As ArrayList
        Dim oConstit As New CRecord 'this is the constit object
        Dim aLatLng As New ArrayList(2) 'we'll be returning this.
        Dim RE7 As REAPI = initAPI() 'this is located in the source. be sure to change up your serial, username, pass and db number. 
        Dim oAddress As CConstitAddress 'address object
            With oConstit
                .Init(RE7.SessionContext) 'init
                .Load(sREID) 'load the passed in REID
                For Each oAddress In .Addresses 'loop over all the addresses
                    If oAddress.Fields(ECONSTIT_ADDRESSFields.CONSTIT_ADDRESS_fld_PREFERRED) = -1 Then 'grab the prefered one, yes I know it's -1 trust me on this -1 = true for some strange reason in the BBREAPI...I don't ask questions if it works. 
                        'pass the retrieved criteria to the seekCoords method
                        aLatLng = getCoords(oAddress.Fields(ECONSTIT_ADDRESSFields.CONSTIT_ADDRESS_fld_ADDRESS_BLOCK) & " " & oAddress.Fields(ECONSTIT_ADDRESSFields.CONSTIT_ADDRESS_fld_CITY) & ", " & oAddress.Fields(ECONSTIT_ADDRESSFields.CONSTIT_ADDRESS_fld_STATE) & " " & oAddress.Fields(ECONSTIT_ADDRESSFields.CONSTIT_ADDRESS_fld_POST_CODE))
                        Exit For
                    End If
            End With
        Finally 'close down your stuff...always
        End Try
        Return aLatLng 'return the value
    End Function

Now lets look at the getCoords function. This one just takes the address we retrieved from the API and uses a Google web service to return the lat/lng. One important thing to note is that it will return Nothing if the address can't be geo-coded OR if the address isn't specific enough and Google returns more than one possible result. I did this for simplicity but you can modify the project so things are handled how you want them to be. 

Private Function getCoords(ByVal sAddress As String) As ArrayList
        Dim stream As IO.Stream = Nothing
        Dim doc As XmlDocument
        Dim req As HttpWebRequest
        Dim aLatLng As New ArrayList
        If sAddress <> "" Then 'we check to make sure that we have an address
            req = DirectCast(WebRequest.Create("" + sAddress), HttpWebRequest) 'pass the address to googole and assign the results to req
            'now we parse up the results 
            'generally speaking kml = xml so we can use the std handlers in .net for this
            'why google doesn't just call it xml is beyond me
            Dim response As HttpWebResponse = DirectCast(req.GetResponse(), HttpWebResponse)
            stream = response.GetResponseStream()
            Dim sr As New StreamReader(stream)
            Dim text As String = ""
            text = sr.ReadToEnd()
            doc = New XmlDocument()
            longitudes = doc.GetElementsByTagName("longitude")
            latitudes = doc.GetElementsByTagName("latitude")
            'for simplicty we only want to worry about results that have 1 possible result
            'none, means the address wasn't geocodable
            'multiple means the address wasn't specific enough
            If longitudes.Count = 1 Then
            End If
        End If
        Return aLatLng
    End Function

So that's pretty much it. You can download the full project below, enjoy. 

Don't forget to Join the LinkedIn and/or Facebook group and be sure to follow me on Twitter.