Skip to main content
Home  › ... Razor
Error Showing Content - please login as admin for details.
Error Showing Content - please login as admin for details.
The samples can differ based on your Razor base class or if you're running an old version.
Switch to Strong-Typed (2sxc 17.06+) Selected: Typed (2sxc 16+) Switch to Dynamic (Razor14 or below)
Error Showing Content - please login as admin for details.

The example takes a cshtml file using GetCode(...)and uses it as a central helpers library. The helper PreviewWithLightbox will generate a thumbnail, include Fancybox3 (only the first time) and ensure you can click it for a full image.

⬇️ Result | Source ➡️


@inherits Custom.Hybrid.RazorTyped

@{
  // Use GetCode in RazorTyped and path which is either
  // - absolute to App root
  // - relative to current file
  var lightbox = GetCode("./Fancybox.cs");
}
@* Url to app root folder is in App.Folder.Url *@
@lightbox.PreviewWithLightbox(App.Folder.Url + "/app-icon.png")
<br>
@lightbox.PreviewWithLightbox(App.Folder.Url + "/assets/img-resize/basic-banner.png", 200, 100)

Source Code of Fancybox.cs

using ToSic.Razor.Blade;

public class Fancybox: Custom.Hybrid.CodeTyped
{
  // Create an image which opens a larger version in a lightbox
  public IHtmlTag PreviewWithLightbox(string url, int width = 100, int height = 100, string classes = "", string label = null)
  {
    // Add fancybox JS to the page (will only add once, no matter how often it's called)
    Kit.Page.Activate("fancybox4"); 

    var imgResizeSettings = Kit.Image.Settings(width: width, height: height);
    var imgOrPic = Kit.Image.Img(url, settings: imgResizeSettings);
    // Create the link tag with the image inside
    var html = Kit.HtmlTags.A()
      .Data("fancybox", "gallery")
      .Href(url)
      .Class(classes)
      .Data("caption", label)
      .Wrap(imgOrPic);

    return html;
  }
}

When you need a function in many places, it's best to put it into an own cs file.

The example takes a cshtml file with a QrPath function returning the url to a qr-code. It then accesses it using GetCode(...).

⬇️ Result | Source ➡️

Hello from lib: Hello!
@inherits Custom.Hybrid.RazorTyped
@using ToSic.Razor.Blade

@{
  // Use GetCode in RazorTyped
  var lib = GetCode("../../shared/SharedFunctions.cs");
}
<div>Hello from lib: @lib.SayHello()</div>
<div>
  <img loading="lazy" src='@lib.QrPath("https://2sxc.org")' width="75px">
</div>

Source Code of SharedFunctions.cs

public class SharedFunctions: Custom.Hybrid.Code14 {

  public string SayHello() {
    return "Hello!";
  }

  public string QrPath(string link) {
    // path to qr-code generator
    var qrPath = "//api.qrserver.com/v1/create-qr-code/?color={foreground}&bgcolor={background}&qzone=0&margin=0&size={dim}x{dim}&ecc={ecc}&data={link}"
      .Replace("{foreground}", App.Settings.QrForegroundColor.Replace("#", ""))
      .Replace("{background}", App.Settings.QrBackgroundColor.Replace("#", ""))
      .Replace("{dim}", App.Settings.QrDimension.ToString())
      .Replace("{ecc}", App.Settings.QrEcc)
      .Replace("{link}", link);
    return qrPath;
  }

}
Error Showing Content - please login as admin for details.

The example takes a cs file with shared code, but gets the class Second.

⬇️ Result | Source ➡️

Hello from FunctionsBasic: Hello from the second class!
@inherits Custom.Hybrid.RazorTyped

@{
  var lib = GetCode("../../shared/FunctionsBasic.cs", className: "Second");
}
<div>Hello from FunctionsBasic: @lib.SayHello()</div>

Source Code of FunctionsBasic.cs

// Important notes: 
// - This class should have the same name as the file it's in
public class FunctionsBasic {

  public string SayHello() {
    return "Hello from shared functions!";
  }
}

