Source: Controllers/HomeController.cs

using Backend.Services;
using PublicAPI.Models;
using Dapper;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Options;
using Backend.Extensions;
using System.Data;
using System.Xml.Linq;
using System.Diagnostics;

namespace PublicAPI.Controllers {

    [Authorize]
    [ApiController]
    [Route("api/[controller]")]

/**
    * Home controller
    @module HomeController
*/
    [AllowAnonymous]
    public class HomeController : Controller {
        private readonly AppOptions _options;
        private readonly Db _db;
        private readonly IDistributedCache _cache;
        private readonly ILogger<HomeController> _logger;
        private readonly AuthService _authService;
        private readonly CurrentUserInfo _currentUserInfo;

        public HomeController(IOptions<AppOptions> options, Db db, IDistributedCache cache, ILogger<HomeController> logger, AuthService authService, CurrentUserInfo currentUserInfo) {
            this._options = options.Value;
            this._db = db;
            this._cache = cache;
            this._logger = logger;
            this._authService = authService;
            _currentUserInfo = currentUserInfo;
        }

        /**
         * Ping (check if the server is running)
         * @return {ActionResult} - Ok
        */
        [HttpGet("Ping")]
        public async Task<ActionResult> Ping() {
            return Ok("Ok");
        }

        /**
            * Get routes for the current user
            * @return {ActionResult} - List of routes
        */
        [HttpGet("GetIndicatorsForDataSource")]
        public async Task<ActionResult> GetIndicatorsForDataSource(int dataSourceId) {
            var ret = await _db.QueryJsonAsyncCached("data.get_indicators_for_data_source", new { DataSourceId = dataSourceId, LangId = _currentUserInfo.LangId }, _options.ConnectionString, "long");
            return Ok(ret);
        }

        /**
            * Get shapes for data source
            * @return {ActionResult} - Shapes for data source
        */
        [HttpGet("GetShapesForDataSource")]
        public async Task<ActionResult> GetShapesForDataSource(int dataSourceId) {
            var ret = await _db.QueryJsonAsyncCached("data.get_shapes_for_data_source", new { DataSourceId = dataSourceId }, _options.ConnectionString, "long");
            return Ok(ret);
        }

