PROWARE technologies
PROWARE technologies

Setup/Add ASP.NET Core REST API Controller to MVC Website

This article requires ASP.NET Core.

It is very easy to add a REST API to an existing or new ASP.NET Core MVC project. See this quick guide if not familiar with what a REST API is, and see this article for an AJAX library compatible with React.

Create a new C# class file and save it to the project's root folder as Customer.cs.

// Customer.cs
namespace REST
{
	public class Customer
	{
		public string id { get; set; }
		public string name { get; set; }
		public string addr { get; set; }
		public string zip { get; set; }
	}
}

Now, create another new C# class file and save it to the Controller's folder as CustomersController.cs.

// CustomersController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc;

namespace REST.Controllers
{
	[ApiController] // NOTE: for a REST API controller
	[Route("[controller]")]
	public class CustomersController : ControllerBase
	{
		private static readonly string[] names = new[]
		{
			"John", "Jill", "Will", "Sam", "Xavier"
		};
		[HttpPost] // CREATE
		public Customer Post([FromBody]Customer item) // NOTE: [FromBody] specifies that "item" be parsed from the request body
		{
			item.id = Guid.NewGuid().ToString("N");
			return item;
		}
		[HttpGet] // READ
		public Customer[] Get()
		{
			var r = new Random();
			return Enumerable.Range(1, 3).Select(index => new Customer
			{
				id = Guid.NewGuid().ToString("N"),
				name = names[r.Next(names.Length)],
				addr = "Address #" + index,
				zip = "Zip #" + index
			}).ToArray(); // don't order the list as this should be done by the client
		}
		[HttpGet("{id}")] // READ
		public Customer Get(string id) // "id" can be an int
		{
			var r = new Random();
			return new Customer
			{
				id = id,
				name = names[r.Next(names.Length)],
				addr = "Address for " + id,
				zip = "Zip for " + id
			};
		}
		[HttpPut("{id}")] // UPDATE
		public Customer Put(string id, [FromBody]Customer item) // "id" can be an int
		{
			item.id = id;
			return item;
		}
		[HttpDelete("{id}")] // DELETE
		public Customer Delete(string id) // "id" can be an int
		{
			var r = new Random();
			return new Customer
			{
				id = id,
				name = names[r.Next(names.Length)],
				addr = "Address for " + id,
				zip = "Zip for " + id
			};
		}
	}
}

Run the server and try accessing the customers controller. Your browser should show or download the JSON output by the special API controller. To POST, PUT and DELETE data use the following file: JSONMAN.html.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>JSON-MAN</title>
<style>
* {
	font-family: sans-serif;
	font-size: 30px;
	color: blue;
}
body {
	padding: 3%;
}
input, table, td:nth-child(2) {
	width: 100%;
}
textarea {
	width: 100%;
	height: 300px;
}
</style>
<script type="text/javascript">
/*
request = {
	verb: "GET POST PUT PATCH DELETE",
	path: "/api/",
	headers: {"header1":"value1","header2":"value2"},
	data: '{"is":"json"}' or Object,
	onprogress: function(percent){}
};
*/
function ajax2(request) {
	var obj = "object";
	var undef = "undefined";
	if (typeof request != obj) { request = {}; }
	var canPromise = (typeof Promise != undef);
	var xmlobj;
	if (typeof XMLHttpRequest != undef) { // must use typeof operator for compatibility reasons
		xmlobj = new XMLHttpRequest();
	}
	else if (typeof window.ActiveXObject != undef) {
		var aVersions = ["MSXML2.XMLHttp.5.0", "MSXML2.XMLHttp.4.0", "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp", "Microsoft.XMLHttp"];
		for (var i = 0; i < aVersions.length; i++) {
			try {
				xmlobj = new ActiveXObject(aVersions[i]);
				break;
			} catch (err) {
				//void
			}
		}
	}
	if (typeof xmlobj != obj) {
		return {then:function(){return{catch:function(ca){ca("XMLHttpRequest object could not be created");}}}};
	}
	if(typeof request.onprogress == "function" && typeof xmlobj.upload == obj) {
		xmlobj.upload.addEventListener("progress", function (event) {
			request.onprogress(Math.floor(event.loaded / event.total * 100));
		});
	}
	// if no verb is specified then use "get"; if no path is specified then use the current file
	xmlobj.open(request.verb || "get", request.path || location.pathname, canPromise);
	xmlobj.setRequestHeader("Content-Type", "application/json; charset=UTF-8");
	if(typeof request.headers == obj) {
		for(var prop in request.headers) {
			xmlobj.setRequestHeader(prop, request.headers[prop]);
		}
	}
	if(typeof request.data == obj) {
		request.data = JSON.stringify(request.data);
	}
	xmlobj.send(request.data || null);
	if(canPromise) {
		return new Promise(function (resolve, reject) {
			xmlobj.onreadystatechange = function () {
				if (xmlobj.readyState == 4) {
					if (xmlobj.status >= 200 && xmlobj.status < 300) {
						resolve(xmlobj.responseText);
					}
					else {
						reject(xmlobj.statusText);
					}
				}
			};
		});
	}
	else {
		if (xmlobj.status >= 200 && xmlobj.status < 300) {
			return {then:function(th){th(xmlobj.responseText);return{catch:function(){}}}};
		}
		else {
			return {then:function(){return{catch:function(ca){ca(xmlobj.statusText);}}}};
		}
	}
}
var headersobj = null;
function setHeadersColor(input) {
	try {
		headersobj = JSON.parse(input.value);
		if (Array.isArray(headersobj)) {
			headersobj = null;
			input.style.color = "red";
		}
		else {
			input.style.color = "#0b0";
		}
	}
	catch {
		headersobj = null;
		input.style.color = "red";
	}
}
function submitRequestForm(form) {
	ajax2({
		verb: form.requestmethod.value,
		path: form.endpoint.value,
		headers: headersobj,
		data: form.requestbody.value
	}).then(function (txt) {
		form.responsebody.value = txt;
		return false;
	}).catch(function (err) {
		alert(err);
		return false;
	});
	return false;
}
</script>
</head>
<body>
	<h1>JSON-MAN</h1>
	<form method="get" action="" onsubmit="return submitRequestForm(this);">
		<div>
			<table><tr><td><select name="requestmethod"><option>GET</option><option>POST</option><option>PUT</option><option>PATCH</option><option>DELETE</option></select></td><td><input type="text" name="endpoint" placeholder="ENDPOINT" /></td></tr></table>
		</div>
		<div>
			<input type="text" name="headers" placeholder='HEADERS EXAMPLE: {"header1":"value1","header2":"value2"}' onchange="setHeadersColor(this);" onkeyup="setHeadersColor(this);" autocomplete="off" />
		</div>
		<div>
			<textarea name="requestbody" placeholder="REQUEST BODY"></textarea>
		</div>
		<div>
			<textarea name="responsebody" placeholder="RESPONSE BODY" readonly></textarea>
		</div>
		<div>
			<button type="submit">submit</button>
		</div>
	</form>
</body>
</html>

Coding Video

https://youtu.be/7N-9qjF6qUk