LavaBlast Software Blog

Help your franchise business get to the next level.
AddThis Feed Button

SubSonic v2.1 Controller and Utilities

clock August 4, 2008 11:45 by author JKealey

We've done a few posts about how we use SubSonic here at LavaBlast. Recently, SubSonic v2.1 was released and we upgraded the code we've previously published to support this new version. We've blogged about our changes in the past and not much has changed since, but we did get a request to post our source code, so here it is. I've actually included a bit more code in this release so that this blog post has a bit more substance!

Download the source code.

The file contains our SubSonicController, SubSonicHelper, and our associated code generation templates. Nothing new to see here, except that you get downloadable code. We unfortunately did not have time to play with the new Query engine all that much, so our controller still uses the old one (which is used throughout our codebase). If anyone would like to augment our code to support the new query engine and post it in the comments, that would be great! Moving to the new query engine would circumvent the OR query limitation related to the search fields we've mentioned in the past.

Auditing using SubSonic

We like to log certain things in our Electronic Journal as it gives us ways to debug more efficiently, and provides us with a way to keep track of who changed what in case something breaks. We've included an SQL script that generates our ElectronicJournal table, and code which allows us to save events in the table. We've wired it up to our SubSonicController so that we can log all object updates, for example. What you log is your own business and it depends on your needs and performance requirements.

ej

We've built an administrative interface over this table allowing us to navigate efficiently through the events. (Each of our pages in FranchiseBlast extends from generic controls which list/filter/page rows using our ObjectDataSource, effectively re-using the code we're presenting here.)

Various notes

  • Remember not to mix AND and OR in the current version of this code, with the old query engine.
  • Don't log everything on high volume sites, for obvious reasons.
  • Issue 3 is still open and waiting to be committed. The others bugs I previously reported (and a new one) have been committed.
  • We removed the ToList() which we added last time, because GetList() is already present. (Thanks to our readers for noticing!)
  • We replaced all calls to IsLoaded() to !IsNew() in our codebase. Click here to learn why.
kick it on DotNetKicks.com


Upgrading to SubSonic v2.1

clock July 10, 2008 16:05 by author JKealey

The timing for the release of SubSonic v2.1 could not have been better as we're between time-critical projects at the moment. As our readers know, we've used SubSonic as our business object code generator since we first launched the company. I spent a few hours this morning doing the migration of our codebase and it seems to have gone smoothly. We've posted some cool improvements we've made to SubSonic in previous posts: Improved ManyManyList Control, Object Change Tracking, and an Improved ObjectDataSource Controller. Migrating to v2.1 involved a few changes and this post will describe them briefly. As this is currently a work in progress, we'll let the dust settle before writing a more formal post.

LavaBlastManyManyList :)

Rob integrated the LavaBlastManyManyList control into SubSonic. It does strike me as uncommon for an open source project to list the contributor in the class name, but who am I to complain? :)

Changes to our SubSonicHelper and SubSonicController.

SubSonic changed the base classes for their objects. Therefore, we have to change our own SubSonicController<T, C> to extend RecordBase<T> instead of AbstractRecord<T>. In our SubSonicHelper, we changed AbstractRecord<T> and ActiveRecord<T> to RecordBase<T> but, for some reason, we also had an ActiveList<T> which we changed to AbstractList<T> to match the rest of the application.

SubSonic Collections no longer extend List<T>

Collections are now extending BindingList<T>, apparently for improved DataBinding support. However, this breaks all the code you may have which uses the fact that Collections were generic lists: Sort, Find, FindAll, FindLast, AddRange, Exists, etc. Luckily for us, we have replacement methods for Sort/Find, which are easier to use but not as powerful as custom delegates/predicates. Rewriting the 70-odd locations in our code to avoid using methods from the List<T> interface isn't what I consider fun and you may feel the same way. The code we had to rewrite was non-trivial and rewriting all these locations without being able to recompile and test (as we don't have unit tests that specifically check that the items in a Collection are sorted the right way, for example), we took the decision to go with a low-impact change.

