App


WebAPI and REST Tutorials

Tutorial HomeWebApi and REST
#2 WebAPI Basics: Call WebAPIs and REST using JavaScript

WebAPI Basics: Call WebAPIs and REST using JavaScript

Very Basic WebAPI Samples

In this example, we'll assume your WebApi controller is called Basic (so the file is called BasicController.cs and has a class called BasicController). It's located in /api which is the default location for WebApi controllers.
We'll show various usages both with the new webApi.fetchJson(...) and webApi.fetch(...) standard fetch

  1. with the new webApi.fetchJson(...) and webApi.fetch(...) commands (new in v12.10)
  2. with the browser built in fetch
  3. using jQuery (not recommended any more, because we believe jQuery is dying)
  4. another example calling the endpoint using a parameter to calculate something so you can see how to use url parameters.

⬇️ Result | Source ➡️

@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="helloFetchJson(this)">
  Quick Fetch Json "Hello"
  </button>
  
<script>
  // Fetch using modern Browser Fetch-promises, with auto-get Json
  // This is the recommended method if you expect JSON, because it's simpler
  // This also uses the shortest API syntax `controller/method`
  function helloFetchJson(moduleContext) {
    $2sxc(moduleContext).webApi
    .fetchJson('basic/hello')
      .then(data => alert('Result using quick Fetch JSON: ' 
      + data));
  }
</script>

Source Code of BasicController.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
public class BasicController : Custom.Hybrid.Api14 // see https://r.2sxc.org/CustomWebApi
{
  [HttpGet]                               // [HttpGet] says we're listening to GET requests
  public string Hello()
  {
    return "Hello from the basic controller in /api";
  }

