Output
<button type="button" class="btn btn-primary" onclick="callBasicHello(this, 'live')">
Get Hello from live
</button>
<button type="button" class="btn btn-primary" onclick="callBasicHello(this, 'dev')">
Get Hello from dev
</button>
@* 2sxclint:disable:no-inline-script *@
<script>
function callBasicHello(moduleContext, edition) {
$2sxc(moduleContext).webApi.fetchJson('app/auto/' + edition + '/api/demo/hello')
.then(data => alert(data));
}
</script>
Source Code of ../live/api/DemoController.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 DemoController : Custom.Hybrid.Api14 // see https://r.2sxc.org/CustomWebApi
{
[HttpGet]
public string Hello()
{
return "Hello from the live controller";
}
}
// 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 ../dev/api/DemoController.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 DemoController : Custom.Hybrid.Api14 // see https://r.2sxc.org/CustomWebApi
{
[HttpGet]
public string Hello()
{
return "Hello from the staging controller - we're still developing this, so you may see errors. Once it's tested, we'll copy this to /live/api/ so the public users will see this too.";
}
}
// The next line is for 2sxc-internal quality checks, you can ignore this
// 2sxclint:disable:no-dnn-namespaces - 2sxclint:disable:no-web-namespace
@inherits Custom.Hybrid.Razor14
<!-- unimportant stuff, hidden -->
<div @Sys.PageParts.InfoWrapper()>
@Html.Partial("../shared/DefaultInfoSection.cshtml")
<div @Sys.PageParts.InfoIntro()>
<h2>WebApi with Polymorph Editions</h2>
<p>
You often need to make changes on a live site (open-heart-surgery) without affecting the users. For this, you should have two copies of the API Controller - one live, and one staging. This is done by doing the following:
</p>
<ol>
<li>Place the live, tested controller in <code>/live/api/</code> and make sure your JavaScript accesses this</li>
<li>Place a copy in <code>/staging/api/</code> or something similar (you can use other path names as well) and make your development JavaScript access that endpoint</li>
<li>Then you can develop without hurting the live output.</li>
<li>Once it's stable, you then deploy by copying the new controller to <code>/live/api/</code></li>
</ol>
<p>
Click to see the result of the two calls, one to live, one to staging:
</p>
</div>
</div>
<button type="button" class="btn btn-primary" onclick="callBasicHello(this, 'live')">
Get Hello from live
</button>
<button type="button" class="btn btn-primary" onclick="callBasicHello(this, 'dev')">
Get Hello from dev
</button>
@* 2sxclint:disable:no-inline-script *@
<script>
function callBasicHello(moduleContext, edition) {
$2sxc(moduleContext).webApi.fetchJson('app/auto/' + edition + '/api/demo/hello')
.then(data => alert(data));
}
</script>
@* Footer *@
@Html.Partial("../Shared/Layout/FooterWithSource.cshtml", new { Sys = Sys })