We edited CS_ClassTemplate.aspx and CS_ViewTemplate.aspx and added the following method to both collections:

   1: public List<<%=className%>> ToList()  {
   2:     return new List<<%=className%>>(Items); // shallow copy
   3: }

BindingList<T> has a protected property named Items which is indeed a List<T>. We didn't check the implementation details, but since it doesn't make this property public, we can assume that playing with that list directly (removing items from the list for example) might screw up the original collection. Therefore, we're creating a shallow copy of the List and using that in our code when necessary. Now that everything compiles and works properly, we can rewrite code where performance is more important (and use the original SubSonic collection instead).

Found two bugs, one old, one new.

We've reported two bugs in the SubSonic's brand new issue tracker on Google Code. (Issue 3 is a rare case relating to composite keys and paging, it probably won't affect you as it has been around forever. However, Issue 4 is a bit more worrisome as it implies that most of your code that uses StoredProcedures might not work anymore without a small workaround until they release SubSonic v2.1.1.)

Conclusion

I hope this helps all of you who were trying to get our SubSonic v2.0.3 code working on SubSonic v2.1! When everything will have been tested thoroughly, we'll post more source code.

kick it on DotNetKicks.com


Manage your ASP.NET Web.config Files using NAnt

clock February 19, 2008 13:24 by author JKealey

Egypt trip in 2007 Nothing is more important than the software engineers in a software company. I just finished re-reading Joel Spolsky’s Smart and Get Things Done and it inspired this post. Not only do I admire his writing style, I share Joel’s vision of how a software company should be run. Pampering your programmers is the best decision a manager can make, especially when you’ve built a team that can hit the high notes.

One of Joel’s key elements to running a successful software company is to automate your build process up to the point where it only takes one operation. This minimizes the chance of error while enabling your developers to grey matter to something more complex than copying files. Although they might use the extra time to shop around for student loan consolidation plans (a practice called reverse telecommuting), in most cases they’ll return to writing fresh code or cleaning out existing bugs.

Today’s post is about one of the little things that made my life much easier as a developer: using NAnt to manage our software product line. I’ve come to realize that we encounter these little “sparks” every day, but we never talk about them. Sure, we’ve produce a number of complex software products and they are fun to describe, but I personally enjoy talking about the little things that save time, just like Henry Petroski verbosely describes common items in his books. Fortunately for you, I’ll keep the story short, unlike his description of the evolution of the paper clip in The Evolution of Useful Things (which is still an interesting read, by the way).

Background

We develop lots of ASP.NET websites. Our architecture includes database schemas and business objects shared amongst multiple projects and some common utility libraries.  Furthermore, instead of always inheriting from System.Web.UI.Page and System.Web.UI.UserControl, we have an object oriented inheritance tree as is good software engineering practice. We even have a shared user control library that gets copied over after a successful build. Furthermore, we use ASP.NET master pages and ASP.NET themes to structure our designs. As opposed to what you see in textbooks where themes can be chosen by the user according to their preferences (oh yes, please show me the pink background with fluffy kittens), we use themes to represent different franchise brands.

My point here is that we reusability is key to our solution. We build elements that we can use not only on the website but also in FranchiseBlast, the interactive kiosk, and the point of sale. However, the more you re-use, the more things get complicated. Indeed, the overhead caused by the added configurability we build into our reusable components is non-negligible. We're always on the lookout for new ways to keep things simple, while still reaping the benefits of reuse. We use the Strategy Design Pattern to encapsulate the behavioural changes in our systems and put our various configuration settings inside our Web.config file.

Hurdle #1: Different developers need different web.config files

Our configuration files have a few settings that we want to change on a per-user basis:

- Where should we email exception notifications?

- Database names & file paths

- Google API Keys

How do we manage this? If we put our Web.config file under source control, we'll end up with various conflicts when the developers change the configuration file to suit their tastes. I don't know about you, but I have better things to do than start memorizing API keys or digits of PI.

Solution #1

Our first solution wasn’t fantastic, but it was sufficient for a while. We simply removed the Web.config from source control and created new files, one for each developer (Web.config.jkealey, Web.config.etremblay, etc.) and one for the deployment server (Web.config.server1). When a change was to be made, we whipped out WinMerge and changed all the files. You can quickly understand that this process does not scale well, but it was sufficient for small projects with 2 to 3 developers.

Hurdle #2: Scaling to more than a couple machines

We deploy our point of sale software and kiosks via Subversion. It might be fun to use WinMerge to compare a couple Web.config files, but when you’ve got a hundred web applications to update to the new version, by comparing Web.config files, you’ve got a problem. Doing this by hand wasn’t very difficult but it was error-prone and time consuming. I don’t know if you have seen the Web.config additions that ASP.NET AJAX brought to the table, but upgrading from a release candidate of Atlas to the full release of ASP.NET AJAX was painful (we’re not talking about half a dozen settings in the AppSettings section).

Solution #2

1) Create a template Web.format.config that contains the general Web.config format, with certain placeholders for variables that vary on a per-developer or per-machine basis.

