Skip to main content
Home  ›  Blog

Deep DNN Skin and Module Integration - Towel Day 2022

2sxc 14 introduces better ways to render and integrate data/metadata in DNN Skins and Modules. 

WTF?

2sxc is usually used as a module to place on pages in DNN. But there are many other scenarios which it's used for, such as:

  1. Render a 2sxc module to the skin - like in the footer
  2. Use 2sxc data in the skin for additional page metadata
  3. ...or for page OpenGraph data
  4. Or for using the new CSP (Content Security Policy) features

Previously...

Previously code would use the static ToSic.Sxc.Dnn.Factory object to do this, but this was a really nasty architecture, because it worked against Dependency Injection as it should be used. 

New: this.GetScopedService<T>

But now that 2sxc 14 only supports DNN 9.6.1 or newer, we can finally do it right. This starts with a simple helper in Skins and Modules called this.GetScopedService<T>(). Just import the namespace ToSic.Sxc.Services first: 

<%-- This has all common 2sxc services and GetScopedService(...)  --%>
<%@ Import Namespace="ToSic.Sxc.Services" %>
<script runat="server">
  public int ToSafeInt(object value) {
    return this.GetScopedService<IConvertService>().ToInt(value, 0);
  }
</script>

This is just a shorthand. DNN has a more complicated way of doing this, but we believe this is more in line with what developers expect. Note that you must write this.GetScopedService<T>() (with the word this) because it's an extension method for System.Web.UI.UserControl. 

New: IRenderService

Using the GetScopedService you can now get the IRenderService to render the HTML of a 2sxc-module in any place in the skin, like this:

<%@ Import Namespace="ToSic.Sxc.Dnn" %>
<%@ Import Namespace="ToSic.Sxc.Services" %>
<%= this.GetScopedService<IRenderService>().Module(5279, 11228) %>

The IRenderService has many more commands - you can find them in the IRenderService docs

Note also that the PageId comes before the ModuleId.

New: IDynamicCodeService for Data and More

In cases where you need data / metadata from an App or additional commands like AsDynamic(...) you can use the IDynamicCodeService. It has ca. 10 methods to either get you a DynamicCode or an App. The difference is that an App is just the data, while the DynamicCode also has commands like AsDynamic etc.:

<%-- This namespace provides this.GetScopedService<T>() --%>
<%@ Import Namespace="ToSic.Sxc.Dnn" %>
<%-- This namespace provides all the common 2sxc services --%>
<%@ Import Namespace="ToSic.Sxc.Services" %>
<%-- This namespace provides IDynamicCode --%>
<%@ Import Namespace="ToSic.Sxc.Code" %>
<script runat="server">
  // Get the Dynamic Code of this Site = OfSite() and keep for re-use
  protected IDynamicCode SiteDynCode { 
    get { return _sdc ?? (_sdc = this.GetScopedService<IDynamicCodeService>().OfSite()); } 
  }
  private IDynamicCode _sdc;

  // Shorthand to Get a service using the SiteDynCode 
  // this will add context to services which need it
  protected T GetService<T>() {
    return SiteDynCode.GetService<T>();
  }

  // Get the PageToolbar to show somewhere using <%= PageToolbar() %>
  private object PageToolbar() {
    // Use GetService of the SiteDynCode so it can give the service more context
    var toolbarSvc = GetService<IToolbarService>();
    var page = SiteDynCode.CmsContext.Page;
    var pageTlb = toolbarSvc.Metadata(page);
    return SiteDynCode.Edit.Toolbar(pageTlb);
  }

  // Apply OpenGraph settings of the page
  private void SetOpenGraph() {
    // Use GetService of the SiteDynCode so it can give the service more context
    var pageSvc = GetService<IPageService>();
    var pageMd = SiteDynCode.CmsContext.Page.Metadata as dynamic;
    pageSvc.AddOpenGraph("og:type", pageMd.OgType);
    pageSvc.AddOpenGraph("og:title", pageMd.OgTitle);

    // Activate fancybox on all pages
    pageSvc.Activate("fancybox4");
  }
</script>

DynamicCode.GetService<T>()

Now there is a special edge case you need to know about. If you get the DynamicCode from the IDynamicCodeService it also has a GetScopedService<T>() method, similar to the one on Dnn. It can do the same things, but services created from there know more about the environment than the basic this.GetScopedService from before. 

For example, a service retrieved from a DynamicCode is able to retrieve site settings - which would be useful when creating Picture tags.

Love from Switzerland, 
iJungleboy


Daniel Mettler grew up in the jungles of Indonesia and is founder and CEO of 2sic internet solutions in Switzerland and Liechtenstein, an 20-head web specialist with over 800 DNN projects since 1999. He is also chief architect of 2sxc (see github), an open source module for creating attractive content and DNN Apps.

Read more posts by Daniel Mettler