Web app logon.

This commit is contained in:
Andy Howard
2024-06-04 16:16:05 +01:00
parent f5e0b925fb
commit 0c44e9ddd3
70 changed files with 2624 additions and 1331 deletions
@@ -29,9 +29,12 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Control.App
private PropertySet propertySet;
private Dictionary<String, SbmAppConfig> appConfigs = new Dictionary<string, SbmAppConfig>();
private Dictionary<String, SbmEmailConfig> emailConfigs = new Dictionary<string, SbmEmailConfig>();
ushort sessionContextIdx_Control = 0;
// Singular databases.
private ISacsDatabase controlDatabase = null;
private ISacsDatabase templateDatabase = null;
// Session contexts.
private static ushort sessionContextIdx_Next = 100;
private ushort sessionContextIdx_Control = 0;
private class SessionContextData
{
public SessionContextData(SbmSessionContext_Web sessionContext)
@@ -39,8 +42,8 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Control.App
SessionContext = sessionContext;
}
public SbmSessionContext_Web SessionContext { get; }
public ISacsDatabase ControlDatabase { get; set; }
public ISacsDatabase BusMgrDatabase { get; set; }
public List<string> DbIdentifiers { get; } = new List<string>();
public ISacsDatabase BusMgrDatabase { get; set; }
}
private readonly Dictionary<ushort, SessionContextData> sessionContexts = new Dictionary<ushort, SessionContextData>();
@@ -58,7 +61,7 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Control.App
catch (Exception exc)
{
SaLogger.Error(GetType().Name + ".CTR " + ExceptionUtil.GetErrorStateMessage(exc));
throw exc;
throw;
}
}
@@ -76,11 +79,19 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Control.App
{
return sessionContexts.GetValue(index, null)?.SessionContext ?? null;
}
public override ISacsDatabase GetControlDatabase(SbmSessionContext sessionContext)
public override ISacsDatabase GetControlDatabase()
{
return sessionContexts.GetValue(sessionContext.Index, null)?.ControlDatabase;
return controlDatabase;
}
public override ISacsDatabase GetBusMgrDatabase(SbmSessionContext sessionContext)
public override ISacsDatabase GetTemplateDatabase()
{
return templateDatabase;
}
public override List<string> GetDbIdentifiers(SbmSessionContext sessionContext)
{
return sessionContexts.GetValue(sessionContext.Index, null)?.DbIdentifiers ?? new List<string>();
}
public override ISacsDatabase GetBusMgrDatabase(SbmSessionContext sessionContext)
{
return sessionContexts.GetValue(sessionContext.Index, null)?.BusMgrDatabase;
}
@@ -136,29 +147,46 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Control.App
LogApplicationStart(fn);
// Control database connection.
SacsDatabaseConsole.OdbcConfig config = new SacsDatabaseConsole.OdbcConfig();
config.location = AppConfig.ControlDatabase.Location;
config.user = AppConfig.ControlDatabase.User;
config.pword = AppConfig.ControlDatabase.Password;
SacsDatabase controlDatabase = SacsDatabaseConsole.OpenOdbcDatabase(config);
SacsDatabaseConsole.OdbcConfig odbcConfig = new SacsDatabaseConsole.OdbcConfig();
odbcConfig.location = AppConfig.ControlDatabase.Location;
odbcConfig.user = AppConfig.ControlDatabase.User;
odbcConfig.pword = AppConfig.ControlDatabase.Password;
controlDatabase = SacsDatabaseConsole.OpenOdbcDatabase(odbcConfig);
if (controlDatabase.HasErrorState())
SaLogger.Warn(fn + " Control Database initialisation error: " + controlDatabase.ErrorStateMessage);
// BusinessMgr database connection.
config = new SacsDatabaseConsole.OdbcConfig();
config.location = AppConfig.BusMgrDatabase.Location;
config.user = AppConfig.BusMgrDatabase.User;
config.pword = AppConfig.BusMgrDatabase.Password;
SacsDatabase busMgrDatabase = SacsDatabaseConsole.OpenOdbcDatabase(config);
if (busMgrDatabase.HasErrorState())
SaLogger.Warn(fn + " BusMgr Database initialisation error: " + busMgrDatabase.ErrorStateMessage);
// Template database connection.
if (AppConfig.TemplateDatabase != null)
{
odbcConfig = new SacsDatabaseConsole.OdbcConfig();
odbcConfig.location = AppConfig.TemplateDatabase.Location;
odbcConfig.user = AppConfig.TemplateDatabase.User;
odbcConfig.pword = AppConfig.TemplateDatabase.Password;
templateDatabase = SacsDatabaseConsole.OpenOdbcDatabase(odbcConfig);
if (templateDatabase.HasErrorState())
SaLogger.Warn(fn + " Template Database initialisation error: " + controlDatabase.ErrorStateMessage);
}
// Session context - only one context available/necessary (for now).
sessionContextIdx_Control = sessionContextIdx_Next++;
SessionContextData sessionContextData = new SessionContextData(new SbmSessionContext_Web(sessionContextIdx_Control, Sbm.Application.WebControl));
sessionContextData.ControlDatabase = controlDatabase;
sessionContextData.BusMgrDatabase = busMgrDatabase;
sessionContexts.Add(sessionContextData.SessionContext.Index, sessionContextData);
// BusinessMgr database connections.
foreach (SbmAppConfig.DatabaseConfig dbConfig in AppConfig.BusMgrDatabases)
{
odbcConfig = new SacsDatabaseConsole.OdbcConfig();
odbcConfig.location = dbConfig.Location;
odbcConfig.user = dbConfig.User;
odbcConfig.pword = dbConfig.Password;
SacsDatabase busMgrDatabase = SacsDatabaseConsole.OpenOdbcDatabase(odbcConfig);
if (busMgrDatabase.HasErrorState())
SaLogger.Warn(fn + " BusMgr Database: " + busMgrDatabase.DatabaseName + ". Initialisation error: " + busMgrDatabase.ErrorStateMessage);
// Session context.
ushort sessionContextIdx = sessionContextIdx_Next++;
if (sessionContextIdx_Control < 1)
sessionContextIdx_Control = sessionContextIdx;
SessionContextData sessionContextData = new SessionContextData(new SbmSessionContext_Web(sessionContextIdx, Sbm.Application.WebControl));
sessionContextData.DbIdentifiers.AddRange(dbConfig.Identifiers);
sessionContextData.BusMgrDatabase = busMgrDatabase;
sessionContexts.Add(sessionContextData.SessionContext.Index, sessionContextData);
}
}
catch (Exception exc)
{
@@ -166,9 +194,8 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Control.App
}
// Occasional startup processing.
SbmSessionContext sessionContext = GetSessionContext(sessionContextIdx_Control);
if (generateDatabaseDefinitions_Control)
GenerateDatabaseDefinition(sessionContext, SbmDbDfnGenerator.DatabaseInstance.Control, GetControlDatabase(sessionContext));
GenerateDatabaseDefinition(SbmDbDfnGenerator.DatabaseInstance.Control, GetControlDatabase());
if (generateDatabaseDefinitions_BusMgr)
{
// Use the 'template' database connection parameters.
@@ -176,24 +203,24 @@ namespace Sarand.BusinessMgr.Net.Core.Web.Control.App
config.location = AppConfig.TemplateDatabase.Location;
config.user = AppConfig.TemplateDatabase.User;
config.pword = AppConfig.TemplateDatabase.Password;
GenerateDatabaseDefinition(sessionContext, SbmDbDfnGenerator.DatabaseInstance.BusinessMgr, SacsDatabaseConsole.GenerateConnectionString(config));
GenerateDatabaseDefinition(SbmDbDfnGenerator.DatabaseInstance.BusinessMgr, GetTemplateDatabase());
}
}
//-------------------------------------------------------------------
// Generate database definition.
private void GenerateDatabaseDefinition(SbmSessionContext sessionContext, SbmDbDfnGenerator.DatabaseInstance dbInstance, ISacsDatabase db)
private void GenerateDatabaseDefinition(SbmDbDfnGenerator.DatabaseInstance dbInstance, ISacsDatabase db)
{
if (!generateDatabaseDefinitions_BusMgr || !SbmSystem.DebugMode || sessionContext == null) return;
if (!generateDatabaseDefinitions_BusMgr || !SbmSystem.DebugMode) return;
if (!StringUtil.EmptyOnNull(EnvironmentName).EqualsCI("Development")) return;
if (db == null || StringUtil.IsEmpty(db.ConnectionString)) return;
// Generate database definitions.
GenerateDatabaseDefinition(sessionContext, dbInstance, db.ConnectionString);
GenerateDatabaseDefinition(dbInstance, db.ConnectionString);
}
private void GenerateDatabaseDefinition(SbmSessionContext sessionContext, SbmDbDfnGenerator.DatabaseInstance dbInstance, String connectionString)
private void GenerateDatabaseDefinition(SbmDbDfnGenerator.DatabaseInstance dbInstance, String connectionString)
{
if (!generateDatabaseDefinitions_BusMgr || !SbmSystem.DebugMode || sessionContext == null) return;
if (!generateDatabaseDefinitions_BusMgr || !SbmSystem.DebugMode) return;
if (!StringUtil.EmptyOnNull(EnvironmentName).EqualsCI("Development")) return;
if (StringUtil.IsEmpty(connectionString)) return;
@@ -0,0 +1,41 @@
using Sarand.BusinessMgr.Net.Core.Web.App;
using Sarand.BusinessMgr.Net.Standard.Base.App;
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Security;
using static Sarand.BusinessMgr.Net.Standard.Base.App.Sbm.Config.Database;
using System.Collections.Generic;
using System;
using Newtonsoft.Json;
namespace Sarand.BusinessMgr.Net.Core.Web.Control.App
{
//=======================================================================
public class SbmSessionData_Control : SbmSessionData_Web
{
//-------------------------------------------------------------------
// Construction.
[JsonConstructor]
private SbmSessionData_Control(long sessionIdx, int itemIdx, SbmSessionContext sessionContext) :
base(sessionIdx, itemIdx, sessionContext)
{ }
/// <summary>
/// SessionData construction.
/// <para>SessionContext and UserAccount must be supplied.</para>
/// <para>Organisation is optional.</para>
/// </summary>
public SbmSessionData_Control(SbmSessionContext sessionContext) :
base(sessionContext)
{
}
//-------------------------------------------------------------------
protected override UserData CreateUserData(SbmSessionContext sessionContext, SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, List<SysIdString> supervisedOrganisations)
{
return null;
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Sarand.BusinessMgr.Net.Core.Web.App;
using Sarand.BusinessMgr.Net.Core.Web.Control.Models;
using System;
using System.Collections.Generic;
@@ -9,29 +10,39 @@ using System.Threading.Tasks;
namespace Sarand.BusinessMgr.Net.Core.Web.Control.Controllers
{
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
//======================================================================
public class HomeController : SbmController_Control
{
//-------------------------------------------------------------------
// Data members.
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
//-------------------------------------------------------------------
// Construction.
public HomeController(SbmLocaliser localiser, ILogger<HomeController> logger) :
base(localiser, logger)
{
}
public IActionResult Index()
//-------------------------------------------------------------------
public IActionResult Index()
{
// Home page.
Model_Home model = new Model_Home(Localiser);
return View();
}
//-------------------------------------------------------------------
public IActionResult Privacy()
{
return View();
}
public IActionResult Privacy()
{
return View();
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
//-------------------------------------------------------------------
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}
//======================================================================
}
@@ -0,0 +1,35 @@
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Sarand.BusinessMgr.Net.Core.Web.App;
using Sarand.BusinessMgr.Net.Core.Web.Control.App;
using Sarand.BusinessMgr.Net.Core.Web.Controllers;
using System;
namespace Sarand.BusinessMgr.Net.Core.Web.Control.Controllers
{
//======================================================================
public class SbmController_Control : SbmController_Base
{
//-------------------------------------------------------------------
// Data members.
//-------------------------------------------------------------------
// Protected construction.
protected SbmController_Control(SbmLocaliser localiser, Microsoft.Extensions.Logging.ILogger<SbmController_Control> logger) : base(localiser)
{
}
//-------------------------------------------------------------------
// Session data.
//-------------------------------------------------------------------
/// <summary>Online session data</summary>
protected SbmSessionData_Control SessionData_Control { get { return SessionData as SbmSessionData_Control; } }
protected override SbmSessionData_Web DeserializeSessionData(String sessionDataJson)
{
return JsonConvert.DeserializeObject<SbmSessionData_Control>(sessionDataJson, SbmSessionDataJsonSerializerSettings);
}
//-------------------------------------------------------------------
}
//======================================================================
}
@@ -0,0 +1,18 @@
using Sarand.BusinessMgr.Net.Core.Web.App;
namespace Sarand.BusinessMgr.Net.Core.Web.Control.Models
{
//=======================================================================
public class Model_Home : SbmModel_Control
{
//-------------------------------------------------------------------
// Construction.
public Model_Home(SbmLocaliser localiser) :
base(localiser)
{
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -0,0 +1,19 @@
using Sarand.BusinessMgr.Net.Core.Web.App;
using Sarand.BusinessMgr.Net.Core.Web.Models;
namespace Sarand.BusinessMgr.Net.Core.Web.Control.Models
{
//=======================================================================
public class SbmModel_Control : SbmModel_Base
{
//-------------------------------------------------------------------
// Protected construction.
protected SbmModel_Control(SbmLocaliser localiser) :
base(localiser)
{
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -1,52 +1,52 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<CopyRefAssembliesToPublishDirectory>false</CopyRefAssembliesToPublishDirectory>
<RootNamespace>Sarand.BusinessMgr.Net.Core.Web</RootNamespace>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<CopyRefAssembliesToPublishDirectory>false</CopyRefAssembliesToPublishDirectory>
<RootNamespace>Sarand.BusinessMgr.Net.Core.Web</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="jQuery.UI.Combined" Version="1.12.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="3.1.16" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="jQuery.UI.Combined" Version="1.13.2" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="6.0.31" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Common-VS\Workspace\SacsCoreWeb\SacsCoreWeb.csproj" />
<ProjectReference Include="..\..\..\Common-VS\Workspace\SacsStandardBase\SacsStandardBase.csproj" />
<ProjectReference Include="..\..\..\Common-VS\Workspace\SacsStandardDbas\SacsStandardDbas.csproj" />
<ProjectReference Include="..\..\..\Common-VS\Workspace\SacsStandardProc\SacsStandardProc.csproj" />
<ProjectReference Include="..\SaBusMgrCoreProcs\SaBusMgrCoreProcs.csproj" />
<ProjectReference Include="..\SaBusMgrCoreWeb\SaBusMgrCoreWeb.csproj" />
<ProjectReference Include="..\SaBusMgrStandardBase\SaBusMgrStandardBase.csproj" />
<ProjectReference Include="..\SaBusMgrStandardDbas\SaBusMgrStandardDbas.csproj" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Common-VS\Workspace\SacsCoreWeb\SacsCoreWeb.csproj" />
<ProjectReference Include="..\..\..\Common-VS\Workspace\SacsStandardBase\SacsStandardBase.csproj" />
<ProjectReference Include="..\..\..\Common-VS\Workspace\SacsStandardDbas\SacsStandardDbas.csproj" />
<ProjectReference Include="..\..\..\Common-VS\Workspace\SacsStandardProc\SacsStandardProc.csproj" />
<ProjectReference Include="..\SaBusMgrCoreProcs\SaBusMgrCoreProcs.csproj" />
<ProjectReference Include="..\SaBusMgrCoreWeb\SaBusMgrCoreWeb.csproj" />
<ProjectReference Include="..\SaBusMgrStandardBase\SaBusMgrStandardBase.csproj" />
<ProjectReference Include="..\SaBusMgrStandardDbas\SaBusMgrStandardDbas.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Control\Consoles\" />
</ItemGroup>
<ItemGroup>
<Folder Include="Control\Consoles\" />
</ItemGroup>
<ItemGroup>
<Content Update="appsettings.Development.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="appsettings.Machine.Sarand107.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="appsettings.Production.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<Content Update="appsettings.Development.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="appsettings.Machine.Sarand110.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="appsettings.Production.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
</ItemGroup>
</Project>
@@ -1,4 +1,12 @@
<!DOCTYPE html>
@model SbmModel_Control
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery AntiForgery;
@inject SbmLocaliser Localiser
@*
Application: BusinessMgr Web Control
Purpose: Page template.
*@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
@@ -34,7 +42,7 @@
<footer class="border-top footer text-muted">
<div class="container">
&copy; 2021 - Sarand BusinessMgr
@(Model.CopyrightNotice) - Sarand BusinessMgr
</div>
</footer>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
@@ -1,3 +1,4 @@
@using Sarand.BusinessMgr.Net.Core.Web.Control
@using Sarand.BusinessMgr.Net.Core.Web.App
@using Sarand.BusinessMgr.Net.Core.Web.Control
@using Sarand.BusinessMgr.Net.Core.Web.Control.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@@ -1,48 +0,0 @@
{
"AppConfigs": {
"SaBusMgr-Dev": {
"Environments": [ "Development" ],
"Instance": "Dev",
"ControlDatabase": {
"Location": "MsSql:Sarand107\\SQL2016.SaBusinessMgr_Control",
"User": "SaBusMgr-Control",
"Password": "sbm-c0Ntrul-dev-2021"
},
"BusMgrDatabases": [
{
"Code": "Sarand",
"Location": "MsSql:Sarand106\\SQL2014.SaBusinessMgr_Sarand"
},
{
"Code": "Cadix",
"Location": "MsSql:Sarand107\\SQL2016.SaBusinessMgr_Cadix",
"User": "SaBusMgr-Cadix",
"Password": "sbm-cul-dev-2021"
}
],
"BusMgrDatabase": {
"Code": "Cadix",
"Location": "MsSql:Sarand107\\SQL2016.SaBusinessMgr_Cadix",
"User": "SaBusMgr-Cadix",
"Password": "sbm-cul-dev-2021"
},
"TemplateDatabase": {
"Location": "MsSql:Sarand107\\SQL2016.SaBusinessMgr_Template",
"User": "SaBusMgr-Control",
"Password": "sbm-c0Ntrul-dev-2021"
},
"Email": {
"Context": "SBM-Dev",
"ContactUs": {
"AddressesTo": [ "dev@SaBusinessMgr.com" ]
}
},
"Documents": {
"RootFolder": "D:\\Sarand\\Projects\\Users\\AHoward\\VS2019\\BusinessMgr\\Docs"
},
"Logging": {
"RootFolder": "D:\\Sarand\\Projects\\Users\\AHoward\\VS2019\\BusinessMgr\\Logs\\WebControl"
}
}
}
}
@@ -0,0 +1,50 @@
{
"AppConfigs": {
"SaBusMgr-Dev": {
"Environments": [ "Development" ],
"Instance": "Dev",
"ControlDatabase": {
"Location": "MsSql:Roman\\SQL2016.SaBusinessMgr_Control",
"User": "sapphire",
"Password": "sarand"
},
"TemplateDatabase": {
"Location": "MsSql:Roman\\SQL2016.SaBusinessMgr_Template",
"User": "sapphire",
"Password": "sarand"
},
"BusMgrDatabases": [
{
"Identifiers": [ "Sarand" ],
"Location": "MsSql:Roman\\SQL2016.SaBusinessMgr_Sarand_Dev",
"User": "sapphire",
"Password": "sarand"
},
{
"Identifiers": [ "Cadix" ],
"Location": "MsSql:Roman\\SQL2016.SaBusinessMgr_Cadix",
"User": "sapphire",
"Password": "sarand"
},
{
"Identifiers": [ "BPE" ],
"Location": "MsSql:Roman\\SQL2016.SaBusinessMgr_BPE",
"User": "sapphire",
"Password": "sarand"
}
],
"Email": {
"Context": "SBM-Dev",
"ContactUs": {
"AddressesTo": [ "dev@SaBusinessMgr.com" ]
}
},
"Documents": {
"RootFolder": "D:\\Sarand\\Projects\\Users\\AHoward\\VS2022\\BusinessMgr\\Docs"
},
"Logging": {
"RootFolder": "D:\\Sarand\\Projects\\Users\\AHoward\\VS2022\\BusinessMgr\\Logs\\WebControl"
}
}
}
}