2) Create a web.default.properties that contains the default settings for the web.config

3) Create a web.developername.properties for each developer that simply overrides the default settings with other values when needed.

4) Write a script to replace the placeholders in the Web.format.config and generate your Web.config.developername files for you.

We implemented this strategy using NAnt. Our script does a bit more work because we’ve got interrelated projects, but I will describe the base idea here.

Examples:

Here is a portion of our web.format.config file:

[...]
<appSettings>
    <add key="GoogleMapsAPIKey" value="${GoogleMapsAPIKey}"/>
</appSettings>
<system.web>
   <healthMonitoring enabled="${healthMonitoring.enabled}">
       <providers>
           <clear/>
           <add type="System.Web.Management.SimpleMailWebEventProvider"  name="EmailWebEventProvider"
               from="${bugs_from_email}"
               to="${bugs_to_email}"
               subjectPrefix="${email_prefix}: Exception occurred"
               bodyHeader="!!! HEALTH MONITORING WARNING!!!"
               bodyFooter="Brought to you by LavaBlast Software Inc..."
               buffer="false" />
       </providers>
   </healthMonitoring>
</system.web>
[...]

Property files

Our default settings look something like the following:

<project>
    <property name="GoogleMapsAPIKey" value="ABQIAAAAkzeKMhfEKdddd8YoBaAeaBR0a45XuIX8vaM2H2dddddQpMmazRQ30ddddPdcuXGuhMT2rGPlC0ddd" />
    <property name="healthMonitoring.enabled" value="true"/>
    <property name="email_prefix" value="LavaBlast"/>
    <property name="bugs_to _email" value="info@test.com" />
    <property name="bugs_from_email" value="exception@test.com" />
</project>

 

Our per-developer files include the default settings, and override a few:

<project>
    <!-- load defaults -->
    <include buildfile="web.default.properties"   failonerror="true" />   
        
    <!-- override settings -->
    <property name="GoogleMapsAPIKey" value="ABQIAAAAkzeKMhfEKeeee8YoBaAeaBR0a45XuIX8vaM2H2eeeeeQpMmazRQ30eeeePecuXGuhMT2rGPlC0eee"/>
    <property name="bugs_to_email" value="jkealey@test.com" />
</project>

The NAnt script

We wrote a NAnt script that runs another NAnt instance to perform the property replacements, but the core code comes from Captain Load Test. It is a bit slow because we have to re-invoke NAnt, but it doesn’t appear like you can dynamically include a properties file at runtime. Feel free to comment if you find a way to make it more efficient. We don’t have our generated files under source control as we only version the property files.