        /**
            * Get catalogs
            * @return {ActionResult} - Catalogs
        */
        [HttpGet("GetCatalogs")]
        public async Task<ActionResult> GetCatalogs() {
            var ret = await _db.QueryJsonAsyncCached("data.get_catalogs", new { LangId = _currentUserInfo.LangId }, _options.ConnectionString, "long");
            return Ok(ret);
        }

/**
    * Get geometry type properties
    * @return {ActionResult} - Geometry type properties
*/
        [HttpGet("GetGeometryTypeProperties")]
        public async Task<ActionResult> GetGeometryTypeProperties() {
            var ret = await _db.QueryJsonAsyncCached("data.get_geometry_type_properties", new { LangId = _currentUserInfo.LangId }, _options.ConnectionString, "long");
            return Ok(ret);
        }

/**
    * Get point history
    * @param {int} pointId - Point id
    * @param {int} indicatorId - Indicator id
    * @return {ActionResult} - Point history
*/
        [HttpGet("GetPointHistory")]     
        public async Task<ActionResult> GetPointHistory(int pointId, int indicatorId) {
            var ret = await _db.QueryAsync("data.get_point_history", new { PointId = pointId, IndicatorId = indicatorId }, _options.ConnectionString);
            return Ok(ret);
        }

/**
    * Get indicator values
    * @param {int} indicatorId - Indicator id
    * @param {int} dataSourceId - Data source id
    * @return {ActionResult} - Indicator values
*/
        [HttpGet("GetIndicatorValues")]
        public async Task<ActionResult> GetIndicatorValues(int indicatorId, int dataSourceId) {
            var ret = await _db.QueryAsyncFrugal("data.get_indicator_values", new { IndicatorId = indicatorId, DataSourceId = dataSourceId}, _options.ConnectionString);
            return Ok(ret);
        }
/**
    * Get indicators table
    * @return {ActionResult} - Indicators table
*/
        [HttpGet("GetIndicatorsTable")]
        public async Task<ActionResult> GetIndicatorsTable() {
            var ret = await _db.QueryAsync("SELECT * FROM data.indicator", new { LangId = _currentUserInfo.LangId }, _options.ConnectionString, cmdType:CommandType.Text);
            return Ok(ret);
        }
/**
    * Get indicator legend
    * @param {int} indicatorId - Indicator id
    * @return {ActionResult} - Indicator legend
*/
        [HttpGet("GetIndicatorLegend")]
        public async Task<ActionResult> GetIndicatorLegend(int indicatorId) {
            var ret = await _db.QueryJsonAsyncCached("data.get_indicator_legend", new { LangId = _currentUserInfo.LangId, IndicatorId = indicatorId  }, _options.ConnectionString, "long");
            return Ok(ret);
        }
/**
    * Get titles
    * @return {ActionResult} - Titles
*/
        [HttpGet("GetTitles")]
        public async Task<ActionResult> GetTitles() {
            var ret = await _db.QueryJsonAsyncCached("data.get_titles", null, _options.ConnectionString, "long");
            return Ok(ret);
        }
/**
    * Get assets
    * @param {int} titleId - Title id
    * @param {string} depth - Depth
    * @param {int} srid - Srid
    * @return {ActionResult} - Assets
*/
        [HttpGet("GetAssets")]
            public async Task<ActionResult> GetAssets([FromQuery] int titleId, string depth, int srid) {
            var ret = await _db.QueryJsonAsyncCached("data.get_assets", new { TitleId = titleId, Depth = depth, Srid = srid }, _options.ConnectionString, "long");
            return Ok(ret);
        }

/**
    * Get boundaries
    * @param {int} level - Level
    * @param {int} srid - Srid
    * @param {int} zoom - Zoom
    * @param {string} extent - Extent
    * @param {int} indicatorId - Indicator id
    * @param {int} dataSourceId - Data source id
    * @return {ActionResult} - Boundaries
*/
        [HttpGet("GetBoundaries")]
        public async Task<ActionResult> GetBoundaries([FromQuery] int level, int srid, int zoom, string extent, int indicatorId, int dataSourceId) {
            var ex = extent.Split(',');
            var ret = await _db.QueryJsonAsyncCached("data.get_nuts_boundaries", 
                new { Level = level, Srid = srid, Zoom = zoom, MinX = Double.Parse(ex[0]), MinY = Double.Parse(ex[1]), MaxX = Double.Parse(ex[2]), MaxY = Double.Parse(ex[3]), 
                    IndicatorId = indicatorId, DataSourceId = dataSourceId }, _options.ConnectionString, "long");
            Debug.WriteLine(ret.Length);
            return Ok(ret);
        }

/**
    * Get tile layers
    * @param {int} srid - Srid
    * @return {ActionResult} - Tile layers
*/  
        [HttpGet("GetTileLayers")]
        public async Task<ActionResult> GetTileLayers([FromQuery] int srid) {
            var ret = await _db.QueryAsyncCached("data.get_tile_layers", new {Srid = srid}, _options.ConnectionString, "long");
            return Ok(ret);
        }

/**
    * Get locale options
    * @return {ActionResult} - Locale options
*/      
        [HttpGet("GetLocaleOptions")]
        public async Task<ActionResult> GetLocaleOptions() {
            var ret = await _db.QueryJsonAsyncCached("meta.get_locale_options", null, _options.ConnectionString, "long");
            return Ok(ret);
        }

/**
    * Get i18n strings
    * @return {ActionResult} - I18n
*/
        [HttpGet("GetI18N")]
        public async Task<ActionResult> GetI18N() {
            var ret = await _db.QueryJsonAsyncCached("meta.get_i18n", new { LangId = _currentUserInfo.LangId }, _options.ConnectionString, "long");
            return Ok(ret);
        }

/**
    * Get help
    * @param {string} name - Name
    * @return {ActionResult} - Help
*/
        [HttpGet("GetHelp/{name}")]
        public async Task<ActionResult> GetHelp(string name) {
            var ret = await _db.QueryJsonAsyncCached("meta.get_help", new { Name = name, LangId = _currentUserInfo.LangId }, _options.ConnectionString, "long");
            return Ok(ret);
        }

/**
    * Get news
    * @param {int} skip - news items to skip 
    * @param {int} n - news items to get
    * @return {ActionResult} - News
*/
        [HttpGet("GetNews/{skip}/{n}")]
        public async Task<ActionResult> GetNews(int skip, int n) {
            try {
                var news = await _cache.GetAsync<List<News>>("News" + _currentUserInfo.LangId.ToString());
                if (news == null) {
                    using var connection = _db.CreateConnection(_options.ConnectionString);
                    news = (await connection.QueryAsync<News>("meta.get_news", new { LangId = _currentUserInfo.LangId },
                        commandType: CommandType.StoredProcedure)).AsList();
                    await _cache.SetAsync<List<News>>("News" + _currentUserInfo.LangId.ToString(), news, "long");
                }
                var ret = news.Skip(skip).Take(n);
                return Ok(ret);
            } catch (Exception e) {
                var ret = Helper.CreateError(_logger, e.Message);
                return Ok(ret);
            }
            
        }

        /**
         * returns the policy for the given policy type
            * @param {string} polycyType - type of policy to return
            * @return {ActionResult} - Policy
        */
        [AllowAnonymous]
        [HttpGet("GetPolicy/{policyType}")]
        public async Task<ActionResult> GetPolicy(string policyType) {
            var ret = await _db.QueryScalarAsyncCached("meta.get_policy", new { PolicyType = policyType }, _options.ConnectionString, "long");
            return Ok(ret);
        }
    }
}