  [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

Note about Hybrid APIs

These examples are all done to work in both Dnn ☢️ and Oqtane 💧. Because of this, the Api Controller have special conditional statements like #if NETCOREAPP which uses different namespaces in .net core and .net Framework.
If you only target Dnn or Oqtane, you can remove the lines you don't need. See See how to use #if

⬇️ Result | Source ➡️

@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="helloFetch(this)">
  Quick Fetch "Hello"
  </button> 
  
<script>
    // Fetch using modern Browser APIs
    // This is the more manual method, in case you don't expect JSON or want more control
    // This uses the full internal syntax `app/auto/api/controller/method`
    function helloFetch(moduleContext) {
      $2sxc(moduleContext).webApi
      .fetchRaw('app/auto/api/basic/hello')
        .then(response => response.json())
        .then(data => alert('Result using quick Fetch: ' 
        + data));
    }
</script>

Source Code of BasicController.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
public class BasicController : Custom.Hybrid.Api14 // see https://r.2sxc.org/CustomWebApi
{
  [HttpGet]                               // [HttpGet] says we're listening to GET requests
  public string Hello()
  {
    return "Hello from the basic controller in /api";
  }

  [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

Note about Hybrid APIs

These examples are all done to work in both Dnn ☢️ and Oqtane 💧. Because of this, the Api Controller have special conditional statements like #if NETCOREAPP which uses different namespaces in .net core and .net Framework.
If you only target Dnn or Oqtane, you can remove the lines you don't need. See See how to use #if

⬇️ Result | Source ➡️

@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="helloFetchManual(this)">Quick Fetch "Hello"</button>
  
  <script>
  // Manual Fetch call using more code
  // This is the most manual method, but shows how it actually works internally
  function helloFetchManual(moduleContext) {
    var moduleApi = $2sxc(moduleContext).webApi;  // webApi for this specific Module
    var fullApiUrl = moduleApi.url('app/auto/api/basic/hello'); // API url based on current App
    var headers = moduleApi.headers("GET");       // Headers used for GET calls
    fetch(fullApiUrl, { headers: { ...headers } })
        .then(response => response.json())
        .then(data => alert('Result using manual Fetch: ' + data));
  }
</script>

Source Code of BasicController.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
public class BasicController : Custom.Hybrid.Api14 // see https://r.2sxc.org/CustomWebApi
{
  [HttpGet]                               // [HttpGet] says we're listening to GET requests
  public string Hello()
  {
    return "Hello from the basic controller in /api";
  }

  [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

Note about Hybrid APIs

These examples are all done to work in both Dnn ☢️ and Oqtane 💧. Because of this, the Api Controller have special conditional statements like #if NETCOREAPP which uses different namespaces in .net core and .net Framework.
If you only target Dnn or Oqtane, you can remove the lines you don't need. See See how to use #if

⬇️ Result | Source ➡️

@inherits Custom.Hybrid.Razor14

@* Make sure anonymous users have the 2sxc JS API *@
@Kit.Page.Activate("2sxc.JsCore")
<button type="button" class="btn btn-secondary" onclick="helloJQueryOld(this)">
  jQuery Get Hello
  </button>
  
  <script>
  // jQuery versions (not recommended any more, will not work on pages without jQuery)
  function helloJQueryOld(moduleContext) {
    $2sxc(moduleContext).webApi
    .get('app/auto/api/basic/hello')
      .then(function (results) {
        alert("Result using jQuery: " 
        + results);      
      });
  }
</script>

Source Code of BasicController.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
public class BasicController : Custom.Hybrid.Api14 // see https://r.2sxc.org/CustomWebApi
{
  [HttpGet]                               // [HttpGet] says we're listening to GET requests
  public string Hello()
  {
    return "Hello from the basic controller in /api";
  }

  [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

Note about Hybrid APIs

These examples are all done to work in both Dnn ☢️ and Oqtane 💧. Because of this, the Api Controller have special conditional statements like #if NETCOREAPP which uses different namespaces in .net core and .net Framework.
If you only target Dnn or Oqtane, you can remove the lines you don't need. See See how to use #if

⬇️ Result | Source ➡️

@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="squareFetch(this, 7)">
  Fetch Square 7
  </button>
  <button type="button" class="btn btn-primary" onclick="squareFetch(this, 27)">
    Fetch Square 27
    </button>
    
  <script>
    function squareFetch(moduleContext, original) {
      $2sxc(moduleContext).webApi
      .fetchJson('basic/square?number=' + original)
        .then(data => alert('The square of ' 
        + original + '= ' + data));
    }
</script>

Source Code of BasicController.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
public class BasicController : Custom.Hybrid.Api14 // see https://r.2sxc.org/CustomWebApi
{
  [HttpGet]                               // [HttpGet] says we're listening to GET requests
  public string Hello()
  {
    return "Hello from the basic controller in /api";
  }

  [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

Note about Hybrid APIs

These examples are all done to work in both Dnn ☢️ and Oqtane 💧. Because of this, the Api Controller have special conditional statements like #if NETCOREAPP which uses different namespaces in .net core and .net Framework.
If you only target Dnn or Oqtane, you can remove the lines you don't need. See See how to use #if

More secure Basic WebApi Example

In this example, we'll ensure that calls to your API only come from users who are visiting your website. This is to protect agains CSRF attacks, where another website gets your users to interact with your API. That could be dangerous, because maybe your API has things only a logged in user should see - and without the CSRF protection, the other website could get access to that because the user is logged in.

⬇️ Result | Source ➡️

@inherits Custom.Hybrid.Razor14

<button type="button" class="btn btn-primary" 
  onclick="apiWithVerification(this)">
  Call WebApi
</button> 
  
<script>
  function apiWithVerification(moduleContext) {
    $2sxc(moduleContext).webApi.fetchJson('verified/hello')
      .then(data => alert(data));
  }
</script>

Source Code of VerifiedController.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 VerifiedController : Custom.Hybrid.Api14 // see https://r.2sxc.org/CustomWebApi
{

  [HttpGet]                               // [HttpGet] says we're listening to GET requests
  public string Hello()
  {
    return "Hello from the controller with ValidateAntiForgeryToken in /api";
  }
}

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

Note about Hybrid APIs

These examples are all done to work in both Dnn ☢️ and Oqtane 💧. Because of this, the Api Controller have special conditional statements like #if NETCOREAPP which uses different namespaces in .net core and .net Framework.
If you only target Dnn or Oqtane, you can remove the lines you don't need. See See how to use #if

REST APIs for Content using GET, POST, PUT, DELETE Verbs

In this example, we'll assume your WebApi controller is called Orders (so the file is called OrdersController.cs and has a class called OrdersController). It's located in /api which is the default location for WebApi controllers.
We'll show various usages of the http methods with the new webApi.fetch(...)

⬇️ Result | Source ➡️

@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="getOrdersFetch(this)">
  Quick Fetch GET "Orders"
</button> 
  
<script>
  function getOrdersFetch(moduleContext) {
    $2sxc(moduleContext).webApi
    .fetchJson('orders/get')
      .then(data => alert('Result using quick Fetch: ' 
      + JSON.stringify(data)));
  }
</script>

Source Code of OrdersController.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.Collections.Generic;

[AllowAnonymous]                          // all commands can be accessed without a login
public class OrdersController : Custom.Hybrid.Api14 // see https://r.2sxc.org/CustomWebApi
{
  public List<Order> orders = new List<Order>{
    new Order{ Id = 1, Amount = 10 },
    new Order{ Id = 2, Amount = 37 }
  };

  [HttpGet]        // [HttpPost] says we're listening to POST requests
  public List<Order> Get()
  {
    return orders;
  }

  [HttpPost]        // [HttpPost] says we're listening to POST requests
  public Order Post([FromBody] Order order)
  {
    order.Id = orders[orders.Count - 1].Id + 1;
    orders.Add(order);
    return orders[orders.Count - 1];
  }

  [HttpPut]        // [HttpPut] says we're listening to PUT requests
  public Order Put([FromBody] Order order)
  {
    orders[0].Amount = order.Amount;
    return orders[0];
  }

  [HttpDelete]        // [HttpDelete] says we're listening to DELETE requests
  public string Delete()
  {
    orders.RemoveAt(0);
    return "";
  }
}

public class Order {
  public int Id;
  public int Amount;
}

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

Note about Hybrid APIs

These examples are all done to work in both Dnn ☢️ and Oqtane 💧. Because of this, the Api Controller have special conditional statements like #if NETCOREAPP which uses different namespaces in .net core and .net Framework.
If you only target Dnn or Oqtane, you can remove the lines you don't need. See See how to use #if

⬇️ Result | Source ➡️

@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="postOrdersFetch(this)">
  Quick Fetch POST "Orders"
</button> 
  
<script>
  function postOrdersFetch(moduleContext) {
    $2sxc(moduleContext).webApi
    .fetchJson('orders/post', 
    { amount: Math.floor(Math.random() * 100) })
      .then(data => alert('Result using quick Fetch: ' 
      + JSON.stringify(data)));
  }
</script>

Source Code of OrdersController.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.Collections.Generic;

[AllowAnonymous]                          // all commands can be accessed without a login
public class OrdersController : Custom.Hybrid.Api14 // see https://r.2sxc.org/CustomWebApi
{
  public List<Order> orders = new List<Order>{
    new Order{ Id = 1, Amount = 10 },
    new Order{ Id = 2, Amount = 37 }
  };

  [HttpGet]        // [HttpPost] says we're listening to POST requests
  public List<Order> Get()
  {
    return orders;
  }

  [HttpPost]        // [HttpPost] says we're listening to POST requests
  public Order Post([FromBody] Order order)
  {
    order.Id = orders[orders.Count - 1].Id + 1;
    orders.Add(order);
    return orders[orders.Count - 1];
  }

  [HttpPut]        // [HttpPut] says we're listening to PUT requests
  public Order Put([FromBody] Order order)
  {
    orders[0].Amount = order.Amount;
    return orders[0];
  }

  [HttpDelete]        // [HttpDelete] says we're listening to DELETE requests
  public string Delete()
  {
    orders.RemoveAt(0);
    return "";
  }
}

public class Order {
  public int Id;
  public int Amount;
}

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

Note about Hybrid APIs

These examples are all done to work in both Dnn ☢️ and Oqtane 💧. Because of this, the Api Controller have special conditional statements like #if NETCOREAPP which uses different namespaces in .net core and .net Framework.
If you only target Dnn or Oqtane, you can remove the lines you don't need. See See how to use #if

⬇️ Result | Source ➡️

@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="putOrdersFetch(this)">
  Quick Fetch PUT "Orders"
</button> 
  
<script>
  function putOrdersFetch(moduleContext) {
    $2sxc(moduleContext).webApi
    .fetchJson('orders/put', 
    { amount: Math.floor(Math.random() * 100) }, 'PUT')
      .then(data => alert('Result using quick Fetch: ' 
      + JSON.stringify(data)));
  }
</script>

Source Code of OrdersController.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.Collections.Generic;

[AllowAnonymous]                          // all commands can be accessed without a login
public class OrdersController : Custom.Hybrid.Api14 // see https://r.2sxc.org/CustomWebApi
{
  public List<Order> orders = new List<Order>{
    new Order{ Id = 1, Amount = 10 },
    new Order{ Id = 2, Amount = 37 }
  };

  [HttpGet]        // [HttpPost] says we're listening to POST requests
  public List<Order> Get()
  {
    return orders;
  }

  [HttpPost]        // [HttpPost] says we're listening to POST requests
  public Order Post([FromBody] Order order)
  {
    order.Id = orders[orders.Count - 1].Id + 1;
    orders.Add(order);
    return orders[orders.Count - 1];
  }

  [HttpPut]        // [HttpPut] says we're listening to PUT requests
  public Order Put([FromBody] Order order)
  {
    orders[0].Amount = order.Amount;
    return orders[0];
  }

  [HttpDelete]        // [HttpDelete] says we're listening to DELETE requests
  public string Delete()
  {
    orders.RemoveAt(0);
    return "";
  }
}

public class Order {
  public int Id;
  public int Amount;
}

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

Note about Hybrid APIs

These examples are all done to work in both Dnn ☢️ and Oqtane 💧. Because of this, the Api Controller have special conditional statements like #if NETCOREAPP which uses different namespaces in .net core and .net Framework.
If you only target Dnn or Oqtane, you can remove the lines you don't need. See See how to use #if

⬇️ Result | Source ➡️

@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="deleteOrdersFetch(this)">
  Quick Fetch DELETE "Orders"
  </button> 
  
<script>
  function deleteOrdersFetch(moduleContext) {
    $2sxc(moduleContext).webApi
    .fetchJson('orders/delete', null, 'DELETE')
      .then(data => alert('Delete executed'));
  }
</script>

Source Code of OrdersController.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.Collections.Generic;

[AllowAnonymous]                          // all commands can be accessed without a login
public class OrdersController : Custom.Hybrid.Api14 // see https://r.2sxc.org/CustomWebApi
{
  public List<Order> orders = new List<Order>{
    new Order{ Id = 1, Amount = 10 },
    new Order{ Id = 2, Amount = 37 }
  };

  [HttpGet]        // [HttpPost] says we're listening to POST requests
  public List<Order> Get()
  {
    return orders;
  }

  [HttpPost]        // [HttpPost] says we're listening to POST requests
  public Order Post([FromBody] Order order)
  {
    order.Id = orders[orders.Count - 1].Id + 1;
    orders.Add(order);
    return orders[orders.Count - 1];
  }

  [HttpPut]        // [HttpPut] says we're listening to PUT requests
  public Order Put([FromBody] Order order)
  {
    orders[0].Amount = order.Amount;
    return orders[0];
  }

  [HttpDelete]        // [HttpDelete] says we're listening to DELETE requests
  public string Delete()
  {
    orders.RemoveAt(0);
    return "";
  }
}

public class Order {
  public int Id;
  public int Amount;
}

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

Note about Hybrid APIs

These examples are all done to work in both Dnn ☢️ and Oqtane 💧. Because of this, the Api Controller have special conditional statements like #if NETCOREAPP which uses different namespaces in .net core and .net Framework.
If you only target Dnn or Oqtane, you can remove the lines you don't need. See See how to use #if

Bare Metal WebAPI Commands

In some cases you want to have more control over the API calls, but still need 2sxc to help you get the right headers and urls. This is what we call the Bare Metal WebApi since it gives you the stuff so you can do the work yourself.

As with everything, you usually need to get the module sxc controller first, so that the values you get match your app and use case. In these examples, we're using the current HTML-node to find the sxc controller, but there are other ways as well if you prefer working the the Module Id.

This will show you the headers which will probably be needed for a request.

⬇️ Result | Source ➡️

@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="showHeaders(this)">Default headers</button>
<button type="button" class="btn btn-primary" onclick="showHeaders(this, 'GET')">Headers for GET</button>
<button type="button" class="btn btn-primary" onclick="showHeaders(this, 'POST')">...for POST</button>
<button type="button" class="btn btn-primary" onclick="showHeaders(this, 'PUT')">...for PUT</button>

<script>
function showHeaders(moduleContext, optionalVerb) {
  var headers = $2sxc(moduleContext).webApi.headers(optionalVerb);
  alert('These are the headers used if the verb is "' + (optionalVerb ?? '') + '":\n' 
    + JSON.stringify(headers, null, 2));
}
</script>

Source Code of VerifiedController.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 VerifiedController : Custom.Hybrid.Api14 // see https://r.2sxc.org/CustomWebApi
{

  [HttpGet]                               // [HttpGet] says we're listening to GET requests
  public string Hello()
  {
    return "Hello from the controller with ValidateAntiForgeryToken in /api";
  }
}

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

Note about Hybrid APIs

These examples are all done to work in both Dnn ☢️ and Oqtane 💧. Because of this, the Api Controller have special conditional statements like #if NETCOREAPP which uses different namespaces in .net core and .net Framework.
If you only target Dnn or Oqtane, you can remove the lines you don't need. See See how to use #if

Resolve URLs to endpoints and similar.

⬇️ Result | Source ➡️

@inherits Custom.Hybrid.Razor14

<button type="button" class="btn btn-primary" onclick="showUrl(this, 'basic/hello')">Url for: basic/hello</button>
<button type="button" class="btn btn-primary" onclick="showUrl(this, 'app/auto/api/basic/hello')">Url: app/auto/api/basic/hello</button>
<button type="button" class="btn btn-primary" onclick="showUrl(this, 'basic/square?number=2742')">Url: basic/square?number=2742</button>
  
<script>
function showUrl(moduleContext, url) {
  var finalUrl = $2sxc(moduleContext).webApi.url(url);
  alert('These is the full url for "' + url + '":\n' + finalUrl);
}
</script>

Source Code of VerifiedController.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 VerifiedController : Custom.Hybrid.Api14 // see https://r.2sxc.org/CustomWebApi
{

  [HttpGet]                               // [HttpGet] says we're listening to GET requests
  public string Hello()
  {
    return "Hello from the controller with ValidateAntiForgeryToken in /api";
  }
}

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

Note about Hybrid APIs

These examples are all done to work in both Dnn ☢️ and Oqtane 💧. Because of this, the Api Controller have special conditional statements like #if NETCOREAPP which uses different namespaces in .net core and .net Framework.
If you only target Dnn or Oqtane, you can remove the lines you don't need. See See how to use #if

 

 

#2 WebAPI Basics: Call WebAPIs and REST using JavaScript