What does it look like to use the Services Framework?
IServiceRouteMapper interface
                void RegisterRoutes(IMapRoute)MapHttpRoute method on IMapRoute argument
            /DesktopModules/Module/API/[route]
            
        /*GET /DesktopModules/Example/S/API/Example.ashx*/
        namespace Example.Dnn.Services {
            using DotNetNuke.Web.Api;
            public class Mapperator : IServiceRouteMapper {
                public void RegisterRoutes(IMapRoute mapper) {
                    mapper.MapHttpRoute(
                        moduleFolderName: "Example/S", 
                        routeName: "default",
                        url: "{controller}.ashx", 
                        namespaces: new[] { 
                            "Example.Dnn.Services",
                        });
                }
            }
        }
        
    DnnApiController
            Controller
            public methods are actions
            HttpResponseMessage
            
        namespace Example.Dnn.Services {
            using System.Net;
            using System.Net.Http;
            using DotNetNuke.Web.Api;
            public class ExampleController : DnnApiController {
                public HttpResponseMessage GetHello() {
                    return this.Request.CreateResponse(
                        HttpStatusCode.OK, 
                        new { 
                            number = 1, 
                            text = "Hi!",
                    });
                }
            }
        }
        
    UserInfo (and authentication)ActiveModulePortalSettings
                ActiveTabHomeDirectoryMapPathAdministratorIdAdministratorRoleNameCultureCodePortalAlias
        using DotNetNuke.Framework;
        public class MyModuleControl : ModuleView<MyViewModel> {
            protected MyModuleControl() {
                ServicesFramework.Instance.RequestAjaxAntiForgerySupport();
            }
        }
        
    
        var sf = $.ServicesFramework(<%:ModuleContext.ModuleId%>);
        $.ajax({
            type: 'GET',
            url: sf.getServiceRoot('Example/S') + 'Example.ashx',
            beforeSend: sf.setModuleHeaders,
            data: {}
        }).done(function (data) { /*...*/ })
          .fail(function (xhr, status) { /*...*/ });
        
    
            var requestUri = new Uri("http://dnn7.dev/DesktopModules/Example/S/API/Example.ashx");
            var request = new HttpRequestMessage(HttpMethod.Get, requestUri);
            request.Headers.Add("ModuleId", "1740");
            request.Headers.Add("TabId", "56");
            var client = new HttpClient(new HttpClientHandler { 
                Credentials = new NetworkCredential("host", "pa$$") 
            });
            var response = await client.SendAsync(request);
            if (!response.IsSuccessStatusCode) {
                // TODO: show error
                return;
            }
            var json = await response.Content.ReadAsStringAsync();
        
    Use a spacebar or arrow keys to navigate