Welcome to Coders for Christ Sign in | Join | Help

I've been asked by a few people why we decided not to attend this year's roundtable.  We've been very disappointed with the 2008.3 release (the problems that it created, the lack of a documented test plan and release certification checklist/sign-off, missing feature documentation and general lack of product responsibility) and decided to make a statement that Arena needed to focus its attention on their core business first.

We made this decision several months ago shortly after the 2008.3 release prior to knowing about the two things that will be announced at the roundtable.  I'll be commenting on these two things immediately as the news breaks on Monday morning.

Now that it's been announced to the Arena community developers I can discuss the news: CCV has decided to branch away from the Arena core code base.

It's difficult for me to talk too much about this situation, since I'm pretty close with Jon and David, and I've got friends over at the Arena HQ in Tennessee.  I've also been involved in the Community Developer Board for the past two years, so I've been able to listen in on many of the discussions between CCV and Arena.  I think it's probably safe for everyone to assume that there is at least some blame (not even sure blame is the right word) on both sides.  Also, based on some things I've heard, both sides believe they will be unshackled a bit by the breakup.  Undoubtedly not having to worry about each others changes will eliminate some additional work they've both been having to deal with, but I personally believe this will probably come at a cost.

Regardless of the reasons that brought CCV and Arena to this point, what will this mean to Arena?

Originally this was going to be the end of the post and I was going to initially refrain from giving my opinion. But after several days of reflection I've decided to be the first to chime in...


I think without proper guidance and strong, decisive leadership there is a danger that Arena could become what many other older ChMS products became: dull, convoluted, complicated, and bloated.  But I think there is definitely hope...

Yes, CCV originally created what we now call Arena ChMS.  They are the masterminds and designers behind most of what it is today.  We all have David and Jon to thank for this.  And the guys at Arena definitely made it a product and added various regular features and many administrative features.  As much as I'd like to think that CCV has been directing the future of Arena/Arena-features, you could make a case that this really has not happened as much over the past 2 years.  I do believe the relationship they shared allowed CCV to influence the overall product to a degree and a continued commitment to that relationship could still have a similar effect.  Even so, CCV's branching will eventually mean that their modules** will not be compatible with any of our Arena installations.

I believe the key to Arena's future is what the community does.  It's the community that makes Arena unique.

When I read Joel's recent post I was reminded of this fact.  Thanks Joel!  What other ChMS system allows you to pick between three different check-in solutions?  As more developer churches come aboard and create more solutions/modules, we all win.  However, now more than ever - the community's role must increase.  And it's not necessarily easy or free.  It will mean more focused, thoughtful discussions.  More energy spent on packaging and documenting your modules for others.  More communicating and coordinating with others.  More of everything.

Trust me -- it takes time and energy.  If you do not put in the time, it will not just happen automatically.

Will the community rise to the challenge?  I believe it will.

