Back to Top

A 2sxc Secret Revealed?

4/3/2022 News Blog
A 2sxc Secret Revealed?

"You have discovered a still hidden feature!!" - Daniel Mettler

We had a simple need, we wanted to show recent logins and user activity on a Dashboard (post-login landing) page. The context was simple, we were using 2sxc and just needed a simple, unstyled View to get the data/details on the page. You can see an example of the final output below, just plain text in a monospaced font.

Outputting successful login events was something we had done before years ago. I knew where the data was in the database and that the correct way to get to it was through the EventLogController. But here we are in 2022 and using DNN 9.10.02, so I jumped in to the docs to refresh on what  GetLogs() looked like and got stopped by the message,

[Obsolete("Deprecated in 9.8.0. Use Dependency Injection to resolve 'DotNetNuke.Abstractions.Logging.IEventLogService' instead. Scheduled for removal in v11.0.0.")]

I quickly verified that the old way still worked (always need a fallback plan). So I proceeded to try to figure out what the new way would be using DI. I stumbled and failed a bit. My excuses? I encountered a couple of issues with the DNN Docs site and was unable to get the code examples working that I found via Google. I didn't try too hard before I posted in the Slack DNN Community to see if someone else knew something or could direct me to a better (working) code example.

While playing with variations of the examples I had found, I also came across the Dependency Injection examples from 2sxc. They looked similar and I tried them out, and I quickly had used DI to get the 2sxc IPageService. Cool? So then I did something stupid. I simple copied the "IEventLogService" from the DNN code that was not working, into my 2sxc code like this:

var eventLogger = GetService<IEventLogService>();

I just wanted to see what would happen. Maybe I'd get an error that would give me a clue…

It worked. Wait, what? No seriously, it worked. But seriously, it was not supposed to work. 2sxc's GetService<>() method did not error and instead returned the DNN service/controller I was expecting. I was surprised, baffled, and curious. In a matter of minutes I had the code below working. You can try it yourself if you have DNN 9.4.4+ or higher and 2sxc v13.x or higher. Just make a new View, set the Data Model for "View doesn't need Data":

@inherits Custom.Hybrid.Razor12

@using ToSic.Razor.Blade;
@using DotNetNuke.Entities.Portals;
@using DotNetNuke.Entities.Users;
@using DotNetNuke.Abstractions.Logging;

  int totalRecords = 0;
  int pageSize = 10; @* updated per Mitch's comment below *@
  int pageIndex = 0;

  var eventLogger = GetService<IEventLogService>();

  foreach (var logInfo in eventLogger.GetLogs(CmsContext.Site.Id,
    pageSize, pageIndex, ref totalRecords)
    @* note that getting the DNN UserInfo like this hits the database and could cause performance issues for a large number of users *@
    var userInfo = getUser(logInfo.LogUserId);
    @Html.Raw(string.Format("<pre>{0,22} {1,24} &nbsp; {2}</pre>"
      , logInfo.LogCreateDate.ToString("G")
      , userInfo.DisplayName
      , Tags.Strip(logInfo.LogProperties.ToString())

  public UserInfo getUser(int userId)
    UserInfo userInfo = new UserController().GetUser(PortalSettings.Current.PortalId, userId);
    return userInfo;

So now what? How do I find out more? I checked the 2sxc docs and (at the time) there no obvious evidence supporting this. Do I post it as an Issue on the GitHub/2sxc project? How do you phrase, "hey, this is working, and shouldn't be, why?" Maybe StackOverflow? But its *not* not working.

So I emailed 2sxc and got this amazing response from Daniel Mettler:

"Hi Jeremy

You have discovered a still hidden feature 😉!!!!

Yes, we have integrated 2sxc with the Dnn DI completely, for a lot of reasons:

  1. If there are any Dnn services available, you can get them now. There are not that many yet, but it works.
  2. If you have dnn 9.4.4+ you can also now get 2sxc services in Dnn skins and modules! …"

Straight from the source. Daniel said the documentation is in progress and will be expanded soon probably starting here (C# Services) and here (DI in 2sxc and EAV). He also encouraged me to blog about it.

In this article I originally planned to talk through the workings a nice solution to displaying Login history and User activity on your DNN site using 2sxc, but I got a little sidetracked with this cool discovery which I hope you find useful or interesting. I'll be back with another blog soon where we'll stick to the original plan.

@* sample output 

3/28/2022 9:49:23 AM      Jeremy TestGather   IP :
3/28/2022 3:19:19 AM             Hank Moody   IP :
3/27/2022 8:13:32 PM       Jared TestManage   IP :
3/27/2022 5:12:23 PM         Amanda Tapping   IP :
3/25/2022 8:51:05 AM            Jeremy Host   IP :
3/25/2022 8:50:48 AM      Jeremy TestGather   IP : 
3/23/2022 4:55:32 PM          Carrie Fisher   IP : 
3/23/2022 1:53:53 PM       Jared TestManage   IP : 
3/23/2022 1:09:33 PM         Penny Robinson   IP : 
3/23/2022 12:56:32 PM     Jeremy TestGather   IP : 


Yes, I posted this on April 1st, but it is not a joke. Try it, you'll like it!!

Thanks: Daniel Mettler, and Josh Slaughter

Read more DNN Details posts... More about Accuraty...

‹ Back to List

With the design scheme of our new website, we feel that our visitors naturally take in more of the website and have more interest in exploring.

DEBUGGING OUTPUT (isDebug is true), WAN IP:

isIpSpecial() begins...
GetAllowedIps() begins...
GetAllowedIps() Found in cache; GetAllowedIps() completed with Count=7, List:,,,,,, 2601:41:c77f:7a0:4536:f8e4:9644:ca23
isIpSpecial() completed