<project name="generate configs" default="generate ">
    <property name="destinationfile"   value="web.config" overwrite="false" />  
    <property name="propertyfile"  value="invalid.file" overwrite="false" />  
    <property name="sourcefile"   value="web.format.config" overwrite="false" />
 
    <include buildfile="${propertyfile}"   failonerror="false"   unless="${string::contains(propertyfile, 'invalid.file')}" />   
    
    <target name="configMerge">    
        <copy file="${sourcefile}"  tofile="${destinationfile}" overwrite="true">
            <filterchain>
                <expandproperties />
            </filterchain>
        </copy>
    </target>
 
    <target name="generate ">
        <property name="destinationfile" value="web.config.${machine}" overwrite="true"/>
        <property name="propertyfile" value="web.${machine}.properties" overwrite="true"/> 
        <property name="sourcefile" value="web.format.config" overwrite="true"/>
        <echo message="Generating: ${destinationfile}"/>
        <!--<call target="configMerge"/>-->
        <exec program="nant">
            <arg value="configMerge"/>
            <arg value="-nologo+"/>
            <arg value="-q"/>
            <arg value="-D:sourcefile=${sourcefile}"/>
            <arg value="-D:propertyfile=${propertyfile}"/>
            <arg value="-D:destinationfile=${destinationfile}"/>
        </exec>
    </target>    
</project>

Hurdle #3: Software Product Lines

Egypt trip 2007 Up to now, we’ve talked about taking one project and making it run on a number of machines, depending on a few preferences. However, we’ve taken it one step further because our web applications are part of a software product line. Indeed, we have different themes for different brands. Different companies have different configuration settings and site maps files. Therefore, we needed to be able to generate configuration files for each brand AND for each machine. This also greatly increases the number of configuration files we need.

Solution #3

It wasn’t very difficult to expand to this new level of greatness thanks to the script presented in hurdle #2. We basically have default configuration files for each project (themes, sitemap, name, locale, etc) in addition to the files we’ve shown above. We simply have to load two configuration files instead of one.

We even wrote a batch file (SwitchToBrandA.bat) that generates the property file for the current machine only (via the machine name environment variable) and it replaces the current Web.config. By running one batch file, we switch to the appropriate product for our current machine.

Future work

Currently, it takes a couple minutes to create a new brand or add a new developer. It doesn’t happen often enough to make it worthwhile for us to augment the infrastructure to make it easier on us, but is a foreseeable enhancement for the future. I guess another future work item would actually be hire someone who is an expert in build automation, test automation and automatic data processing! :) These are skills they don't teach in university, but should!

kick it on DotNetKicks.com  



ViewState property code snippet

clock January 23, 2008 12:47 by author EtienneT

One of the things I do frequently is making a new viewstate property to use in a UserControl in ASP.NET.  (Yes, we know, ViewState is evil. We store it in the session and use it in low-volume sites.) Just download this code snippet, open Visual Studio, open Tools->Code Snippets Manager, and finally Import.

ViewState Property.snippet (1.28 kb)

You can then use it just by writing the shortcut in the code editor and pressing TAB.

image

Here is the result:

image

Using the ?? operator is nice since we don't have to do ugly ifs to return a default value and we don't have to assign something in the ViewState either.  We just fill the ViewState when we need it. This avoids bloating up the ViewState with default values.

ViewState Property.snippet (1.28 kb)

kick it on DotNetKicks.com


CheckBoxList hover extender

clock January 22, 2008 09:16 by author JKealey

Summary

This article presents a CheckBoxList extender that enables the user to hover over individual checkboxes in the list and see a popup with additional information.  The information is populated dynamically (web service call) depending on the hovered checkbox' value.

[VIEW THE ONLINE DEMO]

[DOWNLOAD THE CODE] (469.00 kb)

Where could this be useful?

If you use the ManyToManyList in SubSonic, you know that it inherits from the built-in CheckBoxList control to display data from a many-to-many database relationship.  You probably also know that this can be really useful, but it has it's limitations.  We are using the SubSonic many-to-many list to display a list of stores that a user can be associated with.  You can display only one field of information by item with the ManyToManyList control for the foreign table associated in the relationship (unless you use views!).  Here is an example:

storesList

For a particular user, we are listing all possible stores and showing the store ID as a description for the items.  This can have a meaning for some users, but when a new user comes in and doesn't know the store identifiers, you have a problem. All franchise stores share the same store name as they do business under the same name - they can be uniquely identified by their franchisor-assigned ID or by their address. However, we don't want to show too much information in this control, as it would clutter the interface, in our system. We need a way to display more information by item, without taking up too much screen real estate.  

Our solution is very much inspired by the AjaxControlToolkit controls, such as the HoverMenu to display information when the user hovers over an item in our CheckBoxList (or SubSonic ManyToManyList).  We created an AJAX Control Toolkit Extender that asynchronously calls a web service method (or a page method) to obtain the information displayed in the popup control, when the user hovers over an item.  Here is an example of the result:

checkboxListhover

How to use it

You need a CheckBoxList, a panel to display the information, our extender, and a web service method to invoke.

<asp:CheckBoxList ID="CheckBoxList" runat="server">
    <asp:ListItem Text="Item #1" Value="1" />
    <asp:ListItem Text="Item #2" Value="2" />
    <asp:ListItem Text="Item #3" Value="3" />
    <asp:ListItem Text="Item #4" Value="4" />
    <asp:ListItem Text="Item #5" Value="5" />
</asp:CheckBoxList>

<asp:Panel ID="panelInfo" runat="server" CssClass="checkboxlisthover">
    <asp:Label ID="lblTest" runat="server" Text="Label"></asp:Label>
</asp:Panel>

<ajax:CheckboxListHoverExtender
id="checkboxlistext" runat="server"
TargetControlID="CheckBoxList"
PanelID="panelInfo"
DynamicServiceMethod="GetContent"
DynamicControlID="lblTest"
DynamicServicePath="~/CheckBoxList.asmx" />

The web service class should look something like this:

[ScriptService]
    public class CheckboxList : WebService
    {
        [WebMethod]
        [ScriptMethod]
        public string GetContent(string contextKey) { return "";}

    }

Implementation

A web service method was called with the value of the hovered checkbox.  When you DataBind the CheckBoxList, it is very important to assign a value to each of your ListItems.  In this example, each checkbox has a GUID value.  This GUID is passed as a parameter to the web service call automatically by the extender.  The popup panel is then filled with the information returned by the web service.

As stated previously, the CheckBoxListExtender control is very much inspired by the HoverMenu extender.  The two controls have similarities, but we can't use the HoverMenu directly in the CheckBoxList because we don't have access to the item template of a CheckBoxList.  This prevents us from using the built-in HoverMenu extender for each CheckBoxList item.

Coding a new extender

To code a new extender, you can use existing extenders to simplify your life: that's what we did for the CheckBoxListExtender.  It re-uses the HoverExtender and the PopupExtender.  Those two extenders are not in the sample page of the AjaxControlToolkit (we see the HoverMenuExtender and PopupControlExtender but not the two we are using here), but they are in the source code if you want to see them.  Basically when we coded the CheckBoxListExtender, we had to pass the scripts we wanted to depend on:

[RequiredScript(typeof(CommonToolkitScripts))]
[RequiredScript(typeof(HoverExtender))]
[RequiredScript(typeof(PopupExtender))]
[RequiredScript(typeof(AnimationExtender))]

[Designer(typeof(CheckboxListHoverDesigner))]
[ClientScriptResource("LavaBlast.AJAX.CheckboxListExtender.CheckboxListHoverBehavior", "LavaBlast.AJAX.CheckboxListExtender.CheckboxListHoverBehavior.js")]
[TargetControlType(typeof(CheckBoxList))]
public class CheckboxListHoverExtender : DynamicPopulateExtenderControlBase