[The other great news is that Arena has finally established a single person to be the Product Manager -- and it is Mark White.  I'll cover this in another post.]

** Jon and David tell me they will actually still do some development on the standard Arena product too -- if not during their work week, on their own free time.  And so they will still be part of the community.  So, be on the lookout for some of this great stuff because I recently got a glimpse of some of it.

2 Comments
Filed under: , ,

I was pretty excited about the upcoming AZGroups event with Scott Guthrie next week, but when I started reading about VS 2010 beta 1 released yesterday and some of the .NET 4.0 features I had a flashback about something I said in 2006, but first check out this quote by Kathleen Dollard** in her recent blog entry:

".NET 4.0 is likely to offer patterns that will be the most important change in my coding since the huge changes brought on by LINQ (and supporting techniques like extensions and lambdas) of .NET 3.5. That was the most important change to my coding since generics in .NET 2.0. That was the most important change to my coding style since strongly typed full OO programming came on in .NET 1.0. That was the most important change to my coding style since the visual coding style of Visual Basic (pre .NET). That was the most important change to my coding style since Clipper and FoxPro. Get the trend? Eight years, eight years, three years, two years, 18 months... I do a talk for INETA called "Rethinking Object Orientation" that tries to get a grip on these changes... .NET 4.0 is going to bring a lot and inspire a lot of rethinking.

...

The most important feature of .NET 4.0 is Windows Workflow 4.0."

I think she's exactly right.  When I first started looking at WF at the end of 2006, I said the following in a blog post:

 "...I believe WF has the potential to further revolutionize software development by allowing designers to extract hard-coded business logic from their applications..."

Unfortunately WF was really difficult to use, but if they've solved that problem with this complete re-write, I think it's going to be another thing that we'd be unwise to ignore (similar to what I said about LINQ) as it will become a part of every developer's world.

I hope Scott Guthrie spends some time talking about WF next week.

-Nick 

** I first saw Kathleen at DevConnections in Vegas a year or so ago and she stood out to me as a very level headed and practical developer/architect and I have a lot of respect for her assessments.

MIX09I know this is a month old, but I'm just getting caught up on some reading/viewing...  If you also haven't seen the day 1 keynote of MIX 09 and care about where your craft is going, you need to watch at least the first 8 minutes of the video and then if you're short on time jump to the 97 minute mark and watch the demo of Expression Blend 3.

Having watched that video and having recently worked on our new web site, it's becoming more clear to me how important user experience really is.

Here's a small example of what I mean...

Previously, I might not think twice about a login popup that went something like this:

user experience 1

Now, it seems to me like everything ought to behave more like this:

user experience 2

On one hand it may seem subtle, but on the other hand it definitely changes the user experience.  I actually enjoy logging in to the site (ok, yes, I'm quite weird ;).

I'm guessing we'll get to see some other related cool demos when Scott Guthrie presents next month at the local AZGroups event.  I'll see you there!

This week we finished development and implementation of our latest, jQuery flavored, Arena powered cccev.com website -- and I'm pretty excited about how it turned out.  Everyone did a tremendous job: Jeremy Wagner and Mark Miller on design; Jason Offutt, Dallon and myself on development and implementation; the company PSD2HTML for slicing, and many other Cccev staff for content and testing.

It went down like this...

Jason, Dallon and I first sat down with Mark and his PSD mockups.  It was agreed in advance that our team would provide about 30 days of development time.  We broke everything down into the individual modules we needed to create or customize, and then entered each feature into OnTime (as sprint 1) along with an estimated number of hours to complete it.  Mark had to make decisions whether to keep or toss an idea, because once OnTime said we had reached a total of 30 days worth of estimated work, our meeting was over and sprint 1 was locked in.

Next Mark took the PSDs and worked with PSD2HTML to slice everything into working HTML mockups.  As Mark received output from PSD2HTML we got to work on making them actual functioning Arena modules (more on this approach at the conclusion).

What follows is a quick dissection of sprint 1 for the site.

We created six page templates.  One for the home page, three for department/subpages (1 col, 2 col, 3 col), one for our newsletter main page called "the Drop", and one for the video/podcast stuff called Central TV.

Home page:

  • The promotion/feature roller you see on the home page is a custom Arena module Dallon created which uses LINQ-to-Objects to get the promotions and jQuery and the jquery.galleryScroll.1.4.5.pack.js for the slide navigation.
  • The main drop down navigation is a custom module Jason created which also uses LINQ-to-Objects and jQuery for the slide effects. (applied to the appropriate content area of all new templates)
  • The login-link-user-login popup is a combination of a custom Login Logout control I wrote which controls the display of a custom UserLogin.ascx module (which inherits the standard Arena ArenaWeb.UserControls.Security.UserLogin control). (applied to the appropriate content area of all new templates)

Sub pages: 

  • Side bar calendar with mini event details was created by Jason.  It starts from a parent event id (module setting) and traverses the tree to obtain all child events that are flagged with the given topic areas (module setting).  jQuery is used to slide the event details when there are multiple events.
  • The calendar Invite Friend popup was written by Jason and is smooth-shown via a jQuery wired to the click event of the 'send invite' link on the side bar calendar.
  • The subpage navigation was created by Dallon in about 100 lines of code and markup which uses LINQ-to-Objects (see snippet below) to obtain the pages and jQuery for the sub-sub page slide animation:
    var pages = (from p in rootPage.ChildPages.OfType<PortalPage>()
                 where (p.PortalPageID != -1 && p.DisplayInNav && p.Permissions.Allowed(Arena.Security.OperationType.View, CurrentUser))
                 select p).Distinct().OrderBy(p => p.PageOrder);
  • The serving opportunities viewer, created by Dallon, also uses LINQ-to-Objects and jQuery (see a pattern? I told you LINQ was not something to ignore;) and displays all public viewable serving tags which are a child of a given parent serving tag (module setting).
  • (Not shown) a custom Background changer module applied to the department pages which uses jQuery to dynamically add css classes to particular elements to effectively change the background image according to the configured background (lookup; module setting).
  • (not shown) a custom Flickr module Jason wrote which uses Athena (which uses LinqExtender).  It takes a Flickr ID (module setting) and creates a small grid of photo thumbnails which smoothly slides on prev/next navigation.

The Central TV pages use three custom modules created by Jason: channel viewer, series/topic viewer, and video player.

The Drop page uses a custom NewsletterSubscriber.ascx (it inherits the standard ArenaWeb.UserControls.Core.NewsletterSubscribe class) to achieve the exact layout needed to match Mark and Jeremy's design.

Lastly, for those who care, we relied on the underlying Arena object framework -- we did not create any custom objects.

We actually finished on time, and the burndown chart in OnTime really helped everyone stay focused.  In conclusion, one valuable lesson I learned was the added complexity of setting up our development pipeline overlapping with PSD2HTML.  The dependency between their work (javascript, css, and HTML slices) and our modules made our work messy, inefficient and disheartening at times as we would have to chase down layout bugs after merging their latest output with ours.  Next time we'll just wait until they're complete before starting our work.

For the past few weeks, I was beginning to think our new Arena check-in module was only going to be a virtual system -- not a real, working application.  You see, we had to postpone the full rollout a few weeks ago when our first full scale pilot had a printing meltdown.  After about 20-40 people had successfully checked in, all remaining check-in labels (Zebra LP2824) would fail to print.

Zebra LP2824: my baneIn hindsight, the source of the problem now seems virtually clear... (hint hint)

Jason and I could see where the problem was, but we couldn't explain it.  In code, we check the PrintDocument's IsValid property, and while normally this should return true, after some unknown point it would always return false.   We also discovered just prior to this, our exception log had a System.AccessViolationException with the message 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'

The only way to clear the system from this state was to perform an "iisreset".   The problem seemed to linger in the IIS application pool.  We reckoned that the memory Derek added to the VM host a few days earlier might be the issue so we removed it and tried again.  Same problem.

We did more digging and testing and were able to see this in the stack trace:

at System.Drawing.Internal.IntUnsafeNativeMethods.IntCreateDC(String lpszDriverName, String lpszDeviceName, String lpszOutput, HandleRef lpInitData) 
at System.Drawing.Internal.IntUnsafeNativeMethods.CreateDC(String lpszDriverName, String lpszDeviceName, String lpszOutput, HandleRef lpInitData) 
at System.Drawing.Internal.DeviceContext.CreateDC(String driverName, String deviceName, String fileName, HandleRef devMode) 
at System.Drawing.Printing.PrinterSettings.CreateDeviceContext(IntPtr hdevmode) 
at System.Drawing.Printing.StandardPrintController.OnStartPrint(PrintDocument document, PrintEventArgs e) 
at System.Windows.Forms.PrintControllerWithStatusDialog.OnStartPrint(PrintDocument document, PrintEventArgs e) 
at System.Drawing.Printing.PrintController.Print(PrintDocument document) 
at System.Drawing.Printing.PrintDocument.Print() 
at Arena.Custom.Cccev.CheckIn.CheckinLabel.PrintAllLabels(String printerURL) in C:\Arena Trunk\trunk\Arena.Custom.Cccev\Arena.Custom.Cccev.CheckIn\Entity\CheckinLabel.cs:line 341 
at Arena.Custom.Cccev.CheckIn.Entity.CccevPrintLabel.Arena.Custom.Cccev.CheckIn.Entity.IPrintLabel.Print(FamilyMember attendee, IEnumerable`1 occurrences, OccurrenceAttendance attendance) in C:\Arena Trunk\trunk\Arena.Custom.Cccev\Arena.Custom.Cccev.CheckIn\Entity\CccevPrintLabel.cs:line 61 
at Arena.Custom.Cccev.CheckIn.Controller.PrintLabel(FamilyMember attendee, IEnumerable`1 occurrences, OccurrenceAttendance attendance) in C:\Arena Trunk\trunk\Arena.Custom.Cccev\Arena.Custom.Cccev.CheckIn\CheckInBLL.cs:line 500

Hmmm... IntUnsafeNativeMethods...This seemed to point us in the direction of a driver problem.  We removed the latest Seagull Scientific drivers (7.1.6) and put their older drivers (7.0.2) which we've been using in another environment with no issues.  The problem happened again, but the exception was slightly different:

at System.Drawing.SafeNativeMethods.DocumentProperties(HandleRef hwnd, HandleRef hPrinter, String pDeviceName, IntPtr pDevModeOutput, IntPtr pDevModeInput, Int32 fMode) 
at System.Drawing.Printing.PageSettings.CopyToHdevmode(IntPtr hdevmode) 
at System.Drawing.Printing.PrinterSettings.GetHdevmode(PageSettings pageSettings) 
at System.Drawing.Printing.PrintController.OnStartPrint(PrintDocument document, PrintEventArgs e) 
at System.Windows.Forms.PrintControllerWithStatusDialog.OnStartPrint(PrintDocument document, PrintEventArgs e) 
at System.Drawing.Printing.PrintController.Print(PrintDocument document) 
at System.Drawing.Printing.PrintDocument.Print() 
at Arena.Custom.Cccev.CheckIn.CheckinLabel.PrintAllLabels(String printerURL) in C:\Arena Trunk\trunk\Arena.Custom.Cccev\Arena.Custom.Cccev.CheckIn\Entity\CheckinLabel.cs:line 341 
at Arena.Custom.Cccev.CheckIn.Entity.CccevPrintLabel.Arena.Custom.Cccev.CheckIn.Entity.IPrintLabel.Print(FamilyMember attendee, IEnumerable`1 occurrences, OccurrenceAttendance attendance) in C:\Arena Trunk\trunk\Arena.Custom.Cccev\Arena.Custom.Cccev.CheckIn\Entity\CccevPrintLabel.cs:line 61 
at Arena.Custom.Cccev.CheckIn.Controller.PrintLabel(FamilyMember attendee, IEnumerable`1 occurrences, OccurrenceAttendance attendance) in C:\Arena Trunk\trunk\Arena.Custom.Cccev\Arena.Custom.Cccev.CheckIn\CheckInBLL.cs:line 500

Could the problem be with the Hyper-V which is running our virtualized server?  Phil recommended that we copy our environment to a non-virtualized host, and after several more hours of setup and testing -- presto -- problem gone.  We ran our Gilbert campus children's check-in all weekend long on this temporary, alternate system without a hitch.  Jason and I finally took a sigh of relief.

Our (Derek's) next step is to definitively isolate the problem by moving our server to Microsoft's Virtual Server to see if the problem is exclusively with Hyper-V, and if needed, possibly de-virtualize the system entirely back to reality.

I wonder if we're the only shop trying to serve Zebra printers with Seagull Scientific drivers on a Win2003 virtual environment.  Anyone?  (If you're out there, we feel your pain.)

I'm coming out of my cave to share a few great bits of news.

OnTime 2009 Express1) Since my last post, Jason Offutt has joined our team! Jason comes from Christ's Church of the Valley (CCV) where he was previously developing Arena modules.  With his hiring, Jason also becomes Central's first full time developer (I'm still a self-inflicted part-timer).

2) Without Jason's help we would still by at 70% development completion of our new Arena check-in module.  However due to his monumental efforts we actually had our first complete test milestone at the end of December and are piloting the new Children's check-in this weekend.  We've been in touch with a few other churches (I'll let them comment if they want) and will be sharing the code via the community SVN shortly after the rollout.