// Example for another class in the same file
public class Second {
  public string SayHello() {
    return "Hello from the second class!";
  }
}

Often you may need context - like the Dnn or App objects. We made this easy by defining a base class you can inherit from, called Custom.Hybrid.Code14 (previously ToSic.Sxc.Dnn.DynamicCode). If you use that as your base-class, all existing context is automatically attached, allowing you to access variables like App.

⬇️ Result | Source ➡️

@inherits Custom.Hybrid.RazorTyped

@{
  var powerLib = GetCode("FunctionsWithContext.cs");
}
<div>
  <img loading="lazy" src='@powerLib.QrPath("https://2sxc.org")' width="75px">
</div>

Source Code of FunctionsWithContext.cs

// Important notes: 
// - This class should have the same name as the file it's in
// - This inherits from Custom.Hybrid.Code14
//   which will automatically provide the common objects like App, Dnn etc.
//   from the current context to use in your code
public class FunctionsWithContext: Custom.Hybrid.Code14 {

  public string QrPath(string link) {
        // path to qr-code generator
        var qrPath = "//api.qrserver.com/v1/create-qr-code/?color={foreground}&bgcolor={background}&qzone=0&margin=0&size={dim}x{dim}&ecc={ecc}&data={link}"
            .Replace("{foreground}", App.Settings.QrForegroundColor.Replace("#", ""))
            .Replace("{background}", App.Settings.QrBackgroundColor.Replace("#", ""))
            .Replace("{dim}", App.Settings.QrDimension.ToString())
            .Replace("{ecc}", App.Settings.QrEcc)
            .Replace("{link}", link)
            ;
        return qrPath;
    }

}

The mechanism above also works in WebApi Controllers (if you have 2sxc 10.01+). Note that specifically in WebApi you can only use GetCode(...) for .cs files.

⬇️ Result | Source ➡️

Click to see the result of a WebApi call with the shared code:

@inherits Custom.Hybrid.RazorTyped
@using ToSic.Razor.Blade

<p>
  Click to see the result of a WebApi call with the shared code:
  <button type="button" class="btn btn-primary" onclick="callApiWithSharedCode(this)">
    Call WebApi
  </button>
</p>

<script>
  function callApiWithSharedCode(context) {
    $2sxc(context).webApi.fetchJson('app/auto/api/sharedcode/hello')
      .then(function (results) {
        console.log(results);
        alert(results);
      });
    return false;
  }
</script>

Source Code of SharedCodeController.cs

// Add namespaces for security check in Oqtane & DNN despite differences in .net core/.net Framework
// If you only target one platform, you can remove the parts you don't need
#if NETCOREAPP
using Microsoft.AspNetCore.Authorization; // .net core [AllowAnonymous] & [Authorize]
using Microsoft.AspNetCore.Mvc;           // .net core [HttpGet] / [HttpPost] etc.
#else
using System.Web.Http;                    // .net 4.5 [AllowAnonymous] / [HttpGet]
using DotNetNuke.Web.Api;                 // [DnnModuleAuthorize] & [ValidateAntiForgeryToken]
#endif

[AllowAnonymous]                          // all commands can be accessed without a login
[ValidateAntiForgeryToken]                // protects API from users not on your site (CSRF protection)
public class SharedCodeController : Custom.Hybrid.Api14 // see https://r.2sxc.org/CustomWebApi
{
  [HttpGet]
  [AllowAnonymous]
  public string Hello()
  {
    var shared = CreateInstance("../shared/FunctionsBasic.cs");
    return shared.SayHello();
  }
}

// The next line is for 2sxc-internal quality checks, you can ignore this
// 2sxclint:disable:no-dnn-namespaces - 2sxclint:disable:no-web-namespace

Source Code of FunctionsBasic.cs

// Important notes: 
// - This class should have the same name as the file it's in
public class FunctionsBasic {

  public string SayHello() {
    return "Hello from shared functions!";
  }
}

// Example for another class in the same file
public class Second {
  public string SayHello() {
    return "Hello from the second class!";
  }
}