As you can see, the extender inherits from DynamicPopulateExtenderControlBase.  This means that the extender can dynamically populate the control via a web service call and all the necessary plumbing is already in place. Specifying the scripts you depend on is as easy as using the RequiredScript attribute on your extender class.

JavaScript behavior

As for the JavaScript, for each "TD" inside our CheckBoxList control, we created a HoverBehavior (this is from the HoverExtender).  Each time the HoverBehavior events are fired, we can do something about them.  In this case, we simply activated the PopupBehavior to show the popup panel and call the web service method to populate the content.  As the value of each checkbox of the list is not contained in the DOM of the page, most probably a security feature of ASP.NET, you have to somehow pass this information from the server to the extender behavior.  Since we couldn't find a way to pass a list of values from the server to the behaviour using a generic List variable, we simply used a string of comma separated values.  Right now we're using this:

[ExtenderControlProperty]
[DefaultValue("")]
[Browsable(false)]
public string Values
{
    get { return GetPropertyValue("Values", ""); }
    set { SetPropertyValue("Values", value); }
}

But would much rather like to use the following: 

[ExtenderControlProperty]
[DefaultValue("")]
[Browsable(false)]
public List<string> Values
{
    get { return GetPropertyValue("Values", ""); }
    set { SetPropertyValue("Values", value); }
}

It appears generic lists are not supported, unless we are mistaken. If someone knows if this is possible, please leave us a comment on this post.

Don't forget to look at the online demo!

CheckBoxListHoverExtenderDemo.zip (469.00 kb)

kick it on DotNetKicks.com


Dirt Simple ASP.NET CMS using the ScrewTurn Wiki

clock January 22, 2008 00:08 by author JKealey

A year ago we wanted to quickly integrate the capabilities of a content management system in a customer’s website. Budget was limited but so were the requirements.

  • The user SHALL be able to change a few (a dozen) paragraphs on the website. 
  • The user SHALL be able to use basic formatting (bulleted lists, headers, images) without knowing HTML.

The lengthy option was the integration of a powerful CMS and the shorter one was to create something quickly using one of the many open source rich text editors found on the Internet and a simple database table. We didn’t really feel like coding that infrastructure at that point for various reasons. 

At this point, we were already a wiki for requirements management and task planning for this customer.  On very complex projects, we prefer TWiki because we had already used its metadata and form capabilities to make it easy to collaboratively work on software requirements back in 2005. However, we had installed the ScrewTurn wiki (an open source wiki in ASP.NET) for this customer, as its installation only takes a few seconds. We decided we would dynamically integrate content from our Wiki into our website, which was sufficient for our customer, for the time being.

We took a shorter lunch break that day and coded a dirt simple CMS application that queries the ScrewTurn wiki to obtain paragraphs of text. We simply made an HttpWebRequest to the printable version of the wiki page, cleaned out a bit of HTML markup that we did not need and cached the result. Using the control is then straightforward.

Register ScrewturnVisualizer in our Web.config (system.web, pages, controls):

<add tagPrefix="LB" assembly="LavaBlast" namespace=" LavaBlast.CustomControls" />

Add the base information in our Skin to avoid repeating it everywhere:

<LB:ScrewturnVisualizer runat="server" BaseURL="http://ourclientwiki.lavablast.com" CssClass="ScrewTurn" />

Add the control on the appropriate pages:

<LB:ScrewturnVisualizer ID="stv1" runat="Server" PageName="CurrentSpecials" />

Today, we’ve moved on to a full-fledged CMS and no longer use this code, but the attached code may still help someone out! We’re big fans of incremental engineering and this half hour of coding helped keep our clients happy while we moved to a better solution.

Side note: In terms of open source licences, I’ve always wondered what this would imply. ScrewTurn is GPL (as opposed to LGPL) and I’m curious to know if this would imply that websites using it as a simple CMS would have to be GPL as well. Because we’re making us of an online service (the code can quickly be adapted to work for any Wiki or other website) and not extending the codebase, I think we’re not bound by the GPL. Any thoughts?