3) OnTime 2009 Express edition only costs $5 for a team of up to 5 developers!  Read the full press details.  With the edition of Jason and Dallon's ever increasing development contributions, we're really in need of a bit of a process and tool overhaul to help manage our software projects.  We'll be using OnTime 2009 for sure.  If you've ever seen Axosoft's founder, Hamid Shojee, talk you know what I mean when I say he's brilliant -- check out his entertaining 'SCRUM in under 10 Minutes' video.  He can even make a presentation in software development methodology fun.

(Note: With this post I'm going to tag any similar, future rants as "angry coder".  Although they will be few, I'm doing this just in case you want to take a pass on any of these kinds of entries.)

BSOI love Google, but with their recent announcement I thought I was going to cry.  Does the world really need another browser?  Aren't the existing set of mediocre ones enough?  Opera, Safari, IE, Firefox, Konqueror, AOL TBD, Flock, etc., and now Chrome.

Let me pick on Google for a minute.  I'd really like to see them work on support for HTML/CSS in their premiere email client, Gmail.  It's arguably among the worst when it comes to CSS support.  Perhaps their entry into the browser market will help them with this problem...

I was a staunch Netscape supporter back in the day but, as a web developer, it was never fun being the middleman in the browser display/layout war.  When you're just trying to write programs to solve the latest business problem (and do it in a cross-platform, client-lite way), you really don't have the desire or patience to worry about some other vendor's browser.  It's inefficient at best and it's certainly not your job.  Or is it?  Perhaps when we decided to write a web application we also signed on to support any and every web browser that one of our users wants to use?  Perhaps there is no place to draw the line.  There is no hope.

