#4 App.Data WebApi Examples
Error Showing Content - please login as admin for details.
In this example, we'll get app-data from the WebApi.
Click to see the result of a WebApi call with the shared code:
-
-
Result
@inherits Custom.Hybrid.Razor14
<button type="button" class="btn btn-primary" onclick="getPersons(this)">
Get Persons Custom
</button>
<button type="button" class="btn btn-primary" onclick="getPersonsAuto(this)">
Persons with Auto-Convert
</button>
<button type="button" class="btn btn-primary" onclick="getPersonsAutoPreserveCasing(this)">
Persons with Auto-Convert, preserve casing
</button>
<script>
function getPersons(moduleContext) {
$2sxc(moduleContext).webApi.fetchJson('books/persons')
.then(function(data) {
alert('Found ' + data.length + ' persons. \n'
+ 'The first one is "' + data[0].FirstName + ' ' + data[0].LastName + '"\n\n'
+ 'The raw JSON: \n' + JSON.stringify(data)
);
});
}
function getPersonsAuto(moduleContext) {
$2sxc(moduleContext).webApi.fetchJson('books/personsAuto')
.then(function(results) {
alert('On WebApi with Auto-Convert: Found ' + results.length + ' persons. \n'
+ 'The first one is "' + results[0].firstName + ' ' + results[0].lastName + '"\n\n'
+ 'The raw JSON: \n' + JSON.stringify(results)
);
});
}
function getPersonsAutoPreserveCasing(moduleContext) {
$2sxc(moduleContext).webApi.fetchJson('books/PersonsAutoPreserveCasing')
.then(function(results) {
alert('On WebApi with Auto-Convert: Found ' + results.length + ' persons. \n'
+ 'The first one is "' + results[0].FirstName + ' ' + results[0].LastName + '"\n\n'
+ 'The raw JSON: \n' + JSON.stringify(results)
);
});
}
</script>
Source Code of BooksController.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
using System.Linq; // this enables .Select(x => ...)
using ToSic.Sxc.WebApi; // For the [JsonFormatter] (see below)
using ToSic.Eav.DataFormats.EavLight; // For Auto-Conversion (see below)
[AllowAnonymous] // all commands can be accessed without a login
[ValidateAntiForgeryToken] // protects API from users not on your site (CSRF protection)
public class BooksController : Custom.Hybrid.Api14 // see https://r.2sxc.org/CustomWebApi
{
[HttpGet] // [HttpGet] says we're listening to GET requests
public object Persons()
{
// we could do: return App.Data["Persons"];
// but the raw data is difficult to use, so we'll improve it
// instead we'll create nice objects for our use
return AsList(App.Data["Persons"])
.Select(p => new {
Id = p.EntityId,
p.FirstName,
p.LastName,
Picture = p.Mugshot,
});
}
[HttpGet]
[JsonFormatter] // this will auto-convert Entities to JSON
public object PersonsAuto()
{
return App.Data["Persons"];
}
[HttpGet]
[JsonFormatter(Casing = Casing.Preserve)] // auto-convert but preserve casing
public object PersonsAutoPreserveCasing()
{
return App.Data["Persons"];
}
[HttpGet]
public object Books()
{
return AsList(App.Data["Books"])
.Select(b => new {
Id = b.EntityId,
b.Title,
b.Cover,
Awards = AsList(b.Awards as object)
.Select(a => a.EntityTitle)
});
}
}
// The next line is for 2sxc-internal quality checks, you can ignore this
// 2sxclint:disable:no-dnn-namespaces - 2sxclint:disable:no-web-namespace
In this example, we'll get app-data from the WebApi.
Click to see the result of a WebApi call with the shared code:
-
-
Result
@inherits Custom.Hybrid.Razor14
<button type="button" class="btn btn-primary" onclick="getBooks(this)">
Get Books Custom
</button>
<script>
function getBooks(moduleContext) {
$2sxc(moduleContext).webApi.fetchJson('books/books')
.then(function(results) {
alert('Found ' + results.length + ' books. \n'
+ 'The first one is "' + results[0].Title + '"\n\n'
+ 'The raw JSON: \n' + JSON.stringify(results)
);
});
}
</script>
Source Code of BooksController.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
using System.Linq; // this enables .Select(x => ...)
using ToSic.Sxc.WebApi; // For the [JsonFormatter] (see below)
using ToSic.Eav.DataFormats.EavLight; // For Auto-Conversion (see below)
[AllowAnonymous] // all commands can be accessed without a login
[ValidateAntiForgeryToken] // protects API from users not on your site (CSRF protection)
public class BooksController : Custom.Hybrid.Api14 // see https://r.2sxc.org/CustomWebApi
{
[HttpGet] // [HttpGet] says we're listening to GET requests
public object Persons()
{
// we could do: return App.Data["Persons"];
// but the raw data is difficult to use, so we'll improve it
// instead we'll create nice objects for our use
return AsList(App.Data["Persons"])
.Select(p => new {
Id = p.EntityId,
p.FirstName,
p.LastName,
Picture = p.Mugshot,
});
}
[HttpGet]
[JsonFormatter] // this will auto-convert Entities to JSON
public object PersonsAuto()
{
return App.Data["Persons"];
}
[HttpGet]
[JsonFormatter(Casing = Casing.Preserve)] // auto-convert but preserve casing
public object PersonsAutoPreserveCasing()
{
return App.Data["Persons"];
}
[HttpGet]
public object Books()
{
return AsList(App.Data["Books"])
.Select(b => new {
Id = b.EntityId,
b.Title,
b.Cover,
Awards = AsList(b.Awards as object)
.Select(a => a.EntityTitle)
});
}
}
// The next line is for 2sxc-internal quality checks, you can ignore this
// 2sxclint:disable:no-dnn-namespaces - 2sxclint:disable:no-web-namespace
-
-
Result
@inherits Custom.Hybrid.Razor14
<button type="button" class="btn btn-primary" onclick="getPersons(this)">
Get Persons Custom
</button>
<script>
function getPersons(moduleContext) {
$2sxc(moduleContext).webApi.fetchJson('books/persons')
.then(function(data) {
alert('Found ' + data.length + ' persons. \n'
+ 'The first one is "' + data[0].FirstName + ' ' + data[0].LastName + '"\n\n'
+ 'The raw JSON: \n' + JSON.stringify(data)
);
});
}
</script>
Source Code of BooksController.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
using System.Linq; // this enables .Select(x => ...)
using ToSic.Sxc.WebApi; // For the [JsonFormatter] (see below)
using ToSic.Eav.DataFormats.EavLight; // For Auto-Conversion (see below)
[AllowAnonymous] // all commands can be accessed without a login
[ValidateAntiForgeryToken] // protects API from users not on your site (CSRF protection)
public class BooksController : Custom.Hybrid.Api14 // see https://r.2sxc.org/CustomWebApi
{
[HttpGet] // [HttpGet] says we're listening to GET requests
public object Persons()
{
// we could do: return App.Data["Persons"];
// but the raw data is difficult to use, so we'll improve it
// instead we'll create nice objects for our use
return AsList(App.Data["Persons"])
.Select(p => new {
Id = p.EntityId,
p.FirstName,
p.LastName,
Picture = p.Mugshot,
});
}
[HttpGet]
[JsonFormatter] // this will auto-convert Entities to JSON
public object PersonsAuto()
{
return App.Data["Persons"];
}
[HttpGet]
[JsonFormatter(Casing = Casing.Preserve)] // auto-convert but preserve casing
public object PersonsAutoPreserveCasing()
{
return App.Data["Persons"];
}
[HttpGet]
public object Books()
{
return AsList(App.Data["Books"])
.Select(b => new {
Id = b.EntityId,
b.Title,
b.Cover,
Awards = AsList(b.Awards as object)
.Select(a => a.EntityTitle)
});
}
}
// The next line is for 2sxc-internal quality checks, you can ignore this
// 2sxclint:disable:no-dnn-namespaces - 2sxclint:disable:no-web-namespace
-
-
Result
@inherits Custom.Hybrid.Razor14
<button type="button" class="btn btn-primary" onclick="getPersonsAutoPreserveCasing(this)">
Persons with Auto-Convert, preserve casing
</button>
<script>
function getPersonsAutoPreserveCasing(moduleContext) {
$2sxc(moduleContext).webApi.fetchJson('books/PersonsAutoPreserveCasing')
.then(function(results) {
alert('On WebApi with Auto-Convert: Found ' + results.length + ' persons. \n'
+ 'The first one is "' + results[0].FirstName + ' ' + results[0].LastName + '"\n\n'
+ 'The raw JSON: \n' + JSON.stringify(results)
);
});
}
</script>
Source Code of BooksController.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
using System.Linq; // this enables .Select(x => ...)
using ToSic.Sxc.WebApi; // For the [JsonFormatter] (see below)
using ToSic.Eav.DataFormats.EavLight; // For Auto-Conversion (see below)
[AllowAnonymous] // all commands can be accessed without a login
[ValidateAntiForgeryToken] // protects API from users not on your site (CSRF protection)
public class BooksController : Custom.Hybrid.Api14 // see https://r.2sxc.org/CustomWebApi
{
[HttpGet] // [HttpGet] says we're listening to GET requests
public object Persons()
{
// we could do: return App.Data["Persons"];
// but the raw data is difficult to use, so we'll improve it
// instead we'll create nice objects for our use
return AsList(App.Data["Persons"])
.Select(p => new {
Id = p.EntityId,
p.FirstName,
p.LastName,
Picture = p.Mugshot,
});
}
[HttpGet]
[JsonFormatter] // this will auto-convert Entities to JSON
public object PersonsAuto()
{
return App.Data["Persons"];
}
[HttpGet]
[JsonFormatter(Casing = Casing.Preserve)] // auto-convert but preserve casing
public object PersonsAutoPreserveCasing()
{
return App.Data["Persons"];
}
[HttpGet]
public object Books()
{
return AsList(App.Data["Books"])
.Select(b => new {
Id = b.EntityId,
b.Title,
b.Cover,
Awards = AsList(b.Awards as object)
.Select(a => a.EntityTitle)
});
}
}
// The next line is for 2sxc-internal quality checks, you can ignore this
// 2sxclint:disable:no-dnn-namespaces - 2sxclint:disable:no-web-namespace
In this example, we'll get app-data from the WebApi which runs a query with a parameter.
Click to see the result of a WebApi call with the shared code:
-
-
Result
@inherits Custom.Hybrid.Razor14
@{
var authorId = AsDynamic(App.Data["Persons"].First()).EntityId;
}
<button type="button" class="btn btn-primary" onclick="getAuthor(this, @authorId)">
Get Author #@authorId
</button>
<script>
function getAuthor(moduleContext, authorId) {
$2sxc(moduleContext).webApi.fetchJson('authorsquery/get?authorId=' + authorId)
.then(function (author) {
alert('Found author: '
+ author.FirstName + ' ' + author.LastName
+ ' (with ' + author.Books.length + ' books) \n\n'
+ 'The raw JSON: \n' + JSON.stringify(author)
);
});
}
</script>
Source Code of AuthorsQueryController.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
using System.Linq; // this enables .First() or .Select(x => ...)
// Tutorial note: This is used in the WebApi demos for Querying App Data
[AllowAnonymous] // all commands can be accessed without a login
[ValidateAntiForgeryToken] // protects API from users not on your site (CSRF protection)
public class AuthorsQueryController : Custom.Hybrid.Api14 // see https://r.2sxc.org/CustomWebApi
{
[HttpGet] // [HttpGet] says we're listening to GET requests
public object Get(int authorId)
{
var query = Kit.Data.GetQuery("AuthorsWithBooks", parameters: new {
AuthorId = authorId
});
var a = AsDynamic(query["Current"].First());
return new {
Id = a.EntityId,
a.FirstName,
a.LastName,
Picture = a.Mugshot,
Books = AsList(query["CurrentBooks"])
.Select(b => new {
Id = b.EntityId,
b.Title
})
};
}
}
// The next line is for 2sxc-internal quality checks, you can ignore this
// 2sxclint:disable:no-dnn-namespaces - 2sxclint:disable:no-web-namespace
This is an advanced implementation of the basic examples before. It uses #if
statements to ensure that the same code can run in Dnn and Oqtane.
Click to see the result of a WebApi call with the shared code:
-
-
Result
@inherits Custom.Hybrid.Razor14
@* Make sure anonymous users have the 2sxc JS API *@
@Kit.Page.Activate("2sxc.JsCore")
<button type="button" class="btn btn-primary" onclick="callBasicHello(this)">
Get Hello
</button>
<script>
function callBasicHello(moduleContext) {
$2sxc(moduleContext).webApi.fetchJson('app/auto/api/hybrid/hello')
.then(function (results) { alert(results); });
}
</script>
Source Code of HybridController.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.
using Oqtane.Shared; // Oqtane role names for [Authorize]
#else
using System.Web.Http; // .net 4.5 [AllowAnonymous] / [HttpGet]
using DotNetNuke.Web.Api; // [DnnModuleAuthorize] & [ValidateAntiForgeryToken]
using DotNetNuke.Security; // DnnRoles for SecurityAccessLevel.Anonymous
#endif
#if NETCOREAPP
[Produces("application/json")] // Ensures that strings are JSON and have quotes around them in .net 5
#endif
[AllowAnonymous] // all commands can be accessed without a login
public class HybridController : Custom.Hybrid.Api14 // see https://r.2sxc.org/CustomWebApi
{
[AllowAnonymous] // Explicitly set for this method
[HttpGet] // [HttpGet] says we're listening to GET requests
public string Hello()
{
return "Hello from the basic controller in /api";
}
#if OQTANE
[Authorize(Roles = RoleNames.Everyone)] // Oqtane authorize everyone / anonymous
#else
[DnnModuleAuthorize(AccessLevel = SecurityAccessLevel.Anonymous)] // Dnn equivalent
#endif
[HttpGet] // [HttpGet] says we're listening to GET requests
public int Square(int number)
{
return number * number;
}
}
// The next line is for 2sxc-internal quality checks, you can ignore this
// 2sxclint:disable:no-dnn-namespaces - 2sxclint:disable:no-web-namespace
This is an advanced implementation of the basic examples before. It uses #if
statements to ensure that the same code can run in Dnn and Oqtane.
Click to see the result of a WebApi call with the shared code:
-
-
Result
@inherits Custom.Hybrid.Razor14
@* Make sure anonymous users have the 2sxc JS API *@
@Kit.Page.Activate("2sxc.JsCore")
<button type="button" class="btn btn-primary" onclick="callSquare(this, 7)">
Square 7
</button> <button type="button" class="btn btn-primary" onclick="callSquare(this, 27)">
Square 27
</button>
<script>
function callSquare(moduleContext, original) {
$2sxc(moduleContext).webApi.fetchJson('app/auto/api/hybrid/square?number=' + original)
.then(function (results) { alert(results); });
}
</script>
Source Code of HybridController.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.
using Oqtane.Shared; // Oqtane role names for [Authorize]
#else
using System.Web.Http; // .net 4.5 [AllowAnonymous] / [HttpGet]
using DotNetNuke.Web.Api; // [DnnModuleAuthorize] & [ValidateAntiForgeryToken]
using DotNetNuke.Security; // DnnRoles for SecurityAccessLevel.Anonymous
#endif
#if NETCOREAPP
[Produces("application/json")] // Ensures that strings are JSON and have quotes around them in .net 5
#endif
[AllowAnonymous] // all commands can be accessed without a login
public class HybridController : Custom.Hybrid.Api14 // see https://r.2sxc.org/CustomWebApi
{
[AllowAnonymous] // Explicitly set for this method
[HttpGet] // [HttpGet] says we're listening to GET requests
public string Hello()
{
return "Hello from the basic controller in /api";
}
#if OQTANE
[Authorize(Roles = RoleNames.Everyone)] // Oqtane authorize everyone / anonymous
#else
[DnnModuleAuthorize(AccessLevel = SecurityAccessLevel.Anonymous)] // Dnn equivalent
#endif
[HttpGet] // [HttpGet] says we're listening to GET requests
public int Square(int number)
{
return number * number;
}
}
// The next line is for 2sxc-internal quality checks, you can ignore this
// 2sxclint:disable:no-dnn-namespaces - 2sxclint:disable:no-web-namespace
#4 App.Data WebApi Examples