• Login
  • Register

DNN Blogs

Written for the Community, by the Community

Integrating 2sxc with Other Modules

Written By Joe Craig

I built a website that is a directory of ukulele related events in the Baltimore area. 

I started fairly simply:  I planned to use NA Development's Event Planner & Registration module.  Yes, it's a commercial module, but it's one I have used in the past, is quite full featured, and has some features that aren't present in the DNN Events module.  The main attraction to using this module is that it supports multiple event types, categories, locations, choices for event times, and ... you get the picture.  It also lets you create templates for data display that can be written in Razor, somthing that is appealing to me because data display almost always benefits from some programming.

As I got into the project, I realized that there were some things that I wanted to do that required a bit more than the module provided me.  Another way of saying this is that I wanted complete flexibility to display data, and that wasn't easily done within the confines of the module.

I could do what I wanted using Razor, so I was drawn to creating a 2sxc App do do the data display.  Since I didn't want to write or adapt a full function calendar, I wondered if I could use the Event Planner module for data entry and maintenance, and use 2sxc for the presentation part.  It turns out that I could!

Getting the Data

It turns out that NA Development does very good support (and Nigel Allen deserves a big shout out!).  All that I needed to do was call a method from the Event Planner module, and I could get all of the events that I needed:

IList<Event> events = EventController.GetAllEventsOrderedWithRecurringEvents(moduleId, portalId, EventPlannerSettings.HideEventWhenFullyBooked)
        .Where(x => x.EventStartDate >= thisMorning && x.EventEndDate<= tomorrow)
        .OrderBy(x => x.EventStartDate)

I separated  the events into three groups and each group had it's own display.

    var todayDate = DateTime.Today;
    var todayEvents = events.Where(x => x.EventStartDate.Date <= todayDate && x.EventEndDate.Date >= todayDate );
    var featureDate = events.Where(x => x.EventStartDate.Date > todayDate).First().EventStartDate.Date;
    var featuredEvents = events.Where(x => x.EventStartDate.Date == featureDate );
    var futureEvents = events.Where(x => x.EventStartDate.Date > featureDate );

The first group shows events happening today. 

The second shows the events happening on the next date after today for which there are events. 

Finally, third group is all events happening after the second group.  This is displayed as a table, as the list is a long one.

Later, I  needed a fourth grouping for UkeFests.  These typically are weekend long gatherings and have a longer time frame for registration for attendees.  With the current covid-19 situation, many such events have been cancelled, and are being reschuled for next year.  So, I needed to include another year in my search for events.  So, I changed the end date for my search for UkeFests:

DateTime endDate = startDate.AddYears(2);

Displaying the Data

With the data retrieved, displaying it is quite easy.  All that I need is a foreach look to display each event in the diffferent groups.  This is what it looks like for the events that occur today:

    foreach( var ev in todayEvents ){

        <div class="row featuredEvent">
            <div class ="col-md-6">
                <img src="@GetEventImageUrl(ev)?w=350&h=250&mode=crop&scale=both" class="img-fluid"/>
            <div class="col-md-6 align-self-center">
                <a href="@ev.ExternalRegistrationUrl" target="_blank">@ev.EventName</a><br>
                @ev.EventStartDate.ToString("MM/dd/yy") <br>
                <div style="display:none">@ev.EventEndDate.ToString("MM/dd/yy")</div>
                @foreach( var loc in @ev.GetEventLocations(startDate,endDate) ){
                    if(!String.IsNullOrEmpty(@loc.City)){@loc.City<text>, </text>@loc.Region}

Notice how the events are returned as objects, and each object's fields correspond to the details returned from Event Planner.

For the UkeFests, I need to identify only the events categorize as such.  This is taken care of in the Event Planner module, and I have classes like Jam/Strum, Concert, UkeFest and so on.  These days, pretty much all local events are cancelled, but there are many online events.  So, I created an Online category.  Anyway, my UkeFest display adds a condition to display only those events:

    @foreach( var ev in events ){
        if( IsUkeFest(ev) )
            <div class ="col-md-3 pt-4">
                <a href="@ev.ExternalRegistrationUrl" target="_blank">
                    @if( !String.IsNullOrEmpty(GetEventImageUrl(ev)) ){
                        <img src="@GetEventImageUrl(ev)?w=400&mode=crop&scale=both" class="img-fluid"
                        title="@ev.EventName  @ev.EventStartDate.ToShortDateString()[email protected]()" alt="@ev.EventName"/>
                    else{ @ev.EventName }


Supporting Code

I created a couple of bits of code to simplify retrieving some items.

An event can be assigned to more than one category.  So, I have to iterate over category names to identify UkeFests.

    bool IsUkeFest( Event theEvent)
        foreach( var evcat in theEvent.GetCategories() )
            if( evcat.CategoryName == "UkeFest" ){ return true; }
        return false;

Events can have more than one image.  So, I select only the first one for display.

        string GetEventImageUrl( Event theEvent){
        var eventImages=theEvent.GetImages();
        var eventImageUrl = "";
        if( eventImages.Count > 0) {
            eventImageUrl = eventImages[0].ImageUrl;
        return eventImageUrl;


I have found the jQuery DataTables plug-in to be very useful for data displays that require tables.  My "further along" (future) events uses a DataTable.  In code, it's rendered as a table, and then DataTables takes it over.  I can control the number of rows it displays, it is paginated, and the search box searches the entire table.

On another site, I used the DNN IsInRole methode to control which columns are displayed.  I also added an Export to Excel button.  So, administrators can see one thing and download the data, but the "protected" columns are not rendered to non-admin viewers.

Data Entry

This item really belongs at the beginning.  I use Event Planner's event management tools and UI to manage all of the events.  I can use every feature in the module to create events.  But, I'm now using 2sxc to display the events in ways that I need them.  This is the very best of all worlds.


Getting data directly out of other modules and into 2sxc opens up a world of possibilities.  This approach is now a new power tool in my DNN Toolbox.  I have also used this technique to get data out of NA Development's Cart Viper e-commerce product. The client for that site was using Cart Viper, but needed some special reports -- not available in Cart Viper -- so I did those in 2sxc using methods from Cart Viper to find and deliver the necessary data to me.

For other modules, you can do the same kinds of things.  If the module doesn't have the necessary tools to retrieve the data that you need, you can also use 2sxc's data source tools.  I've used the SQL Data Source, and it works great.

And here is an invitation:  If you've used any cool features available in 2sxc, why not blog about them.  Or cool features in any other module.

Total: 2 Comment(s)
Awesome stuff, Joe! Thanx for sharing, very inspiring!
Friday, April 10, 2020 ·
Hey this is really cool - thanks Joe! BTW: I'm just releasing 2sxc 11 now, and I think you'll love the new CodeBehind feature. I'll blog about it in 3-4 days 😎
Monday, May 4, 2020 ·

Would you like to help us?

Awesome! Simply post in the forums using the link below and we'll get you started.

Get Involved