Enter the 3rd party control developers!  Yes, that's right -- it's their job.  Pick from Telerik, ComponentArt, Infragistics, Devexpress, etc.  Let them worry about the war.  They will do it better and more completely than you and I can.  You and I can get back to developing solutions for our domain(s) and leave the browser war behind.

Let me summarize with the point that drove me to finally speak up regarding this topic. I think Jon Edmiston's key #7 captures it well.  Beware of bright shiny objects.  Chrome is definitely shiny.  Seriously.  Will installing it or twittering it (don't get me started on this ;) help us be successful?  Will having it help with the business problems we're getting ready to solve?

LOL - can you do this?[update: only moments after posting this, I happened to visit a link that Scott Miller had sent earlier today.  I had to laugh out loud because I don't think I've ever actually had this happen to me.  Perhaps this (see image) is another way to deal with it.  Hey, where is Chrome in that list?]

1 Comments
Filed under: ,

I dig the latest version of Arena ChMS and the new Document Types feature is great.  In a nutshell it allows you to attach documents (pdf, images, .doc, etc.) to a person, tag or group.  It's the feature that enables you to move to a paperless office and it's super easy to setup.

Last click to watch demoweek a super admin, Kim came to me and said something like, 'I want to throw out this huge book of completed paper forms before I drop it on my foot and break my toe.'  I said "let's do it."  We quickly setup a new Document Type and a Person Attribute to hold the document. Now she just scans the document, attaches it to the person's record and then shreds the original.

