Initial commit: solution and project structure
This commit is contained in:
commit
02805630d0
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
bin/
|
||||
obj/
|
||||
.vs/
|
||||
*.user
|
||||
*.log
|
||||
appsettings.Development.json
|
||||
25
SlReport.sln
Normal file
25
SlReport.sln
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.14.36603.0 d17.14
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SlReport", "SlReport\SlReport.csproj", "{2FCE8950-D2A2-4730-96DD-4DB3EB1BD1FD}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{2FCE8950-D2A2-4730-96DD-4DB3EB1BD1FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2FCE8950-D2A2-4730-96DD-4DB3EB1BD1FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2FCE8950-D2A2-4730-96DD-4DB3EB1BD1FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2FCE8950-D2A2-4730-96DD-4DB3EB1BD1FD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {9351DED9-BDB8-4A4C-97B2-582D3BBF902B}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
6
SlReport/App.config
Normal file
6
SlReport/App.config
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
|
||||
</startup>
|
||||
</configuration>
|
||||
192
SlReport/Program.cs
Normal file
192
SlReport/Program.cs
Normal file
@ -0,0 +1,192 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
|
||||
class Program
|
||||
{
|
||||
static SignLanguageReportApiClient api;
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Console.Title = "SL REPORT – API TEST HARNESS";
|
||||
|
||||
try
|
||||
{
|
||||
api = new SignLanguageReportApiClient("https://localhost:44367/");
|
||||
|
||||
LogHeader("SL REPORT TEST STARTED");
|
||||
|
||||
var userId = RegisterUser();
|
||||
if (userId == Guid.Empty)
|
||||
return;
|
||||
|
||||
RegisterClient();
|
||||
MapUser(userId);
|
||||
CaptureSessions();
|
||||
ReportAllHistory();
|
||||
ReportFilteredHistory();
|
||||
ListAllClients();
|
||||
|
||||
LogHeader("SL REPORT TEST COMPLETED");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFatal("UNHANDLED FATAL ERROR", ex);
|
||||
}
|
||||
|
||||
Console.WriteLine("\nPress ENTER to exit...");
|
||||
Console.ReadLine();
|
||||
}
|
||||
static Guid RegisterUser()
|
||||
{
|
||||
return SafeCall(
|
||||
() => api.RegisterUser("test_user3", "123456"),
|
||||
"RegisterUser"
|
||||
);
|
||||
}
|
||||
static void RegisterClient()
|
||||
{
|
||||
SafeCall(
|
||||
() => api.RegisterClient("13351", "MORO"),
|
||||
"RegisterClient"
|
||||
);
|
||||
}
|
||||
static void MapUser(Guid userId)
|
||||
{
|
||||
SafeCall(
|
||||
() => api.MapUser(userId, "13351", "MORO"),
|
||||
"MapUser"
|
||||
);
|
||||
}
|
||||
static void CaptureSessions()
|
||||
{
|
||||
SafeCall(() => api.Capture("13351", "MORO"), "Capture #1");
|
||||
SafeCall(() => api.Capture("13351", "MORO"), "Capture #2");
|
||||
}
|
||||
static void ReportAllHistory()
|
||||
{
|
||||
var history = SafeCall(
|
||||
() => api.ReportAllClientHistory("13351", "MORO"),
|
||||
"ReportAllClientHistory"
|
||||
);
|
||||
|
||||
if (history == null) return;
|
||||
|
||||
LogInfo($"History records: {history.Count}");
|
||||
foreach (var h in history)
|
||||
LogInfo($"{h.captDate:yyyy-MM-dd HH:mm:ss} , Sessions: {h.NoOfSessions}");
|
||||
}
|
||||
static void ReportFilteredHistory()
|
||||
{
|
||||
var from = DateTime.Today.AddDays(-7);
|
||||
var to = DateTime.Today;
|
||||
|
||||
var history = SafeCall(
|
||||
() => api.ReportClientHistory("13351", "MORO", from, to),
|
||||
"ReportClientHistory"
|
||||
);
|
||||
|
||||
if (history != null)
|
||||
LogInfo($"Filtered records: {history.Count}");
|
||||
foreach (var h in history)
|
||||
LogInfo($"{h.captDate:yyyy-MM-dd HH:mm:ss} , Sessions: {h.NoOfSessions}");
|
||||
|
||||
}
|
||||
static void ListAllClients()
|
||||
{
|
||||
var clients = SafeCall(
|
||||
() => api.ListAllClients(),
|
||||
"ListAllClients"
|
||||
);
|
||||
|
||||
if (clients != null)
|
||||
LogInfo($"Total clients: {clients.Count}");
|
||||
foreach (var c in clients)
|
||||
LogInfo($"cid: {c.cid}, srv: {c.srv}, addingDate: {c.addingDate}, lastCaptDate: {c.lastCaptDate}, NoOfCapt: {c.NoOfCapt}");
|
||||
|
||||
}
|
||||
static T SafeCall<T>(Func<T> action, string stepName)
|
||||
{
|
||||
var sw = Stopwatch.StartNew();
|
||||
LogStep(stepName);
|
||||
|
||||
try
|
||||
{
|
||||
var result = action();
|
||||
sw.Stop();
|
||||
LogSuccess($"{stepName} completed in {sw.ElapsedMilliseconds} ms");
|
||||
return result;
|
||||
}
|
||||
catch (WebException wex)
|
||||
{
|
||||
sw.Stop();
|
||||
LogError(stepName, "NETWORK / HTTP ERROR", wex);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
sw.Stop();
|
||||
LogError(stepName, "APPLICATION ERROR", ex);
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
static void LogHeader(string msg)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Cyan;
|
||||
Console.WriteLine("\n======================================");
|
||||
Console.WriteLine(msg);
|
||||
Console.WriteLine("======================================\n");
|
||||
Console.ResetColor();
|
||||
}
|
||||
|
||||
static void LogStep(string msg)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||
Console.WriteLine($"> {msg}");
|
||||
Console.ResetColor();
|
||||
}
|
||||
|
||||
static void LogSuccess(string msg)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Green;
|
||||
Console.WriteLine($"✔ {msg}\n");
|
||||
Console.ResetColor();
|
||||
}
|
||||
|
||||
static void LogInfo(string msg)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Gray;
|
||||
Console.WriteLine($" {msg}");
|
||||
Console.ResetColor();
|
||||
}
|
||||
|
||||
static void LogError(string step, string type, Exception ex)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.WriteLine($"✖ {step} FAILED [{type}]");
|
||||
Console.WriteLine($" Message: {ex.Message}");
|
||||
|
||||
if (ex.InnerException != null)
|
||||
Console.WriteLine($" Inner: {ex.InnerException.Message}");
|
||||
|
||||
Console.ResetColor();
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
static void LogFatal(string msg, Exception ex)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.DarkRed;
|
||||
Console.WriteLine("!!! FATAL ERROR !!!");
|
||||
Console.WriteLine(msg);
|
||||
|
||||
if (ex != null)
|
||||
{
|
||||
Console.WriteLine(ex.Message);
|
||||
Console.WriteLine(ex.StackTrace);
|
||||
}
|
||||
|
||||
Console.ResetColor();
|
||||
}
|
||||
}
|
||||
33
SlReport/Properties/AssemblyInfo.cs
Normal file
33
SlReport/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("SlReport")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("SlReport")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2026")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("2fce8950-d2a2-4730-96dd-4db3eb1bd1fd")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
109
SlReport/SignLanguageReportApiClient.cs
Normal file
109
SlReport/SignLanguageReportApiClient.cs
Normal file
@ -0,0 +1,109 @@
|
||||
using MindRockets.WebTools.Client;
|
||||
using MindRockets.WebTools.Contracts;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
||||
public class SignLanguageReportApiClient : ModernAPIClient
|
||||
{
|
||||
public SignLanguageReportApiClient(string endPointHost)
|
||||
: base(endPointHost)
|
||||
{
|
||||
}
|
||||
|
||||
public Guid RegisterUser(string username, string pwd)
|
||||
{
|
||||
var data = new Dictionary<string, object>
|
||||
{
|
||||
{ "username", username },
|
||||
{ "pwd", pwd }
|
||||
};
|
||||
|
||||
return PostAction<Guid>("slrep", "reguser", data.Secure(), true);
|
||||
}
|
||||
|
||||
public bool RegisterClient(string cid, string srv)
|
||||
{
|
||||
var data = new Dictionary<string, object>
|
||||
{
|
||||
{ "cid", cid },
|
||||
{ "srv", srv }
|
||||
};
|
||||
|
||||
return PostAction<bool>("slrep", "regclient", data.Secure(), true);
|
||||
}
|
||||
|
||||
public bool MapUser(Guid userId, string cid, string srv)
|
||||
{
|
||||
var data = new Dictionary<string, object>
|
||||
{
|
||||
{ "userid", userId.ToString() },
|
||||
{ "cid", cid },
|
||||
{ "srv", srv }
|
||||
};
|
||||
|
||||
return PostAction<bool>("slrep", "mapuser", data.Secure(), true);
|
||||
}
|
||||
|
||||
public bool Capture(string cid, string srv)
|
||||
{
|
||||
var data = new Dictionary<string, object>
|
||||
{
|
||||
{ "cid", cid },
|
||||
{ "srv", srv }
|
||||
};
|
||||
|
||||
return PostAction<bool>("slrep", "capt", data.Secure(), true);
|
||||
}
|
||||
|
||||
public List<ClientHistory> ReportAllClientHistory(string cid, string srv)
|
||||
{
|
||||
var data = new Dictionary<string, object>
|
||||
{
|
||||
{ "cid", cid },
|
||||
{ "srv", srv }
|
||||
};
|
||||
|
||||
return PostAction<List<ClientHistory>>("slrep", "repallcid", data.Secure(), true);
|
||||
}
|
||||
|
||||
public List<ClientHistory> ReportClientHistory(
|
||||
string cid,
|
||||
string srv,
|
||||
DateTime from,
|
||||
DateTime to)
|
||||
{
|
||||
var data = new Dictionary<string, object>
|
||||
{
|
||||
{ "cid", cid },
|
||||
{ "srv", srv },
|
||||
{ "from", from },
|
||||
{ "to", to }
|
||||
};
|
||||
|
||||
return PostAction<List<ClientHistory>>("slrep", "repcid", data.Secure(), true);
|
||||
}
|
||||
|
||||
public List<ClientInfo> ListAllClients()
|
||||
{
|
||||
return PostAction<List<ClientInfo>>("slrep", "listallclients", NoParams.Secure(), true);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class ClientInfo
|
||||
{
|
||||
public string cid { get; set; }
|
||||
public string srv { get; set; }
|
||||
public DateTime addingDate { get; set; }
|
||||
public DateTime? lastCaptDate { get; set; }
|
||||
public int NoOfCapt { get; set; }
|
||||
}
|
||||
|
||||
public class ClientHistory
|
||||
{
|
||||
public DateTime captDate { get; set; }
|
||||
public int NoOfSessions { get; set; }
|
||||
}
|
||||
|
||||
115
SlReport/SlReport.csproj
Normal file
115
SlReport/SlReport.csproj
Normal file
@ -0,0 +1,115 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{2FCE8950-D2A2-4730-96DD-4DB3EB1BD1FD}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>SlReport</RootNamespace>
|
||||
<AssemblyName>SlReport</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="MindRockets.WebTools, Version=1.5.2.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\MindRockets.WebTools.1.6.0\lib\net47\MindRockets.WebTools.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="MindRockets.WebTools.Client, Version=1.4.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\MindRockets.WebTools.Client.1.4.0\lib\net47\MindRockets.WebTools.Client.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="MindRockets.WebTools.Contracts, Version=1.3.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\MindRockets.WebTools.Contracts.1.3.0\lib\net47\MindRockets.WebTools.Contracts.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="MindRockets.WebTools.Json, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\MindRockets.WebTools.Json.1.0.0\lib\net47\MindRockets.WebTools.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="MindRocketsInc.Helpers, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\MindRocketsInc.Helpers.1.5.2\lib\net45\MindRocketsInc.Helpers.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.Composition" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.IO, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.IO.4.3.0\lib\net462\System.IO.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Net.Http, Version=4.1.1.3, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Net.Http.4.3.4\lib\net46\System.Net.Http.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Runtime, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Runtime.4.3.0\lib\net462\System.Runtime.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Security.Cryptography.Algorithms, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net463\System.Security.Cryptography.Algorithms.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Security.Cryptography.Encoding, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Security.Cryptography.Primitives, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Security.Cryptography.X509Certificates, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SignLanguageReportApiClient.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="WebClient\modern-client.js" />
|
||||
<Content Include="WebClient\modern-utils.js" />
|
||||
<Content Include="WebClient\ModernAPIClient_Documentation.html" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
130
SlReport/WebClient/ModernAPIClient_Documentation.html
Normal file
130
SlReport/WebClient/ModernAPIClient_Documentation.html
Normal file
@ -0,0 +1,130 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>ModernAPIClient Documentation</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
</head>
|
||||
<body class="bg-light">
|
||||
<div class="container mt-5">
|
||||
<h1 class="mb-4">ModernAPIClient Documentation</h1>
|
||||
|
||||
<section>
|
||||
<h2>Overview</h2>
|
||||
<p>The <code>ModernAPIClient</code> class is designed to simplify API interactions in a web environment. It supports making <code>GET</code> and <code>POST</code> requests, including handling file uploads and securely managing request parameters.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Initialization</h2>
|
||||
<pre><code>const client = new ModernAPIClient('https://api.example.com');</code></pre>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Memory Optimization and Security</h2>
|
||||
<p>When the <code>ModernAPIClient</code> is instantiated, it automatically decrypts and stores certain values (e.g., <code>MemOptimizeMethod</code> and <code>MemStackFrame</code>) that are used to secure API requests. These values are expected to be present as Base64-encoded hidden fields in the HTML page.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Methods</h2>
|
||||
|
||||
<h3>1. <code>postAction(controller, action, parameters, secure = false)</code></h3>
|
||||
<p>Sends a <code>POST</code> request to a specific controller and action within the API.</p>
|
||||
<p><strong>Parameters:</strong></p>
|
||||
<ul>
|
||||
<li><code>controller</code> (string): The controller name.</li>
|
||||
<li><code>action</code> (string): The action name.</li>
|
||||
<li><code>parameters</code> (object): An object containing key-value pairs to be sent as the POST body.</li>
|
||||
<li><code>secure</code> (boolean): If <code>true</code>, the request will be secured with additional parameters.</li>
|
||||
</ul>
|
||||
<p><strong>Returns:</strong> A <code>Promise</code> that resolves with the response data.</p>
|
||||
|
||||
<h4>Example:</h4>
|
||||
<pre><code>const parameters = { param1: 'value1' };
|
||||
client.postAction('exampleController', 'exampleAction', parameters)
|
||||
.then(response => console.log('POST Action Result:', response))
|
||||
.catch(error => console.error('Error in POST Action:', error));</code></pre>
|
||||
|
||||
<h3>2. <code>postFileAction(controller, action, fileName, secure = false)</code></h3>
|
||||
<p>Sends a <code>POST</code> request to upload a file to a specific controller and action within the API.</p>
|
||||
<p><strong>Parameters:</strong></p>
|
||||
<ul>
|
||||
<li><code>controller</code> (string): The controller name.</li>
|
||||
<li><code>action</code> (string): The action name.</li>
|
||||
<li><code>fileName</code> (string): The file to be uploaded.</li>
|
||||
<li><code>secure</code> (boolean): If <code>true</code>, the request will be secured with additional parameters.</li>
|
||||
</ul>
|
||||
<p><strong>Returns:</strong> A <code>Promise</code> that resolves with the response data.</p>
|
||||
|
||||
<h4>Example:</h4>
|
||||
<pre><code>const fileInput = document.getElementById('fileInput');
|
||||
const file = fileInput.files[0];
|
||||
client.postFileAction('uploadController', 'uploadAction', file)
|
||||
.then(response => console.log('File Upload Result:', response))
|
||||
.catch(error => console.error('Error in File Upload:', error));</code></pre>
|
||||
|
||||
<h3>3. <code>getAction(controller, action, parameters, secure = false)</code></h3>
|
||||
<p>Sends a <code>GET</code> request to a specific controller and action within the API.</p>
|
||||
<p><strong>Parameters:</strong></p>
|
||||
<ul>
|
||||
<li><code>controller</code> (string): The controller name.</li>
|
||||
<li><code>action</code> (string): The action name.</li>
|
||||
<li><code>parameters</code> (object): An object containing key-value pairs to be sent as query string parameters.</li>
|
||||
<li><code>secure</code> (boolean): If <code>true</code>, the request will be secured with additional parameters.</li>
|
||||
</ul>
|
||||
<p><strong>Returns:</strong> A <code>Promise</code> that resolves with the response data.</p>
|
||||
|
||||
<h4>Example:</h4>
|
||||
<pre><code>const parameters = { param1: 'value1' };
|
||||
client.getAction('exampleController', 'exampleAction', parameters)
|
||||
.then(response => console.log('GET Action Result:', response))
|
||||
.catch(error => console.error('Error in GET Action:', error));</code></pre>
|
||||
|
||||
<h3>4. <code>getStatic(staticRoute, parameters, secure = false)</code></h3>
|
||||
<p>Sends a <code>GET</code> request to a specific static route within the API.</p>
|
||||
<p><strong>Parameters:</strong></p>
|
||||
<ul>
|
||||
<li><code>staticRoute</code> (string): The static route.</li>
|
||||
<li><code>parameters</code> (object): An object containing key-value pairs to be sent as query string parameters.</li>
|
||||
<li><code>secure</code> (boolean): If <code>true</code>, the request will be secured with additional parameters.</li>
|
||||
</ul>
|
||||
<p><strong>Returns:</strong> A <code>Promise</code> that resolves with the response data.</p>
|
||||
|
||||
<h4>Example:</h4>
|
||||
<pre><code>const parameters = { param1: 'value1' };
|
||||
client.getStatic('/staticRoute', parameters)
|
||||
.then(response => console.log('GET Static Result:', response))
|
||||
.catch(error => console.error('Error in GET Static:', error));</code></pre>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Secure Requests</h2>
|
||||
<p>For secure API interactions, set the <code>secure</code> parameter to <code>true</code> in any of the methods. This will add additional parameters, such as a timestamp and values from decrypted memory, to the request.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Example Workflow</h2>
|
||||
<pre><code>// Initialize the client with the base API URL
|
||||
const client = new ModernAPIClient('https://api.example.com');
|
||||
|
||||
// Perform a secure POST request
|
||||
const postParams = { param1: 'value1', param2: 'value2' };
|
||||
client.postAction('myController', 'myAction', postParams, true)
|
||||
.then(response => console.log('POST Response:', response))
|
||||
.catch(error => console.error('POST Error:', error));
|
||||
|
||||
// Perform a secure GET request
|
||||
const getParams = { param1: 'value1' };
|
||||
client.getAction('myController', 'myGetAction', getParams, true)
|
||||
.then(response => console.log('GET Response:', response))
|
||||
.catch(error => console.error('GET Error:', error));</code></pre>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Conclusion</h2>
|
||||
<p>The <code>ModernAPIClient</code> class is a powerful tool for interacting with RESTful APIs in a web environment. It offers flexibility with its secure request options and supports a variety of request types, including file uploads. By following the examples provided, you can easily integrate this class into your web applications.</p>
|
||||
</section>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
150
SlReport/WebClient/modern-client.js
Normal file
150
SlReport/WebClient/modern-client.js
Normal file
@ -0,0 +1,150 @@
|
||||
class ModernAPIClient {
|
||||
constructor(endpointHost) {
|
||||
this._endpointHost = verifyUrlNotEndingWithSlash(endpointHost);
|
||||
this.MemOptimizeMethod = '';
|
||||
this.MemStackFrame = '';
|
||||
|
||||
this.initializeMemory();
|
||||
}
|
||||
|
||||
initializeMemory() {
|
||||
optimizeMemory();
|
||||
this.MemOptimizeMethod = MemOptimizeMethod;
|
||||
this.MemStackFrame = MemStackFrame;
|
||||
}
|
||||
|
||||
secureRequest(parameters) {
|
||||
if (this.MemOptimizeMethod && this.MemStackFrame) {
|
||||
parameters[this.MemOptimizeMethod] = this.MemStackFrame;
|
||||
}
|
||||
}
|
||||
|
||||
async postFileActionResponse(controller, action, fileName, secure = false) {
|
||||
return this.postFileStaticResponse(`/api/${controller}/${action}`, fileName, secure);
|
||||
}
|
||||
|
||||
async postFileAction(controller, action, fileName, secure = false) {
|
||||
const response = await this.postFileStaticResponse(`/api/${controller}/${action}`, fileName, secure);
|
||||
if (response.Results === "OK") {
|
||||
return response.Data;
|
||||
} else {
|
||||
throw new Error(response.Error);
|
||||
}
|
||||
}
|
||||
|
||||
async postFileStaticResponse(staticRoute, fileName, secure = false) {
|
||||
staticRoute = verifyStartingRouteWithSlash(staticRoute);
|
||||
let requestURL = `${this._endpointHost}${staticRoute}`;
|
||||
|
||||
if (secure) {
|
||||
const securityDictionary = {};
|
||||
this.secureRequest(securityDictionary);
|
||||
const params = new URLSearchParams(securityDictionary).toString();
|
||||
requestURL += requestURL.includes('?') ? `&${params}` : `?${params}`;
|
||||
}
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('file', fileName);
|
||||
|
||||
const response = await fetch(requestURL, {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
|
||||
return await parseActionResponse(response);
|
||||
}
|
||||
|
||||
async postFileStatic(staticRoute, fileName, secure = false) {
|
||||
const response = await this.postFileStaticResponse(staticRoute, fileName, secure);
|
||||
if (response.Results === "OK") {
|
||||
return response.Data;
|
||||
} else {
|
||||
throw new Error(response.Error);
|
||||
}
|
||||
}
|
||||
|
||||
async postStaticResponse(staticRoute, parameters, secure = false) {
|
||||
parameters = removeUndefinedValues(parameters);
|
||||
staticRoute = verifyStartingRouteWithSlash(staticRoute);
|
||||
let requestURL = `${this._endpointHost}${staticRoute}`;
|
||||
|
||||
if (secure) {
|
||||
this.secureRequest(parameters);
|
||||
}
|
||||
|
||||
const response = await fetch(requestURL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
body: new URLSearchParams(parameters).toString()
|
||||
});
|
||||
|
||||
return await parseActionResponse(response);
|
||||
}
|
||||
|
||||
async postStatic(staticRoute, parameters, secure = false) {
|
||||
const response = await this.postStaticResponse(staticRoute, parameters, secure);
|
||||
if (response.Results === "OK") {
|
||||
return response.Data;
|
||||
} else {
|
||||
throw new Error(response.Error);
|
||||
}
|
||||
}
|
||||
|
||||
async postActionResponse(controller, action, parameters, secure = false) {
|
||||
return this.postStaticResponse(`/api/${controller}/${action}`, parameters, secure);
|
||||
}
|
||||
|
||||
async postAction(controller, action, parameters, secure = false) {
|
||||
const response = await this.postActionResponse(controller, action, parameters, secure);
|
||||
if (response.Results === "OK") {
|
||||
return response.Data;
|
||||
} else {
|
||||
throw new Error(response.Error);
|
||||
}
|
||||
}
|
||||
|
||||
async getStaticResponse(staticRoute, parameters, secure = false) {
|
||||
staticRoute = verifyStartingRouteWithSlash(staticRoute);
|
||||
let requestURL = `${this._endpointHost}${staticRoute}`;
|
||||
|
||||
parameters = removeUndefinedValues(parameters);
|
||||
if (parameters && Object.keys(parameters).length > 0) {
|
||||
if (secure) {
|
||||
this.secureRequest(parameters);
|
||||
}
|
||||
const params = new URLSearchParams(parameters).toString();
|
||||
requestURL += requestURL.includes('?') ? `&${params}` : `?${params}`;
|
||||
}
|
||||
|
||||
const response = await fetch(requestURL);
|
||||
return await parseActionResponse(response);
|
||||
}
|
||||
|
||||
async getStatic(staticRoute, parameters, secure = false) {
|
||||
const response = await this.getStaticResponse(staticRoute, parameters, secure);
|
||||
if (response.Results === "OK") {
|
||||
return response.Data;
|
||||
} else {
|
||||
throw new Error(response.Error);
|
||||
}
|
||||
}
|
||||
|
||||
async getAction(controller, action, parameters, secure = false) {
|
||||
const response = await this.getActionResponse(controller, action, parameters, secure);
|
||||
if (response.Results === "OK") {
|
||||
return response.Data;
|
||||
} else {
|
||||
throw new Error(response.Error);
|
||||
}
|
||||
}
|
||||
|
||||
async getActionResponse(controller, action, parameters, secure = false) {
|
||||
return this.getStaticResponse(`/api/${controller}/${action}`, parameters, secure);
|
||||
}
|
||||
|
||||
dispose() {
|
||||
// Cleanup tasks if any
|
||||
}
|
||||
}
|
||||
67
SlReport/WebClient/modern-utils.js
Normal file
67
SlReport/WebClient/modern-utils.js
Normal file
@ -0,0 +1,67 @@
|
||||
// modern-utils.js
|
||||
// modern-utils.js
|
||||
|
||||
// Variables to store the decrypted values
|
||||
let MemOptimizeMethod = '';
|
||||
let MemStackFrame = '';
|
||||
|
||||
// Function to simulate decryption (you'll replace this with your actual decryption logic)
|
||||
function decryptBase64(encodedString) {
|
||||
try {
|
||||
return atob(encodedString); // Base64 decode
|
||||
} catch (e) {
|
||||
console.error('Decryption failed', e);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
// Function to extract and decrypt values from hidden fields
|
||||
function optimizeMemory() {
|
||||
const methodField = document.getElementById('MemOptimizeMethod');
|
||||
const frameField = document.getElementById('MemStackFrame');
|
||||
|
||||
if (methodField && frameField) {
|
||||
MemOptimizeMethod = decryptBase64(methodField.value);
|
||||
MemStackFrame = decryptBase64(frameField.value);
|
||||
} else {
|
||||
console.error('Hidden fields for MemOptimizeMethod and MemStackFrame not found');
|
||||
}
|
||||
}
|
||||
|
||||
// Attach variables and functions to the window object so they are globally available
|
||||
window.MemOptimizeMethod = MemOptimizeMethod;
|
||||
window.MemStackFrame = MemStackFrame;
|
||||
window.optimizeMemory = optimizeMemory;
|
||||
|
||||
function verifyUrlNotEndingWithSlash(url) {
|
||||
return url.endsWith('/') ? url.slice(0, -1) : url;
|
||||
}
|
||||
|
||||
function verifyStartingRouteWithSlash(route) {
|
||||
return route.startsWith('/') ? route : `/${route}`;
|
||||
}
|
||||
|
||||
|
||||
|
||||
async function parseActionResponse(response) {
|
||||
const contentType = response.headers.get('Content-Type');
|
||||
|
||||
if (contentType && contentType.includes('application/json')) {
|
||||
return await response.json();
|
||||
} else {
|
||||
return await response.text();
|
||||
}
|
||||
}
|
||||
function removeUndefinedValues(obj) {
|
||||
for (const key in obj) {
|
||||
if (obj[key] === undefined) {
|
||||
delete obj[key];
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
window.removeUndefinedValues = removeUndefinedValues;
|
||||
// Attach functions to the window object so they are globally available
|
||||
window.verifyUrlNotEndingWithSlash = verifyUrlNotEndingWithSlash;
|
||||
window.verifyStartingRouteWithSlash = verifyStartingRouteWithSlash;
|
||||
window.parseActionResponse = parseActionResponse;
|
||||
16
SlReport/packages.config
Normal file
16
SlReport/packages.config
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="MindRockets.WebTools" version="1.6.0" targetFramework="net48" />
|
||||
<package id="MindRockets.WebTools.Client" version="1.4.0" targetFramework="net48" />
|
||||
<package id="MindRockets.WebTools.Contracts" version="1.3.0" targetFramework="net48" />
|
||||
<package id="MindRockets.WebTools.Json" version="1.0.0" targetFramework="net48" />
|
||||
<package id="MindRocketsInc.Helpers" version="1.5.2" targetFramework="net48" />
|
||||
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net48" />
|
||||
<package id="System.IO" version="4.3.0" targetFramework="net48" />
|
||||
<package id="System.Net.Http" version="4.3.4" targetFramework="net48" />
|
||||
<package id="System.Runtime" version="4.3.0" targetFramework="net48" />
|
||||
<package id="System.Security.Cryptography.Algorithms" version="4.3.0" targetFramework="net48" />
|
||||
<package id="System.Security.Cryptography.Encoding" version="4.3.0" targetFramework="net48" />
|
||||
<package id="System.Security.Cryptography.Primitives" version="4.3.0" targetFramework="net48" />
|
||||
<package id="System.Security.Cryptography.X509Certificates" version="4.3.0" targetFramework="net48" />
|
||||
</packages>
|
||||
Loading…
x
Reference in New Issue
Block a user