ScrewturnVisualizer.zip (1.41 kb)

kick it on DotNetKicks.com


Using { and } in string.Format

clock January 16, 2008 14:02 by author EtienneT

Have you ever tried to use the { and } characters in the c# string.Format() method?  If you have, then you probably ran into a problem.  I'm posting this because this little Gotcha might not turn up until much later if your string formats are dynamically loaded from some external source, such as RESX files.

In any case, I sometimes find it useful to write some JavaScript code directly in C# and then dynamically insert it into the page with the ScriptManager.  Here is a quick example:



Basically, I write my JavaScript code on multiple lines with the @"" notation.  Then, I have to escape all { and } characters using {{ or }} otherwise string.Format will run into a System.FormatException: Input string was not in a correct format exception.  I can customize my JavaScript (or insert control.ClientID parameters) this way while retaining a readable format in the C# code.



Sample C# code for BeanStream credit card processing

clock October 26, 2007 16:11 by author JKealey

The other day we started looking at various credit card payment gateways in order to be able to process transactions on one of our client’s e-commerce sites. After reading up on a few alternatives, we hoped to be able to implement an easy all-in-one solution such as PayPal’s Website Payments Pro. Unfortunately, this program is not available in Canada. Apparently it will be some time soon, but we can’t wait on them for e-commerce, obviously.

After looking round a bit more, we found a payment gateway popularity contest and since we had seen a bunch of programming samples for Authorize.NET, it interested us. However, once again, Canadians cannot use this payment gateway. We looked at PSIGate the most popular one in Canada and were interested by their offering but, in the end, our client decided to go with BeanStream, another Canadian firm. BeanStream offers Electronic Funds Transfer programs (EFT) which is very useful for collecting royalties from franchisees. I may post something concerning EFT later in the year.

In any case, we were a bit disappointed that the site was not full of technical information, programming samples, SDKs, etc.  We had to contact them to obtain a copy of the documentation, something we would not have expected from a technical company in the days of Web 2.0. Having to contact them increases their contact base but shows a certain lack in openness, something which is gaining stream nowadays. The integration process seemed straightforward, as expected. Send out a request and get a response back. We were a bit surprised that the requests were encoded as you would encode a query string instead of XML with a freely available XSD/DTD. The sample code provided was dirt simple VBScript (ASP) with other technologies that we don’t use.

Some would call us lazy, but we feel that re-inventing the wheel is not a mission one should waste time on. Therefore, we started googling for freely available code for C# for payment processing using BeanStream, figuring that if the company itself doesn’t make this code available, someone must have posted an article on The Code Project or at least that we could find some code on Google Code Search. We found some PHP and some Perl, but since we code in C#, this code was not useful for us. Therefore, we started our implementation from scratch for our own purposes.

The code that follows is the current state of our implementation. It has not yet been tested in production, but our unit tests are working. We discovered a SOAP API after signing up and used that instead of the query string format.  We implemented a bit of parameter verification to make it easier to integrate with our higher level structures, which don’t have strict field lengths. Hopefully you’ll find this code useful and will let us know if you find any flaws. In our code, we've subclassed this base class to insert logging and conversion from our object-oriented data structures.

We found that the documentation was not very good, especially for the SOAP API. There were tons of mistakes and inconsistencies but, worst of all, the documentation was only available in a PDF format from which we cannot copy-paste. Therefore, the 500+ error messages or 100+ country codes cannot be easily exported to an Excel spreadsheet in order to create lookup tables in our database. We're building multi-lingual systems and don't have the time to translate their 500+ error messages, so we chose a simple solution as seen in the code. All errors (and exceptions in our code) are mapped to large encompassing classes. Fortunately, we were put in contact with VERY helpful people who responded extremely rapidly to our technical questions.

The source code follows. If you're interested, download the attached zip file containing the c# source code.

BeanStreamProcessing.zip (5.82 kb)

kick it on DotNetKicks.com


Month List

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2014

Sign in