In Kim's case she was maintaining the paper copies of our driving insurance form -- some paperwork that our insurance company gives us when someone has permission to drive the church vans.  The document is slightly sensitive so we also locked it down so that only few people have access to edit or view it.

We've lined up several more documents we'll be moving to Arena including our:

  • 4 page application to serve (currently a fillable PDF)click to watch
  • applicant background check (pdf)
  • applicant's reference response documents (typically emailed .doc or paper)
  • and several other paper forms people are physically signing

With Arena you can literally set these up in just a few minutes.  Watch this video to see how it is done.

announcementA couple of months ago I had the pleasure of introducing Dallon's Developer in Beta to the blogosphere, and now I get share the news of Jason Hamrock's new blog.

Jason is the Communications Director at CCCEV and his team is one of my team's biggest Arena "customer". As such they rely on Arena as the CMS for the web site, event announcement and promotion, and soon a semi weekly newsletter.  He's already queued up several posts so If you're involved in commuicating with your church body be sure to subscribe to his blog as he'll be sharing the good, the bad and the ugly we face every week/month at Central.

0 Comments
Filed under:

UAT for ArenaIf you're not familiar with a UAT environment, it's the place where your users can perform either formal testing or just simply kick the tires of the latest version of your system/application (depending on how formal your "testing" really is).  Most corporate environments have a UAT environment for their mission critical systems.

At our church our mission critical system is Arena.  Although it's not ideal that me, our staff, or any Arena customer are the ones to find a bug with the latest version of Arena, it is nice to have a chance of finding one before it goes live.  A UAT environment is also a great way to provide advanced training to your Power Users on features that will be in the upcoming release (like the training Austin Spooner does with his teams after their monthly staff meetings).

Now that we've virtualized our servers, creating a UAT system has become a bit easier and I finally created a more formal Arena UAT environment which even includes a recent copy of the underlying database.  I think I've come up with some faily simple steps that anyone can follow to create their own.

