Skip to main content
Home  › ... Razor

WebApi Tutorials

Tutorial HomeWebApi

App.Data WebApi Examples

In this example, we'll get app-data from the WebApi.

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

Important: WebApi using [JsonFormatter] 🆕 in 2sxc 16
The [JsonFormatter] has a few effects. It auto-defaults to camelCase (but you can modify this if you need to preserve casing). It will also auto-convert entities to a standard JSON format.

Output



<button type="button" class="btn btn-primary" onclick="getPersons(this)">
  Get Persons Custom
</button> 
<button type="button" class="btn btn-primary" onclick="getBooks(this)">
  Get Books Custom
</button>
<br>
<br>
<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> 
  @* 2sxclint:disable:no-inline-script *@
<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 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)
          );
      });
  }
  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 ../api/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 dynamic 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 dynamic PersonsAuto()
  {
    return App.Data["Persons"];
  }

  [HttpGet]
  [JsonFormatter(Casing = Casing.Preserve)] // auto-convert but preserve casing
  public dynamic PersonsAutoPreserveCasing()
  {
    return App.Data["Persons"];
  }
  

  [HttpGet]
  public dynamic 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

Source Code of this file

Below you'll see the source code of the file. Note that we're just showing the main part, and hiding some parts of the file which are not relevant for understanding the essentials. Click to expand the code

@inherits Custom.Hybrid.Razor14
<!-- unimportant stuff, hidden -->

<div @Sys.PageParts.InfoWrapper()>
  @Html.Partial("../shared/DefaultInfoSection.cshtml")
  <div @Sys.PageParts.InfoIntro()>
      <h2>App.Data WebApi Examples</h2>
      <p>In this example, we'll get app-data from the WebApi.</p>

      <p>Click to see the result of a WebApi call with the shared code:</p>

      @Html.Partial("./Part NowUsingJsonFormatter.cshtml")
  </div>
</div>

  <button type="button" class="btn btn-primary" onclick="getPersons(this)">
    Get Persons Custom
  </button> 
  <button type="button" class="btn btn-primary" onclick="getBooks(this)">
    Get Books Custom
  </button>
  <br>
  <br>
  <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> 
    @* 2sxclint:disable:no-inline-script *@
  <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 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)
            );
        });
    }
    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>



@* Footer *@
@Html.Partial("../Shared/Layout/FooterWithSource.cshtml", new { Sys = Sys })