These steps basically create a replica of your production environment and then upgrade it to the latest version of Arena.

  1. Create a new virtual server.  We called ours UAT01.
  2. Install SQL Server 2005 with Reporting Services.
  3. Add a alias (CNAME) record to your DNS that points your test arena site (ArenaTest) to your UAT server (UAT01).
  4. Copy your Arena web folder from your production server to your new UAT server (ex. copy '\\ARENA\C$\Program Files\Arena ChMS\Arena' '\\UAT01\C$\Program Files\Arena ChMS\Arena').  You can do the same with your ArenaCheckIn web folder.
    1. Edit the copied web.config replacing your normal database server name with your UAT server (UAT01).
  5. In IIS on your production Arena server, save your configuration to a file.
    IIS - Save Configuration to a File...
  6. In IIS on your UAT server, create a new site or virtual directory from a file (that was created in previous step).
    1. You may need to verify that the web app is set to ASP.NET 2.0
  7. Backup your production ArenaDB from your SQL server and restore it to your UAT server.
    1. Before restoring your ArenaDB backup, you might also run Arena's SQLInstaller.exe which will can create a new, empty database.  I did it this way for a particular reason but I don't think you should need to do this.
    2. Depending on your situation, you may have an orphaned Arena login which you can fix in SQL Manager using:

      USE ArenaDB

      GO

      sp_change_users_login 'auto_fix', 'Arena'
      GO

    3. Verify that the database's Arena login is dbo for the new ArenaDB.
  8. At this point, in theory, you've made a copy of your production Arena environment.
    1. You might test by visting your UAT url (http://ArenaTest or http://ArenaTest/arena
    2. Disable your Arena->Shelby triggers in SQL Manager using: 

      USE ArenaDB;

      GO

      EXEC sp_MSforeachtable @command1="ALTER TABLE ? DISABLE TRIGGER ALL"

      GO

    3. Edit your Arena Organizations settings (under Administration) changing the value of your "CheckInUrl" and "ReportServerURL" settings to the new appropriate value.
    4. You might also want to take a "snapshot" of your virtual server so you can perform the next steps (the upgrade) over if necessary.
  9. Upgrade your Arena UAT to the latest version...
    1. Download and execute the latest version of ArenaSetup.exe
    2. Follow the steps in the wizard as necessary
    3. After the install disable the Arena Automation Agent and set it to manual startup (in Windows Services) or do whatever you want with it... just be careful what jobs you run since they could potentially be emailing people when you really don't want to.
  10. Almost done... replace your Arena header images with this new set here to avoid user confusion.
  11. Test your site and then let your power users know about it.
0 Comments
Filed under:

Desert Code CampIs the expression "you are what you read" true?  I think it is to some degree.  Not only does it give you knowledge but it also says something about you.  My most innovative friends are heavy blog, book and magazine readers, and I believe there is a correlation.  I frequently ask people what blogs or magazines they are read because I want to know a little more about them.

When it comes to software development, I think it is especially important to keep up with the state of our art and its related technology.  Knowing about something does not mean you have to run out and implement it, but I believe you're in a better position to make future decisions.

It's truly a treat when you can spend a whole day learning from experts (or just people who know more than you) and it doesn't cost you anything but time.  That's why I especially love the Desert Code Camp that the guys at AZGroups (formely AZ .NET User Groups) have been putting on for a while now.  You can spend 8 hours and ramp up very rapidly on several things which you may have only heard very little about  -- whether you want just an overview of a technology or want to go deeper into something you've read only a little about.

At the upcoming DCC on Saturday, May 31 you'll have a chance to learn about things such as:

  • FLEX and Adobe AIR
  • Agile SCRUM
  • iPhone SDK
  • Continuous Integration
  • LINQ
  • Silverlight (I love the presenters description of this class: No "Hello World". No MS Comic Sans. No interminable feature dump of XAML attributes. And most definitely, no multicolor-gradient-filled rotating rectangles "just because they're possible". There is a correct time and place to create a multicolored gradient: when you're five years old and playing with watercolors. "I'm a developer not a designer" is no reason to build an application that looks like one of Bill Cosby's sweaters.)
  • Google AppEngine
  • SOA / Enterprise 2.0 REST
  • ColdFusion 8 (are people still using ColdFusion???)
  • and more!

So clear your schedule on Saturday, May 31 and join me at the Desert Code Camp!

1 Comments
Filed under: , ,

the Arena Community DeveloperIf you were at the Fall 07 Arena Community Developer Rountable you heard me mention Dallon as the youngest Arena Community Developer, but now I'd like to introduce him via his new blog -- Developer in Beta.

Dallon is a remarkable developer who's been quite involved at our church (our IT team) for the past 3-4 years where both his Dad and Mom now work full and part time, respectively.   And he's only 13.

With fantastic teaching and support from his parents, Dallon typically drops by on Monday afternoon's to both code and learn.  It was fun introducing him to some basic OO concepts several years ago, but his skills and ability to learn has easily surpassed my abilities and time available to teach him everything he is capable of learning.  (This past year I was glad to see Dallon start taking formal, pre-college/college level courses online.)

Dallon has written several Arena ChMS modules of varying sizes including one for managing Central's food pantry (where his Mom leads/serves). With time on his side he has become quite familiar with, and begun using, many of the latest .NET technologies including ASP.NET AJAX, LINQ and Silverlight, and on more than one occasion Dallon's asked me 'when can we start using that in our Arena development environment.'  It's been fun trying to explain how sometimes we can't move as fast as we'd like...

If you want a fresh perspective on various developer related topics check out Dallon's blog, Developer in Beta.

My pestering has paid off.  I just got word on Friday that Derek Mangrum, our Network and Systems Administrator, has begun blogging IT specific posts over at Grinding-IT-Out and he's doing it at a furious, daily pace (compared to my 1-2 per month).  Derek's been tremendous addition to our IT team and is always learning and teaching me interesting things.  Because of that I've periodically hinted to him that he should be sharing all those goodies in a blog.

Don't be shy -- stop over there and drop him a "welcome" comment on his Introduction post.

0 Comments
Filed under: ,

With the current release of Arena (2007.2.x) there is no "E-Ticket" feature, which means if you enable it for one of your online registrations it will attempt to link to a page/file that does not exist (~/eticket.aspx).  Luckily, this also means you can easily write your own!

With very little work I created a eticket.aspx page that creates the one (non-styled) shown here: 

eTicket

Everything was trivial. The only interesting part was creating the barcode.  Because you can't expect the user's browser to have a barcode font installed, it's best to create it on the server and then render it as an image.  I used some of the information from Imran's Barcode Image Generation Made Easy article on DotNetSlackers.com to do this.

I ended up making an OutputBarCode method to perform the output rendering so that I could reference the same page with an additional querystring parameter (line 52 of the .cs).  When this barcode image source is retrieved the Page_Load calls the OutputBarCode method (line 12-14).  Also note that the barcode font does not need to be "installed" on your server.  Instead, it is simply referenced from the webroot (line 66 of the .cs).

You can download these two files here.

eticket.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="eticket.aspx.cs" Inherits="eticket" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Your Registration Confirmation</title>
    <link href="CSS/arena.css" rel="stylesheet" type="text/css" />
</head>
<body onload="window.print(); window.close();">
    <form id="form1" runat="server">
    <div class="eticketContainer" style="padding: 10px 10px 10px 10px">
        <asp:Panel ID="pnlViewETicket" Visible=false runat="server">
            <h2>Registration Receipt</h2>
                <table border="0" cellpadding="4" cellspacing="0">
                    <tr>
                        <td style="width: 100px"><span class="formLabel">Name(s):</span>
                        </td>
                        <td><asp:Label ID="lblName" runat="server" CssClass="formItem"></asp:Label>
                        </td>
                    </tr>
                    <tr>
                        <td style="width: 100px"><span class="formLabel">Event:</span>
                        </td>
                        <td ><asp:Label ID="lblEventName" runat="server" CssClass="formItem"></asp:Label>
                        </td>
                    </tr>
                    <tr>
                        <td style="width: 100px"><span class="formLabel">Date(s):</span>
                        </td>
                        <td ><asp:Label ID="lblEventDate" runat="server" CssClass="formItem"></asp:Label>
                        </td>
                    </tr>
                    <tr>
                        <td style="width: 100px">
                        </td>
                        <td><asp:Label ID="lblEventDescription" runat="server" CssClass="formItem"></asp:Label>
                        </td>
                    </tr>
                    <tr>
                        <td style="width: 100px"><span class="formLabel">registration ID:</span>
                        </td>
                        <td><asp:Label ID="lblRegistrationID" runat="server" CssClass="formItem"></asp:Label>
                        </td>
                    </tr>
                </table>
                <asp:Panel runat="server" ID="pnlSpecialNotes">
                    <h3>Special Notes</h3>
                    <asp:Label ID="lblEventConfirmation" runat="server" CssClass="formItem"></asp:Label>
                </asp:Panel>
            <p><asp:Image runat="server" ID="imgBarcode"/></p>
            <p class="smallText" style="text-align: center; text-transform: uppercase">Please present this document when you arrive at the event.</p>
        </asp:Panel>
    </div>
    </form>
</body>
</html>

eticket.aspx.cs

   1: using System;
   2: using System.Drawing;
   3: using System.Drawing.Imaging;
   4: using System.Drawing.Text;
   5: using System.Web;
   6: using Arena.Event;
   7:  
   8: public partial class eticket : System.Web.UI.Page
   9: {
  10:     protected void Page_Load( object sender, EventArgs e )
  11:     {
  12:         if ( ! IsPostBack && Request.QueryString[ "r" ] != null && Request.QueryString[ "b" ] != null )
  13:         {
  14:             OutputBarCode( Request.QueryString[ "r" ] );
  15:         }
  16:         else if ( ! IsPostBack && Request.QueryString[ "r" ] != null )
  17:         {
  18:             PrintEticket( Request.QueryString[ "r" ] );
  19:         }
  20:     }
  21:  
  22:     /// <summary>
  23:     /// Binds the needed registration information to the form's controls.
  24:     /// </summary>
  25:     /// <param name="guid"></param>
  26:     private void PrintEticket( string guid )
  27:     {
  28:         Registration registration = new Registration( new Guid( guid ) );
  29:         if ( registration != null && registration.RegistrationId != -1 )
  30:         {
  31:             this.pnlViewETicket.Visible = true;
  32:             this.lblName.Text = registration.Registrants.ToHtml();
  33:             this.lblEventName.Text = registration.EventProfile.Name;
  34:             this.lblEventDescription.Text = registration.EventProfile.Details; ;
  35:             this.lblEventDate.Text = registration.EventProfile.Start.ToShortDateString() +
  36:                 " " + registration.EventProfile.Start.ToShortTimeString() +
  37:                 " - " + registration.EventProfile.End.ToShortDateString() + " " + registration.EventProfile.End.ToShortTimeString();
  38:             
  39:             if ( !"".Equals( registration.EventProfile.ConfirmationText.Trim() ) )
  40:             {
  41:                 this.lblEventConfirmation.Text = registration.EventProfile.ConfirmationText;
  42:             }
  43:             else
  44:             {
  45:                 this.pnlSpecialNotes.Visible = false;
  46:             }
  47:  
  48:             this.lblRegistrationID.Text = registration.Guid.ToString();
  49:  
  50:             // Set the barcode source to be this page (the b=1) will cause the
  51:             // image output to be rendered on the fly via the OutputBarCode method.
  52:             imgBarcode.ImageUrl = Request.RawUrl + "&b=1";
  53:         }
  54:     }
  55:  
  56:     /// <summary>
  57:     /// This method will create the barcode and stream the image
  58:     /// data to the Response.OutputStream.
  59:     /// </summary>
  60:     /// <param name="text">the text to barcode</param>
  61:     private void OutputBarCode( string text )
  62:     {  
  63:         string TypeFaceName = "barcode font";
  64:  
  65:         PrivateFontCollection fnts = new PrivateFontCollection();   
  66:         fnts.AddFontFile( Server.MapPath( "~/BarcodeFont.ttf" ) );    
  67:         FontFamily fntfam = new FontFamily( TypeFaceName, fnts );    
  68:         Font fnt = new Font( fntfam, 46 );                                       
  69:       
  70:         //Draw the barcode as an image 
  71:         Bitmap bmp = new Bitmap( 500, 60 );           //Canvas size    
  72:         Graphics g = Graphics.FromImage( bmp );
  73:         g.Clear( Color.White );
  74:  
  75:         Brush br = new SolidBrush( Color.Black );
  76:         StringFormat stringFormat = new StringFormat();
  77:         //stringFormat.FormatFlags = StringFormatFlags.DirectionVertical;
  78:  
  79:         g.DrawString( text, fnt, br, 10, 10, stringFormat );
  80:  
  81:         Response.Clear();
  82:         Response.ClearContent();
  83:         Response.ClearHeaders();
  84:         Response.ContentType = "image/jpg";
  85:         Response.AddHeader( "Content-Type", "image/jpg" );
  86:  
  87:         bmp.Save( Response.OutputStream, ImageFormat.Jpeg ); 
  88:         bmp.Dispose();
  89:         Response.End();
  90:     }
  91: }
More Posts Next page »