diff --git a/VAR.WebFormsCore.AspNetCore/Code/AspnetCoreWebContext.cs b/VAR.WebFormsCore.AspNetCore/Code/AspnetCoreWebContext.cs new file mode 100644 index 0000000..594155a --- /dev/null +++ b/VAR.WebFormsCore.AspNetCore/Code/AspnetCoreWebContext.cs @@ -0,0 +1,134 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.AspNetCore.Http; +using VAR.WebFormsCore.Code; + +namespace VAR.WebFormsCore.AspNetCore.Code; + +public class AspnetCoreWebContext : IWebContext +{ + private readonly HttpContext _context; + + public AspnetCoreWebContext(HttpContext context) + { + _context = context; + } + + public string RequestPath => _context.Request.Path; + + public string RequestMethod => _context.Request.Method; + + + private Dictionary? _requestHeader; + + public Dictionary RequestHeader + { + get + { + if (_requestHeader == null) + { + _requestHeader = _context.Request.Headers + .ToDictionary(p => p.Key, p => p.Value[0]); + } + + return _requestHeader; + } + } + + private Dictionary? _requestQuery; + + public Dictionary RequestQuery + { + get + { + if (_requestQuery == null) + { + _requestQuery = _context.Request.Query + .ToDictionary(p => p.Key, p => p.Value[0]); + } + + return _requestQuery; + } + } + + private Dictionary? _requestForm; + + public Dictionary RequestForm + { + get + { + if (_requestForm == null) + { + if (_context.Request.Method == "POST") + { + _requestForm = _context.Request.Form + .ToDictionary(p => p.Key, p => p.Value[0]); + } + else + { + _requestForm = new Dictionary(); + } + } + + return _requestForm; + } + } + + public void ResponseWrite(string text) + { + _context.Response.WriteAsync(text).GetAwaiter().GetResult(); + } + + public void ResponseWriteBin(byte[] content) + { + _context.Response.Body.WriteAsync(content).GetAwaiter().GetResult(); + } + + public void ResponseFlush() + { + _context.Response.Body.FlushAsync().GetAwaiter().GetResult(); + } + + public void ResponseRedirect(string url) + { + _context.Response.Redirect(url); + } + + public bool ResponseHasStarted => _context.Response.HasStarted; + + public int ResponseStatusCode + { + get => _context.Response.StatusCode; + set => _context.Response.StatusCode = value; + } + + public string? ResponseContentType + { + get => _context.Response.ContentType; + set => _context.Response.ContentType = value; + } + + public void SetResponseHeader(string key, string value) + { + _context.Response.Headers.SafeSet(key, value); + } + + public void PrepareCacheableResponse() + { + const int secondsInDay = 86400; + _context.Response.Headers.SafeSet("Cache-Control", $"public, max-age={secondsInDay}"); + string expireDate = DateTime.UtcNow.AddSeconds(secondsInDay) + .ToString("ddd, dd MMM yyyy HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture); + _context.Response.Headers.SafeSet("Expires", $"{expireDate} GMT"); + } + + public void PrepareUncacheableResponse() + { + _context.Response.Headers.SafeSet("Cache-Control", "max-age=0, no-cache, no-store"); + string expireDate = DateTime.UtcNow.AddSeconds(-1500) + .ToString("ddd, dd MMM yyyy HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture); + _context.Response.Headers.SafeSet("Expires", $"{expireDate} GMT"); + } + +} \ No newline at end of file diff --git a/VAR.WebFormsCore.AspNetCore/Code/ExtensionMethods.cs b/VAR.WebFormsCore.AspNetCore/Code/ExtensionMethods.cs new file mode 100644 index 0000000..0c57941 --- /dev/null +++ b/VAR.WebFormsCore.AspNetCore/Code/ExtensionMethods.cs @@ -0,0 +1,18 @@ +using Microsoft.AspNetCore.Http; + +namespace VAR.WebFormsCore.AspNetCore.Code +{ + public static class ExtensionMethods + { + #region IHeaderDictionary + + public static void SafeSet(this IHeaderDictionary header, string key, string value) { header[key] = value; } + + public static void SafeDel(this IHeaderDictionary header, string key) + { + if (header.ContainsKey(key)) { header.Remove(key); } + } + + #endregion IHeaderDictionary + } +} \ No newline at end of file diff --git a/VAR.WebFormsCore.AspNetCore/Code/GlobalRouterMiddleware.cs b/VAR.WebFormsCore.AspNetCore/Code/GlobalRouterMiddleware.cs new file mode 100644 index 0000000..c570c84 --- /dev/null +++ b/VAR.WebFormsCore.AspNetCore/Code/GlobalRouterMiddleware.cs @@ -0,0 +1,61 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using VAR.WebFormsCore.Code; + +namespace VAR.WebFormsCore.AspNetCore.Code; + +public class GlobalRouterMiddleware +{ + private readonly GlobalRouter _globalRouter = new(); + + public GlobalRouterMiddleware(RequestDelegate next, IWebHostEnvironment env) + { + ServerHelpers.SetContentRoot(env.ContentRootPath); + } + + public async Task Invoke(HttpContext httpContext) + { + httpContext.Response.Headers.SafeDel("Server"); + httpContext.Response.Headers.SafeDel("X-Powered-By"); + httpContext.Response.Headers.SafeSet("X-Content-Type-Options", "nosniff"); + httpContext.Response.Headers.SafeSet("X-Frame-Options", "SAMEORIGIN"); + httpContext.Response.Headers.SafeSet("X-XSS-Protection", "1; mode=block"); + + IWebContext webContext = new AspnetCoreWebContext(httpContext); + + try + { + _globalRouter.RouteRequest(webContext); + await httpContext.Response.Body.FlushAsync(); + } + catch (Exception ex) + { + if (IsIgnoreException(ex) == false) + { + // TODO: Implement better error logging + Console.WriteLine("!!!!!!!!!!"); + Console.Write("Message: {0}\nStacktrace: {1}\n", ex.Message, ex.StackTrace); + + GlobalErrorHandler.HandleError(webContext, ex); + } + } + } + + private static bool IsIgnoreException(Exception ex) { return ex is ThreadAbortException; } + +} + +public static class GlobalRouterMiddlewareExtensions +{ + public static IApplicationBuilder UseGlobalRouterMiddleware( + this IApplicationBuilder builder, + IWebHostEnvironment env + ) + { + return builder.UseMiddleware(env); + } +} \ No newline at end of file diff --git a/VAR.WebFormsCore.AspNetCore/Program.cs b/VAR.WebFormsCore.AspNetCore/Program.cs new file mode 100644 index 0000000..ac861d3 --- /dev/null +++ b/VAR.WebFormsCore.AspNetCore/Program.cs @@ -0,0 +1,19 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; + +namespace VAR.WebFormsCore.AspNetCore; + +public static class DefaultMain +{ + public static void WebFormCoreMain(string[] args) + { + CreateHostBuilder(args).Build().Run(); + } + + private static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); +} \ No newline at end of file diff --git a/VAR.WebFormsCore.AspNetCore/Startup.cs b/VAR.WebFormsCore.AspNetCore/Startup.cs new file mode 100644 index 0000000..71b2c0a --- /dev/null +++ b/VAR.WebFormsCore.AspNetCore/Startup.cs @@ -0,0 +1,24 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Server.Kestrel.Core; +using Microsoft.Extensions.DependencyInjection; +using VAR.WebFormsCore.AspNetCore.Code; + +namespace VAR.WebFormsCore.AspNetCore; + +public class Startup +{ + public void ConfigureServices(IServiceCollection services) + { + // If using Kestrel: + services.Configure(options => + { + options.AddServerHeader = false; + }); + } + + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + app.UseGlobalRouterMiddleware(env); + } +} \ No newline at end of file diff --git a/VAR.WebFormsCore.AspNetCore/VAR.WebFormsCore.AspNetCore.csproj b/VAR.WebFormsCore.AspNetCore/VAR.WebFormsCore.AspNetCore.csproj new file mode 100644 index 0000000..f599172 --- /dev/null +++ b/VAR.WebFormsCore.AspNetCore/VAR.WebFormsCore.AspNetCore.csproj @@ -0,0 +1,13 @@ + + + + Library + net7.0 + enable + + + + + + + diff --git a/VAR.WebFormsCore.TestWebApp/FrmDefault.cs b/VAR.WebFormsCore.TestWebApp/FrmDefault.cs index ea99d82..d8ac636 100644 --- a/VAR.WebFormsCore.TestWebApp/FrmDefault.cs +++ b/VAR.WebFormsCore.TestWebApp/FrmDefault.cs @@ -1,3 +1,4 @@ +using System; using VAR.WebFormsCore.Code; using VAR.WebFormsCore.Controls; using VAR.WebFormsCore.Pages; diff --git a/VAR.WebFormsCore.TestWebApp/Program.cs b/VAR.WebFormsCore.TestWebApp/Program.cs index 0890000..8427abf 100644 --- a/VAR.WebFormsCore.TestWebApp/Program.cs +++ b/VAR.WebFormsCore.TestWebApp/Program.cs @@ -1,17 +1,12 @@ -namespace VAR.WebFormsCore.TestWebApp -{ - public static class Program - { - public static void Main(string[] args) - { - CreateHostBuilder(args).Build().Run(); - } +using VAR.WebFormsCore.AspNetCore; - private static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => - { - webBuilder.UseStartup(); - }); +namespace VAR.WebFormsCore.TestWebApp; + +public static class Program +{ + public static void Main(string[] args) + { + DefaultMain.WebFormCoreMain(args); } -} + +} \ No newline at end of file diff --git a/VAR.WebFormsCore.TestWebApp/Startup.cs b/VAR.WebFormsCore.TestWebApp/Startup.cs deleted file mode 100644 index 71fc70d..0000000 --- a/VAR.WebFormsCore.TestWebApp/Startup.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Microsoft.AspNetCore.Server.Kestrel.Core; -using VAR.WebFormsCore.Code; - -namespace VAR.WebFormsCore.TestWebApp -{ - public class Startup - { - public void ConfigureServices(IServiceCollection services) - { - // If using Kestrel: - services.Configure(options => - { - options.AddServerHeader = false; - }); - } - - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - app.UseGlobalRouterMiddleware(env); - } - } -} \ No newline at end of file diff --git a/VAR.WebFormsCore.TestWebApp/TestWebAppGlobalConfig.cs b/VAR.WebFormsCore.TestWebApp/TestWebAppGlobalConfig.cs index ed1177a..dd363af 100644 --- a/VAR.WebFormsCore.TestWebApp/TestWebAppGlobalConfig.cs +++ b/VAR.WebFormsCore.TestWebApp/TestWebAppGlobalConfig.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using VAR.WebFormsCore.Code; namespace VAR.WebFormsCore.TestWebApp; @@ -14,12 +15,12 @@ public class TestWebAppGlobalConfig : IGlobalConfig public List AllowedExtensions { get; } = new() { ".png", ".jpg", ".jpeg", ".gif", ".ico", ".wav", ".mp3", ".ogg", ".mp4", ".webm", ".webp", ".mkv", ".avi" }; - public bool IsUserAuthenticated(HttpContext context) + public bool IsUserAuthenticated(IWebContext context) { return false; } - public void UserDeauthenticate(HttpContext context) + public void UserDeauthenticate(IWebContext context) { } } \ No newline at end of file diff --git a/VAR.WebFormsCore.TestWebApp/VAR.WebFormsCore.TestWebApp.csproj b/VAR.WebFormsCore.TestWebApp/VAR.WebFormsCore.TestWebApp.csproj index 34ca235..e1d011d 100644 --- a/VAR.WebFormsCore.TestWebApp/VAR.WebFormsCore.TestWebApp.csproj +++ b/VAR.WebFormsCore.TestWebApp/VAR.WebFormsCore.TestWebApp.csproj @@ -3,10 +3,10 @@ net7.0 enable - enable + diff --git a/VAR.WebFormsCore.sln b/VAR.WebFormsCore.sln index 27df3df..632759a 100644 --- a/VAR.WebFormsCore.sln +++ b/VAR.WebFormsCore.sln @@ -4,6 +4,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VAR.WebFormsCore", "VAR.Web EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VAR.WebFormsCore.TestWebApp", "VAR.WebFormsCore.TestWebApp\VAR.WebFormsCore.TestWebApp.csproj", "{0D81464B-802D-4ECA-92C8-427F481A4583}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VAR.WebFormsCore.AspNetCore", "VAR.WebFormsCore.AspNetCore\VAR.WebFormsCore.AspNetCore.csproj", "{378B98EF-9269-4B96-B894-1B0F9B24EEC2}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -18,5 +20,9 @@ Global {0D81464B-802D-4ECA-92C8-427F481A4583}.Debug|Any CPU.Build.0 = Debug|Any CPU {0D81464B-802D-4ECA-92C8-427F481A4583}.Release|Any CPU.ActiveCfg = Release|Any CPU {0D81464B-802D-4ECA-92C8-427F481A4583}.Release|Any CPU.Build.0 = Release|Any CPU + {378B98EF-9269-4B96-B894-1B0F9B24EEC2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {378B98EF-9269-4B96-B894-1B0F9B24EEC2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {378B98EF-9269-4B96-B894-1B0F9B24EEC2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {378B98EF-9269-4B96-B894-1B0F9B24EEC2}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/VAR.WebFormsCore/Code/Bundler.cs b/VAR.WebFormsCore/Code/Bundler.cs index 9e199cc..9cee5d2 100644 --- a/VAR.WebFormsCore/Code/Bundler.cs +++ b/VAR.WebFormsCore/Code/Bundler.cs @@ -3,105 +3,103 @@ using System.IO; using System.Linq; using System.Reflection; using System.Text; -using Microsoft.AspNetCore.Http; -namespace VAR.WebFormsCore.Code +namespace VAR.WebFormsCore.Code; + +public class Bundler { - public class Bundler + #region Declarations + + private readonly Assembly? _assembly; + private readonly string? _assemblyNamespace; + private List? _assemblyFiles; + private readonly string? _absolutePath; + private List? _absoluteFiles; + + #endregion Declarations + + #region Properties + + private List AssemblyFiles { - #region Declarations - - private readonly Assembly? _assembly; - private readonly string? _assemblyNamespace; - private List? _assemblyFiles; - private readonly string? _absolutePath; - private List? _absoluteFiles; - - #endregion Declarations - - #region Properties - - private List AssemblyFiles + get { - get + if (_assemblyFiles != null) { return _assemblyFiles; } + + if (_assembly == null || string.IsNullOrEmpty(_assemblyNamespace)) { - if (_assemblyFiles != null) { return _assemblyFiles; } - - if (_assembly == null || string.IsNullOrEmpty(_assemblyNamespace)) - { - _assemblyFiles = new List(); - return _assemblyFiles; - } - - string assemblyPath = string.Concat(_assembly.GetName().Name, ".", _assemblyNamespace, "."); - _assemblyFiles = _assembly.GetManifestResourceNames().Where(r => r.StartsWith(assemblyPath)).ToList(); + _assemblyFiles = new List(); return _assemblyFiles; } + + string assemblyPath = string.Concat(_assembly.GetName().Name, ".", _assemblyNamespace, "."); + _assemblyFiles = _assembly.GetManifestResourceNames().Where(r => r.StartsWith(assemblyPath)).ToList(); + return _assemblyFiles; } + } - private List AbsoluteFiles + private List AbsoluteFiles + { + get { - get + if (_absoluteFiles != null) { return _absoluteFiles; } + + if (string.IsNullOrEmpty(_absolutePath)) { - if (_absoluteFiles != null) { return _absoluteFiles; } - - if (string.IsNullOrEmpty(_absolutePath)) - { - _absoluteFiles = new List(); - return _absoluteFiles; - } - - DirectoryInfo dir = new DirectoryInfo(_absolutePath); - FileInfo[] files = dir.GetFiles(); - _absoluteFiles = files.OrderBy(file => file.FullName).Select(file2 => file2.FullName).ToList(); + _absoluteFiles = new List(); return _absoluteFiles; } + + DirectoryInfo dir = new DirectoryInfo(_absolutePath); + FileInfo[] files = dir.GetFiles(); + _absoluteFiles = files.OrderBy(file => file.FullName).Select(file2 => file2.FullName).ToList(); + return _absoluteFiles; } - - #endregion Properties - - #region Creator - - public Bundler(Assembly? assembly = null, string? assemblyNamespace = null, string? absolutePath = null) - { - _assembly = assembly; - _assemblyNamespace = assemblyNamespace; - _absolutePath = absolutePath; - } - - #endregion Creator - - #region Public methods - - private static readonly Encoding Utf8Encoding = new UTF8Encoding(); - - public void WriteResponse(HttpResponse response, string contentType) - { - StringWriter textWriter = new StringWriter(); - response.ContentType = contentType; - foreach (string fileName in AssemblyFiles) - { - Stream? resourceStream = _assembly?.GetManifestResourceStream(fileName); - if (resourceStream != null) - { - string fileContent = new StreamReader(resourceStream).ReadToEnd(); - textWriter.Write(fileContent); - } - - textWriter.Write("\n\n"); - } - - foreach (string fileName in AbsoluteFiles) - { - string fileContent = File.ReadAllText(fileName); - textWriter.Write(fileContent); - textWriter.Write("\n\n"); - } - - byte[] byteObject = Utf8Encoding.GetBytes(textWriter.ToString()); - response.Body.WriteAsync(byteObject).GetAwaiter().GetResult(); - } - - #endregion Public methods } + + #endregion Properties + + #region Creator + + public Bundler(Assembly? assembly = null, string? assemblyNamespace = null, string? absolutePath = null) + { + _assembly = assembly; + _assemblyNamespace = assemblyNamespace; + _absolutePath = absolutePath; + } + + #endregion Creator + + #region Public methods + + private static readonly Encoding Utf8Encoding = new UTF8Encoding(); + + public void WriteResponse(IWebContext context, string contentType) + { + StringWriter textWriter = new StringWriter(); + context.ResponseContentType = contentType; + foreach (string fileName in AssemblyFiles) + { + Stream? resourceStream = _assembly?.GetManifestResourceStream(fileName); + if (resourceStream != null) + { + string fileContent = new StreamReader(resourceStream).ReadToEnd(); + textWriter.Write(fileContent); + } + + textWriter.Write("\n\n"); + } + + foreach (string fileName in AbsoluteFiles) + { + string fileContent = File.ReadAllText(fileName); + textWriter.Write(fileContent); + textWriter.Write("\n\n"); + } + + byte[] byteObject = Utf8Encoding.GetBytes(textWriter.ToString()); + context.ResponseWriteBin(byteObject); + } + + #endregion Public methods } \ No newline at end of file diff --git a/VAR.WebFormsCore/Code/ExtensionMethods.cs b/VAR.WebFormsCore/Code/ExtensionMethods.cs index 93d5cf0..d40b8a9 100644 --- a/VAR.WebFormsCore/Code/ExtensionMethods.cs +++ b/VAR.WebFormsCore/Code/ExtensionMethods.cs @@ -1,66 +1,45 @@ -using System; -using System.Text; -using Microsoft.AspNetCore.Http; -using VAR.Json; - -namespace VAR.WebFormsCore.Code -{ - public static class ExtensionMethods - { - #region HttpContext - - public static string GetRequestParameter(this HttpContext context, string parameter) - { - if (context.Request.Method == "POST") - { - foreach (string key in context.Request.Form.Keys) - { - if (string.IsNullOrEmpty(key) == false && key == parameter) { return context.Request.Form[key][0] ?? string.Empty; } - } - } - - foreach (string key in context.Request.Query.Keys) - { - if (string.IsNullOrEmpty(key) == false && key == parameter) { return context.Request.Query[key][0] ?? string.Empty; } - } - - return string.Empty; - } - - private static readonly Encoding Utf8Encoding = new UTF8Encoding(); - - public static void ResponseObject(this HttpContext context, object obj, string contentType = "text/json") - { - context.Response.ContentType = contentType; - string strObject = JsonWriter.WriteObject(obj); - byte[] byteObject = Utf8Encoding.GetBytes(strObject); - context.Response.Body.WriteAsync(byteObject).GetAwaiter().GetResult(); - } - - public static void SafeSet(this IHeaderDictionary header, string key, string value) { header[key] = value; } - - public static void SafeDel(this IHeaderDictionary header, string key) - { - if (header.ContainsKey(key)) { header.Remove(key); } - } - - public static void PrepareCacheableResponse(this HttpResponse response) - { - const int secondsInDay = 86400; - response.Headers.SafeSet("Cache-Control", $"public, max-age={secondsInDay}"); - string expireDate = DateTime.UtcNow.AddSeconds(secondsInDay) - .ToString("ddd, dd MMM yyyy HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture); - response.Headers.SafeSet("Expires", expireDate + " GMT"); - } - - public static void PrepareUncacheableResponse(this HttpResponse response) - { - response.Headers.SafeSet("Cache-Control", "max-age=0, no-cache, no-store"); - string expireDate = DateTime.UtcNow.AddSeconds(-1500) - .ToString("ddd, dd MMM yyyy HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture); - response.Headers.SafeSet("Expires", expireDate + " GMT"); - } - - #endregion HttpContext - } +using System.Text; +using VAR.Json; + +namespace VAR.WebFormsCore.Code; + +public static class ExtensionMethods +{ + #region IWebContext + + public static string GetRequestParameter(this IWebContext context, string parameter) + { + if (context.RequestMethod == "POST") + { + foreach (string key in context.RequestForm.Keys) + { + if (string.IsNullOrEmpty(key) == false && key == parameter) + { + return context.RequestForm[key] ?? string.Empty; + } + } + } + + foreach (string key in context.RequestQuery.Keys) + { + if (string.IsNullOrEmpty(key) == false && key == parameter) + { + return context.RequestQuery[key] ?? string.Empty; + } + } + + return string.Empty; + } + + private static readonly Encoding Utf8Encoding = new UTF8Encoding(); + + public static void ResponseObject(this IWebContext context, object obj, string contentType = "text/json") + { + context.ResponseContentType = contentType; + string strObject = JsonWriter.WriteObject(obj); + byte[] byteObject = Utf8Encoding.GetBytes(strObject); + context.ResponseWriteBin(byteObject); + } + + #endregion IWebContext } \ No newline at end of file diff --git a/VAR.WebFormsCore/Code/GlobalConfig.cs b/VAR.WebFormsCore/Code/GlobalConfig.cs index 11c6e0b..9905325 100644 --- a/VAR.WebFormsCore/Code/GlobalConfig.cs +++ b/VAR.WebFormsCore/Code/GlobalConfig.cs @@ -1,54 +1,52 @@ using System; using System.Collections.Generic; using System.Linq; -using Microsoft.AspNetCore.Http; -namespace VAR.WebFormsCore.Code +namespace VAR.WebFormsCore.Code; + +public static class GlobalConfig { - public static class GlobalConfig + private static IGlobalConfig? _globalConfig; + + public static IGlobalConfig Get() { - private static IGlobalConfig? _globalConfig; + if (_globalConfig != null) { return _globalConfig; } - public static IGlobalConfig Get() + Type iGlobalConfig = typeof(IGlobalConfig); + Type? foundGlobalConfig = AppDomain.CurrentDomain + .GetAssemblies() + .SelectMany(x => x.GetTypes()) + .FirstOrDefault( + x => + x is { IsAbstract: false, IsInterface: false, IsPublic: true } && + iGlobalConfig.IsAssignableFrom(x) + ); + if(foundGlobalConfig != null) { - if (_globalConfig != null) { return _globalConfig; } - - Type iGlobalConfig = typeof(IGlobalConfig); - Type? foundGlobalConfig = AppDomain.CurrentDomain - .GetAssemblies() - .SelectMany(x => x.GetTypes()) - .FirstOrDefault( - x => - x is { IsAbstract: false, IsInterface: false, IsPublic: true } && - iGlobalConfig.IsAssignableFrom(x) - ); - if(foundGlobalConfig != null) - { - _globalConfig = ObjectActivator.CreateInstance(foundGlobalConfig) as IGlobalConfig; - } - - return _globalConfig ??= new DefaultGlobalConfig(); + _globalConfig = ObjectActivator.CreateInstance(foundGlobalConfig) as IGlobalConfig; } - // TODO: Better default global config - private class DefaultGlobalConfig : IGlobalConfig - { - public string Title => string.Empty; - public string TitleSeparator => string.Empty; - public string Author => string.Empty; - public string Copyright => string.Empty; - public string DefaultHandler => string.Empty; - public string LoginHandler => string.Empty; - public List AllowedExtensions { get; } = new(); - - public bool IsUserAuthenticated(HttpContext context) - { - return false; - } + return _globalConfig ??= new DefaultGlobalConfig(); + } - public void UserDeauthenticate(HttpContext context) - { - } + // TODO: Better default global config + private class DefaultGlobalConfig : IGlobalConfig + { + public string Title => string.Empty; + public string TitleSeparator => string.Empty; + public string Author => string.Empty; + public string Copyright => string.Empty; + public string DefaultHandler => string.Empty; + public string LoginHandler => string.Empty; + public List AllowedExtensions { get; } = new(); + + public bool IsUserAuthenticated(IWebContext context) + { + return false; + } + + public void UserDeauthenticate(IWebContext context) + { } } } \ No newline at end of file diff --git a/VAR.WebFormsCore/Code/GlobalErrorHandler.cs b/VAR.WebFormsCore/Code/GlobalErrorHandler.cs index 1dd42cd..752180b 100644 --- a/VAR.WebFormsCore/Code/GlobalErrorHandler.cs +++ b/VAR.WebFormsCore/Code/GlobalErrorHandler.cs @@ -1,66 +1,64 @@ using System; using System.Text; -using Microsoft.AspNetCore.Http; using VAR.WebFormsCore.Pages; -namespace VAR.WebFormsCore.Code +namespace VAR.WebFormsCore.Code; + +public static class GlobalErrorHandler { - public static class GlobalErrorHandler + #region Private methods + + private static void ShowInternalError(IWebContext context, Exception ex) { - #region Private methods - - private static void ShowInternalError(HttpContext context, Exception ex) + try { - try + context.ResponseStatusCode = 500; + + StringBuilder sbOutput = new StringBuilder(); + sbOutput.Append("

Internal error

"); + Exception? exAux = ex; + while (exAux != null) { - context.Response.StatusCode = 500; - - StringBuilder sbOutput = new StringBuilder(); - sbOutput.Append("

Internal error

"); - Exception? exAux = ex; - while (exAux != null) - { - sbOutput.Append($"

Message: {exAux.Message}

"); - sbOutput.Append($"

StackTrace:

{exAux.StackTrace}
"); - exAux = exAux.InnerException; - } - - // Fill response to 512 bytes to avoid browser "beauty" response of errors. - long fillResponse = 512 - sbOutput.Length; - if (fillResponse > 0) - { - sbOutput.Append(""); - } - - context.Response.WriteAsync(sbOutput.ToString()).GetAwaiter().GetResult(); - context.Response.Body.FlushAsync().GetAwaiter().GetResult(); + sbOutput.Append($"

Message: {exAux.Message}

"); + sbOutput.Append($"

StackTrace:

{exAux.StackTrace}
"); + exAux = exAux.InnerException; } - catch + + // Fill response to 512 bytes to avoid browser "beauty" response of errors. + long fillResponse = 512 - sbOutput.Length; + if (fillResponse > 0) { - /* Nom nom nom */ + sbOutput.Append(""); } + + context.ResponseWrite(sbOutput.ToString()); + context.ResponseFlush(); } - - #endregion Private methods - - #region Public methods - - public static void HandleError(HttpContext context, Exception ex) + catch { - try - { - IHttpHandler frmError = new FrmError(ex); - //context.Response.Clear(); - //context.Handler = frmError; - frmError.ProcessRequest(context); - context.Response.Body.FlushAsync().GetAwaiter().GetResult(); - } - catch { ShowInternalError(context, ex); } + /* Nom nom nom */ } - - #endregion Public methods } + + #endregion Private methods + + #region Public methods + + public static void HandleError(IWebContext context, Exception ex) + { + try + { + IHttpHandler frmError = new FrmError(ex); + //context.Response.Clear(); + //context.Handler = frmError; + frmError.ProcessRequest(context); + context.ResponseFlush(); + } + catch { ShowInternalError(context, ex); } + } + + #endregion Public methods } \ No newline at end of file diff --git a/VAR.WebFormsCore/Code/GlobalRouter.cs b/VAR.WebFormsCore/Code/GlobalRouter.cs new file mode 100644 index 0000000..41a9dee --- /dev/null +++ b/VAR.WebFormsCore/Code/GlobalRouter.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; + +namespace VAR.WebFormsCore.Code; + +public class GlobalRouter +{ + public void RouteRequest(IWebContext context) + { + string path = context.RequestPath; + string file = Path.GetFileName(path); + if (string.IsNullOrEmpty(file)) { file = GlobalConfig.Get().DefaultHandler; } + + // Pass allowed extensions requests + string extension = Path.GetExtension(path).ToLower(); + if (GlobalConfig.Get().AllowedExtensions.Contains(extension)) + { + string filePath = ServerHelpers.MapContentPath(path); + if (File.Exists(filePath)) + { + StaticFileHelper.ResponseStaticFile(context, filePath); + return; + } + else + { + // TODO: FrmNotFound + throw new Exception($"NotFound: {path}"); + } + } + + IHttpHandler? handler = GetHandler(file); + if (handler == null) + { + // TODO: FrmNotFound + throw new Exception($"NotFound: {path}"); + } + + // Use handler + handler.ProcessRequest(context); + } + + private static readonly Dictionary Handlers = new(); + + private static IHttpHandler? GetHandler(string typeName) + { + if (string.IsNullOrEmpty(typeName)) { return null; } + + Type? type; + lock (Handlers) + { + if (Handlers.TryGetValue(typeName, out type)) + { + IHttpHandler? handler = ObjectActivator.CreateInstance(type) as IHttpHandler; + return handler; + } + } + + // Search type on executing assembly + Assembly asm = Assembly.GetExecutingAssembly(); + Type[] types = asm.GetTypes(); + foreach (Type typeAux in types) + { + if (typeAux.FullName?.EndsWith(typeName) == true) + { + type = typeAux; + break; + } + } + + // Search type on all loaded assemblies + if (type == null) + { + Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); + foreach (Assembly asmAux in assemblies) + { + types = asmAux.GetTypes(); + foreach (Type typeAux in types) + { + if (typeAux.FullName?.EndsWith(typeName) != true) { continue; } + + type = typeAux; + break; + } + + if (type != null) { break; } + } + } + + // Use found type + if (type != null) + { + IHttpHandler? handler = ObjectActivator.CreateInstance(type) as IHttpHandler; + if (handler != null) + { + lock (Handlers) + { + if (Handlers.ContainsKey(typeName) == false) + { + Handlers.Add(typeName, type); + } + } + } + + return handler; + } + + return null; + } +} \ No newline at end of file diff --git a/VAR.WebFormsCore/Code/GlobalRouterMiddleware.cs b/VAR.WebFormsCore/Code/GlobalRouterMiddleware.cs deleted file mode 100644 index 384b964..0000000 --- a/VAR.WebFormsCore/Code/GlobalRouterMiddleware.cs +++ /dev/null @@ -1,158 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; - -namespace VAR.WebFormsCore.Code -{ - public class GlobalRouterMiddleware - { - public GlobalRouterMiddleware(RequestDelegate next, IWebHostEnvironment env) - { - ServerHelpers.SetContentRoot(env.ContentRootPath); - } - - public async Task Invoke(HttpContext httpContext) - { - httpContext.Response.Headers.SafeDel("Server"); - httpContext.Response.Headers.SafeDel("X-Powered-By"); - httpContext.Response.Headers.SafeSet("X-Content-Type-Options", "nosniff"); - httpContext.Response.Headers.SafeSet("X-Frame-Options", "SAMEORIGIN"); - httpContext.Response.Headers.SafeSet("X-XSS-Protection", "1; mode=block"); - - try - { - RouteRequest(httpContext); - await httpContext.Response.Body.FlushAsync(); - } - catch (Exception ex) - { - if (IsIgnoreException(ex) == false) - { - // TODO: Implement better error logging - Console.WriteLine("!!!!!!!!!!"); - Console.Write("Message: {0}\nStacktrace: {1}\n", ex.Message, ex.StackTrace); - - GlobalErrorHandler.HandleError(httpContext, ex); - } - } - } - - private static bool IsIgnoreException(Exception ex) { return ex is ThreadAbortException; } - - private void RouteRequest(HttpContext context) - { - string path = context.Request.Path; - string file = Path.GetFileName(path); - if (string.IsNullOrEmpty(file)) { file = GlobalConfig.Get().DefaultHandler; } - - // Pass allowed extensions requests - string extension = Path.GetExtension(path).ToLower(); - if (GlobalConfig.Get().AllowedExtensions.Contains(extension)) - { - string filePath = ServerHelpers.MapContentPath(path); - if (File.Exists(filePath)) - { - StaticFileHelper.ResponseStaticFile(context, filePath); - return; - } - else - { - // TODO: FrmNotFound - throw new Exception($"NotFound: {path}"); - } - } - - IHttpHandler? handler = GetHandler(file); - if (handler == null) - { - // TODO: FrmNotFound - throw new Exception($"NotFound: {path}"); - } - - // Use handler - handler.ProcessRequest(context); - } - - private static readonly Dictionary Handlers = new(); - - private static IHttpHandler? GetHandler(string typeName) - { - if (string.IsNullOrEmpty(typeName)) { return null; } - - Type? type; - lock (Handlers) - { - if (Handlers.TryGetValue(typeName, out type)) - { - IHttpHandler? handler = ObjectActivator.CreateInstance(type) as IHttpHandler; - return handler; - } - } - - // Search type on executing assembly - Assembly asm = Assembly.GetExecutingAssembly(); - Type[] types = asm.GetTypes(); - foreach (Type typeAux in types) - { - if (typeAux.FullName?.EndsWith(typeName) == true) - { - type = typeAux; - break; - } - } - - // Search type on all loaded assemblies - if (type == null) - { - Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); - foreach (Assembly asmAux in assemblies) - { - types = asmAux.GetTypes(); - foreach (Type typeAux in types) - { - if (typeAux.FullName?.EndsWith(typeName) != true) { continue; } - - type = typeAux; - break; - } - - if (type != null) { break; } - } - } - - // Use found type - if (type != null) - { - IHttpHandler? handler = ObjectActivator.CreateInstance(type) as IHttpHandler; - if (handler != null) - { - lock (Handlers) - { - Handlers.TryAdd(typeName, type); - } - } - - return handler; - } - - return null; - } - } - - public static class GlobalRouterMiddlewareExtensions - { - public static IApplicationBuilder UseGlobalRouterMiddleware( - this IApplicationBuilder builder, - IWebHostEnvironment env - ) - { - return builder.UseMiddleware(env); - } - } -} \ No newline at end of file diff --git a/VAR.WebFormsCore/Code/IGlobalConfig.cs b/VAR.WebFormsCore/Code/IGlobalConfig.cs index c15427a..c139cad 100644 --- a/VAR.WebFormsCore/Code/IGlobalConfig.cs +++ b/VAR.WebFormsCore/Code/IGlobalConfig.cs @@ -1,19 +1,17 @@ using System.Collections.Generic; -using Microsoft.AspNetCore.Http; -namespace VAR.WebFormsCore.Code +namespace VAR.WebFormsCore.Code; + +public interface IGlobalConfig { - public interface IGlobalConfig - { - string Title { get; } - string TitleSeparator { get; } - string Author { get; } - string Copyright { get; } - string DefaultHandler { get; } - string LoginHandler { get; } - List AllowedExtensions { get; } + string Title { get; } + string TitleSeparator { get; } + string Author { get; } + string Copyright { get; } + string DefaultHandler { get; } + string LoginHandler { get; } + List AllowedExtensions { get; } - bool IsUserAuthenticated(HttpContext context); - void UserDeauthenticate(HttpContext context); - } + bool IsUserAuthenticated(IWebContext context); + void UserDeauthenticate(IWebContext context); } \ No newline at end of file diff --git a/VAR.WebFormsCore/Code/IHttpHandler.cs b/VAR.WebFormsCore/Code/IHttpHandler.cs index b5eabac..f91b16b 100644 --- a/VAR.WebFormsCore/Code/IHttpHandler.cs +++ b/VAR.WebFormsCore/Code/IHttpHandler.cs @@ -1,9 +1,6 @@ -using Microsoft.AspNetCore.Http; +namespace VAR.WebFormsCore.Code; -namespace VAR.WebFormsCore.Code +public interface IHttpHandler { - public interface IHttpHandler - { - void ProcessRequest(HttpContext context); - } + void ProcessRequest(IWebContext context); } \ No newline at end of file diff --git a/VAR.WebFormsCore/Code/IWebContext.cs b/VAR.WebFormsCore/Code/IWebContext.cs new file mode 100644 index 0000000..985e50c --- /dev/null +++ b/VAR.WebFormsCore/Code/IWebContext.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; + +namespace VAR.WebFormsCore.Code; + +public interface IWebContext +{ + string RequestPath { get; } + string RequestMethod { get; } + Dictionary RequestForm { get; } + Dictionary RequestQuery { get; } + Dictionary RequestHeader { get; } + + void ResponseWrite(string text); + void ResponseWriteBin(byte[] content); + void ResponseFlush(); + void ResponseRedirect(string url); + + bool ResponseHasStarted { get; } + int ResponseStatusCode { get; set; } + string? ResponseContentType { get; set; } + void SetResponseHeader(string key, string value); + + void PrepareCacheableResponse(); + void PrepareUncacheableResponse(); +} \ No newline at end of file diff --git a/VAR.WebFormsCore/Code/MultiLang.cs b/VAR.WebFormsCore/Code/MultiLang.cs index 56b0ab5..2e4a5ad 100644 --- a/VAR.WebFormsCore/Code/MultiLang.cs +++ b/VAR.WebFormsCore/Code/MultiLang.cs @@ -2,95 +2,94 @@ using System.IO; using VAR.Json; -namespace VAR.WebFormsCore.Code +namespace VAR.WebFormsCore.Code; + +public static class MultiLang { - public static class MultiLang + private static string GetPrivatePath(string baseDir, string fileName) { - private static string GetPrivatePath(string baseDir, string fileName) + string currentDir = Directory.GetCurrentDirectory(); + string privatePath = Path.Combine(currentDir, baseDir); + while (Directory.Exists(privatePath) == false) { - string currentDir = Directory.GetCurrentDirectory(); - string privatePath = Path.Combine(currentDir, baseDir); - while (Directory.Exists(privatePath) == false) - { - DirectoryInfo? dirInfo = Directory.GetParent(currentDir); - if (dirInfo == null) { break; } + DirectoryInfo? dirInfo = Directory.GetParent(currentDir); + if (dirInfo == null) { break; } - currentDir = dirInfo.FullName; - privatePath = Path.Combine(currentDir, baseDir); - } - - return Path.Combine(privatePath, fileName); + currentDir = dirInfo.FullName; + privatePath = Path.Combine(currentDir, baseDir); } - private static Dictionary?>? _literals; + return Path.Combine(privatePath, fileName); + } - private static void InitializeLiterals() + private static Dictionary?>? _literals; + + private static void InitializeLiterals() + { + _literals = new Dictionary?>(); + + JsonParser jsonParser = new JsonParser(); + foreach (string lang in new[] {"en", "es"}) { - _literals = new Dictionary?>(); + string filePath = GetPrivatePath("Resources", $"Literals.{lang}.json"); + if (File.Exists(filePath) == false) { continue; } - JsonParser jsonParser = new JsonParser(); - foreach (string lang in new[] {"en", "es"}) - { - string filePath = GetPrivatePath("Resources", $"Literals.{lang}.json"); - if (File.Exists(filePath) == false) { continue; } - - string strJsonLiteralsLanguage = File.ReadAllText(filePath); - object result = jsonParser.Parse(strJsonLiteralsLanguage); - _literals.Add(lang, result as Dictionary); - } - } - - private const string DefaultLanguage = "en"; - - private static string GetUserLanguage() - { - // TODO: Needs replacement for ctx.Request.UserLanguages - //HttpContext ctx = HttpContext.Current; - //if (ctx != null) - //{ - // if (ctx.Items["UserLang"] != null) - // { - // return (string)ctx.Items["UserLang"]; - // } - - // IEnumerable userLanguages = ctx.Request.UserLanguages - // .Select(lang => - // { - // if (lang.Contains(";")) - // { - // lang = lang.Split(';')[0]; - // } - // if (lang.Contains("-")) - // { - // lang = lang.Split('-')[0]; - // } - // return lang.ToLower(); - // }) - // .Where(lang => _literals.ContainsKey(lang)); - // string userLang = userLanguages.FirstOrDefault() ?? _defaultLanguage; - - // ctx.Items["UserLang"] = userLang; - // return userLang; - //} - return DefaultLanguage; - } - - public static string GetLiteral(string resource, string? culture = null) - { - if (_literals == null) { InitializeLiterals(); } - - culture ??= GetUserLanguage(); - - if (_literals == null || _literals.ContainsKey(culture) == false) { return resource; } - - Dictionary? literalCurrentCulture = _literals[culture]; - - if (literalCurrentCulture == null || literalCurrentCulture.ContainsKey(resource) == false) - { - return resource; - } - - return (literalCurrentCulture[resource] as string) ?? resource; + string strJsonLiteralsLanguage = File.ReadAllText(filePath); + object result = jsonParser.Parse(strJsonLiteralsLanguage); + _literals.Add(lang, result as Dictionary); } } + + private const string DefaultLanguage = "en"; + + private static string GetUserLanguage() + { + // TODO: Needs replacement for ctx.Request.UserLanguages + //HttpContext ctx = HttpContext.Current; + //if (ctx != null) + //{ + // if (ctx.Items["UserLang"] != null) + // { + // return (string)ctx.Items["UserLang"]; + // } + + // IEnumerable userLanguages = ctx.Request.UserLanguages + // .Select(lang => + // { + // if (lang.Contains(";")) + // { + // lang = lang.Split(';')[0]; + // } + // if (lang.Contains("-")) + // { + // lang = lang.Split('-')[0]; + // } + // return lang.ToLower(); + // }) + // .Where(lang => _literals.ContainsKey(lang)); + // string userLang = userLanguages.FirstOrDefault() ?? _defaultLanguage; + + // ctx.Items["UserLang"] = userLang; + // return userLang; + //} + return DefaultLanguage; + } + + public static string GetLiteral(string resource, string? culture = null) + { + if (_literals == null) { InitializeLiterals(); } + + culture ??= GetUserLanguage(); + + if (_literals == null || _literals.ContainsKey(culture) == false) { return resource; } + + Dictionary? literalCurrentCulture = _literals[culture]; + + if (literalCurrentCulture == null || literalCurrentCulture.ContainsKey(resource) == false) + { + return resource; + } + + return (literalCurrentCulture[resource] as string) ?? resource; + } } \ No newline at end of file diff --git a/VAR.WebFormsCore/Code/ObjectActivator.cs b/VAR.WebFormsCore/Code/ObjectActivator.cs index c02a7a8..aff6398 100644 --- a/VAR.WebFormsCore/Code/ObjectActivator.cs +++ b/VAR.WebFormsCore/Code/ObjectActivator.cs @@ -2,32 +2,31 @@ using System.Collections.Generic; using System.Linq.Expressions; -namespace VAR.WebFormsCore.Code +namespace VAR.WebFormsCore.Code; + +public static class ObjectActivator { - public static class ObjectActivator + private static readonly Dictionary> Creators = new(); + + private static Func GetLambdaNew(Type type) { - private static readonly Dictionary> Creators = new(); - - private static Func GetLambdaNew(Type type) + lock (Creators) { - lock (Creators) - { - if (Creators.TryGetValue(type, out var creator)) { return creator; } + if (Creators.TryGetValue(type, out var creator)) { return creator; } - NewExpression newExp = Expression.New(type); - LambdaExpression lambda = Expression.Lambda(typeof(Func), newExp); - Func compiledLambdaNew = (Func) lambda.Compile(); + NewExpression newExp = Expression.New(type); + LambdaExpression lambda = Expression.Lambda(typeof(Func), newExp); + Func compiledLambdaNew = (Func) lambda.Compile(); - Creators.Add(type, compiledLambdaNew); + Creators.Add(type, compiledLambdaNew); - return Creators[type]; - } - } - - public static object CreateInstance(Type type) - { - Func creator = GetLambdaNew(type); - return creator(); + return Creators[type]; } } + + public static object CreateInstance(Type type) + { + Func creator = GetLambdaNew(type); + return creator(); + } } \ No newline at end of file diff --git a/VAR.WebFormsCore/Code/ScriptsBundler.cs b/VAR.WebFormsCore/Code/ScriptsBundler.cs index 6a5e704..2bb0e21 100644 --- a/VAR.WebFormsCore/Code/ScriptsBundler.cs +++ b/VAR.WebFormsCore/Code/ScriptsBundler.cs @@ -1,23 +1,21 @@ using System.Reflection; -using Microsoft.AspNetCore.Http; -namespace VAR.WebFormsCore.Code +namespace VAR.WebFormsCore.Code; + +public class ScriptsBundler : IHttpHandler { - public class ScriptsBundler : IHttpHandler + #region IHttpHandler + + public void ProcessRequest(IWebContext context) { - #region IHttpHandler - - public void ProcessRequest(HttpContext context) - { - Bundler bundler = new Bundler( - assembly: Assembly.GetExecutingAssembly(), - assemblyNamespace: "Scripts", - absolutePath: ServerHelpers.MapContentPath("Scripts") - ); - context.Response.PrepareCacheableResponse(); - bundler.WriteResponse(context.Response, "text/javascript"); - } - - #endregion IHttpHandler + Bundler bundler = new Bundler( + assembly: Assembly.GetExecutingAssembly(), + assemblyNamespace: "Scripts", + absolutePath: ServerHelpers.MapContentPath("Scripts") + ); + context.PrepareCacheableResponse(); + bundler.WriteResponse(context, "text/javascript"); } + + #endregion IHttpHandler } \ No newline at end of file diff --git a/VAR.WebFormsCore/Code/ServerHelpers.cs b/VAR.WebFormsCore/Code/ServerHelpers.cs index 9b31903..64d3f79 100644 --- a/VAR.WebFormsCore/Code/ServerHelpers.cs +++ b/VAR.WebFormsCore/Code/ServerHelpers.cs @@ -1,118 +1,117 @@ using System.Globalization; using System.Text; -namespace VAR.WebFormsCore.Code +namespace VAR.WebFormsCore.Code; + +public static class ServerHelpers { - public static class ServerHelpers + private static string? _contentRoot; + + public static void SetContentRoot(string contentRoot) { - private static string? _contentRoot; + _contentRoot = contentRoot; + } - public static void SetContentRoot(string contentRoot) + public static string MapContentPath(string path) + { + string mappedPath = string.Concat(_contentRoot, "/", path); + return mappedPath; + } + + public static string HtmlEncode(string text) + { + if (string.IsNullOrEmpty(text)) { - _contentRoot = contentRoot; + return text; } - public static string MapContentPath(string path) + StringBuilder sbResult = new(); + + foreach (var ch in text) { - string mappedPath = string.Concat(_contentRoot, "/", path); - return mappedPath; - } - - public static string HtmlEncode(string text) - { - if (string.IsNullOrEmpty(text)) + switch (ch) { - return text; - } - - StringBuilder sbResult = new(); - - foreach (var ch in text) - { - switch (ch) + case '<': + sbResult.Append("<"); + break; + case '>': + sbResult.Append(">"); + break; + case '"': + sbResult.Append("""); + break; + case '\'': + sbResult.Append("'"); + break; + case '&': + sbResult.Append("&"); + break; + default: { - case '<': - sbResult.Append("<"); - break; - case '>': - sbResult.Append(">"); - break; - case '"': - sbResult.Append("""); - break; - case '\'': - sbResult.Append("'"); - break; - case '&': - sbResult.Append("&"); - break; - default: + if (ch > 127) { - if (ch > 127) - { - sbResult.Append("&#"); - sbResult.Append(((int)ch).ToString(NumberFormatInfo.InvariantInfo)); - sbResult.Append(';'); - } - else - { - sbResult.Append(ch); - } - - break; + sbResult.Append("&#"); + sbResult.Append(((int)ch).ToString(NumberFormatInfo.InvariantInfo)); + sbResult.Append(';'); } + else + { + sbResult.Append(ch); + } + + break; } } - - return sbResult.ToString(); } - public static string UrlEncode(string text) + return sbResult.ToString(); + } + + public static string UrlEncode(string text) + { + if (string.IsNullOrEmpty(text)) { - if (string.IsNullOrEmpty(text)) - { - return text; - } - - StringBuilder sbResult = new(); - - foreach (var ch in text) - { - if (ch == ' ') - { - sbResult.Append('+'); - } - else if (IsUrlSafe(ch) == false) - { - sbResult.Append($"%{ch:X02}"); - } - else - { - sbResult.Append(ch); - } - } - - return sbResult.ToString(); + return text; } - private static bool IsUrlSafe(char ch) + StringBuilder sbResult = new(); + + foreach (var ch in text) { - if ( - (ch >= 'a' && ch <= 'z') || - (ch >= 'A' && ch <= 'Z') || - (ch >= '0' && ch <= '9') || - ch == '-' || - ch == '_' || - ch == '.' || - ch == '!' || - ch == '*' || - ch == '(' || - ch == ')') + if (ch == ' ') { - return true; + sbResult.Append('+'); + } + else if (IsUrlSafe(ch) == false) + { + sbResult.Append($"%{ch:X02}"); + } + else + { + sbResult.Append(ch); } - - return false; } + + return sbResult.ToString(); + } + + private static bool IsUrlSafe(char ch) + { + if ( + (ch >= 'a' && ch <= 'z') || + (ch >= 'A' && ch <= 'Z') || + (ch >= '0' && ch <= '9') || + ch == '-' || + ch == '_' || + ch == '.' || + ch == '!' || + ch == '*' || + ch == '(' || + ch == ')') + { + return true; + } + + return false; } } \ No newline at end of file diff --git a/VAR.WebFormsCore/Code/StaticFileHelper.cs b/VAR.WebFormsCore/Code/StaticFileHelper.cs index f1343d4..1fada06 100644 --- a/VAR.WebFormsCore/Code/StaticFileHelper.cs +++ b/VAR.WebFormsCore/Code/StaticFileHelper.cs @@ -1,84 +1,82 @@ using System.Collections.Generic; using System.IO; -using Microsoft.AspNetCore.Http; -namespace VAR.WebFormsCore.Code +namespace VAR.WebFormsCore.Code; + +public static class StaticFileHelper { - public static class StaticFileHelper + private static readonly Dictionary MimeTypeByExtension = new() { - private static readonly Dictionary MimeTypeByExtension = new() - { - {".aac", "audio/aac"}, - {".abw", "application/x-abiword"}, - {".arc", "application/octet-stream"}, - {".avi", "video/x-msvideo"}, - {".azw", "application/vnd.amazon.ebook"}, - {".bin", "application/octet-stream"}, - {".bz", "application/x-bzip"}, - {".bz2", "application/x-bzip2"}, - {".csh", "application/x-csh"}, - {".css", "text/css"}, - {".csv", "text/csv"}, - {".doc", "application/msword"}, - {".epub", "application/epub+zip"}, - {".gif", "image/gif"}, - {".htm", "text/html"}, - {".html", "text/html"}, - {".ico", "image/x-icon"}, - {".ics", "text/calendar"}, - {".jar", "application/java-archive"}, - {".jpg", "image/jpeg"}, - {".jpeg", "image/jpeg"}, - {".js", "application/javascript"}, - {".json", "application/json"}, - {".mid", "audio/midi"}, - {".midi", "audio/midi"}, - {".mpeg", "video/mpeg"}, - {".mpkg", "application/vnd.apple.installer+xml"}, - {".odp", "application/vnd.oasis.opendocument.presentation"}, - {".ods", "application/vnd.oasis.opendocument.spreadsheet"}, - {".odt", "application/vnd.oasis.opendocument.text"}, - {".oga", "audio/ogg"}, - {".ogv", "video/ogg"}, - {".ogx", "application/ogg"}, - {".png", "image/png"}, - {".pdf", "application/pdf"}, - {".ppt", "application/vnd.ms-powerpoint"}, - {".rar", "application/x-rar-compressed"}, - {".rtf", "application/rtf"}, - {".sh", "application/x-sh"}, - {".svg", "image/svg+xml"}, - {".swf", "application/x-shockwave-flash"}, - {".tar", "application/x-tar"}, - {".tiff", "image/tiff"}, - {".tif", "image/tiff"}, - {".ttf", "font/ttf"}, - {".vsd", "application/vnd.visio"}, - {".wav", "audio/x-wav"}, - {".weba", "audio/webm"}, - {".webm", "video/webm"}, - {".webp", "image/webp"}, - {".woff", "font/woff"}, - {".woff2", "font/woff2"}, - {".xhtml", "application/xhtml+xml"}, - {".xls", "application/vnd.ms-excel"}, - {".xml", "application/xml"}, - {".xul", "application/vnd.mozilla.xul+xml"}, - {".zip", "application/zip"}, - {".7z", "application/x-7z-compressed"}, - }; + {".aac", "audio/aac"}, + {".abw", "application/x-abiword"}, + {".arc", "application/octet-stream"}, + {".avi", "video/x-msvideo"}, + {".azw", "application/vnd.amazon.ebook"}, + {".bin", "application/octet-stream"}, + {".bz", "application/x-bzip"}, + {".bz2", "application/x-bzip2"}, + {".csh", "application/x-csh"}, + {".css", "text/css"}, + {".csv", "text/csv"}, + {".doc", "application/msword"}, + {".epub", "application/epub+zip"}, + {".gif", "image/gif"}, + {".htm", "text/html"}, + {".html", "text/html"}, + {".ico", "image/x-icon"}, + {".ics", "text/calendar"}, + {".jar", "application/java-archive"}, + {".jpg", "image/jpeg"}, + {".jpeg", "image/jpeg"}, + {".js", "application/javascript"}, + {".json", "application/json"}, + {".mid", "audio/midi"}, + {".midi", "audio/midi"}, + {".mpeg", "video/mpeg"}, + {".mpkg", "application/vnd.apple.installer+xml"}, + {".odp", "application/vnd.oasis.opendocument.presentation"}, + {".ods", "application/vnd.oasis.opendocument.spreadsheet"}, + {".odt", "application/vnd.oasis.opendocument.text"}, + {".oga", "audio/ogg"}, + {".ogv", "video/ogg"}, + {".ogx", "application/ogg"}, + {".png", "image/png"}, + {".pdf", "application/pdf"}, + {".ppt", "application/vnd.ms-powerpoint"}, + {".rar", "application/x-rar-compressed"}, + {".rtf", "application/rtf"}, + {".sh", "application/x-sh"}, + {".svg", "image/svg+xml"}, + {".swf", "application/x-shockwave-flash"}, + {".tar", "application/x-tar"}, + {".tiff", "image/tiff"}, + {".tif", "image/tiff"}, + {".ttf", "font/ttf"}, + {".vsd", "application/vnd.visio"}, + {".wav", "audio/x-wav"}, + {".weba", "audio/webm"}, + {".webm", "video/webm"}, + {".webp", "image/webp"}, + {".woff", "font/woff"}, + {".woff2", "font/woff2"}, + {".xhtml", "application/xhtml+xml"}, + {".xls", "application/vnd.ms-excel"}, + {".xml", "application/xml"}, + {".xul", "application/vnd.mozilla.xul+xml"}, + {".zip", "application/zip"}, + {".7z", "application/x-7z-compressed"}, + }; - public static void ResponseStaticFile(HttpContext context, string filePath) - { - string extension = Path.GetExtension(filePath).ToLower(); - MimeTypeByExtension.TryGetValue(extension, out string? contentType); + public static void ResponseStaticFile(IWebContext context, string filePath) + { + string extension = Path.GetExtension(filePath).ToLower(); + MimeTypeByExtension.TryGetValue(extension, out string? contentType); - if (string.IsNullOrEmpty(contentType) == false) { context.Response.ContentType = contentType; } + if (string.IsNullOrEmpty(contentType) == false) { context.ResponseContentType = contentType; } - context.Response.PrepareCacheableResponse(); + context.PrepareCacheableResponse(); - byte[] fileData = File.ReadAllBytes(filePath); - context.Response.Body.WriteAsync(fileData).GetAwaiter().GetResult(); - } + byte[] fileData = File.ReadAllBytes(filePath); + context.ResponseWriteBin(fileData); } } \ No newline at end of file diff --git a/VAR.WebFormsCore/Code/StylesBundler.cs b/VAR.WebFormsCore/Code/StylesBundler.cs index fd48e7a..5f088a5 100644 --- a/VAR.WebFormsCore/Code/StylesBundler.cs +++ b/VAR.WebFormsCore/Code/StylesBundler.cs @@ -1,23 +1,21 @@ using System.Reflection; -using Microsoft.AspNetCore.Http; -namespace VAR.WebFormsCore.Code +namespace VAR.WebFormsCore.Code; + +public class StylesBundler : IHttpHandler { - public class StylesBundler : IHttpHandler + #region IHttpHandler + + public void ProcessRequest(IWebContext context) { - #region IHttpHandler - - public void ProcessRequest(HttpContext context) - { - Bundler bundler = new Bundler( - assembly: Assembly.GetExecutingAssembly(), - assemblyNamespace: "Styles", - absolutePath: ServerHelpers.MapContentPath("Styles") - ); - context.Response.PrepareCacheableResponse(); - bundler.WriteResponse(context.Response, "text/css"); - } - - #endregion IHttpHandler + Bundler bundler = new Bundler( + assembly: Assembly.GetExecutingAssembly(), + assemblyNamespace: "Styles", + absolutePath: ServerHelpers.MapContentPath("Styles") + ); + context.PrepareCacheableResponse(); + bundler.WriteResponse(context, "text/css"); } + + #endregion IHttpHandler } \ No newline at end of file diff --git a/VAR.WebFormsCore/Code/Unit.cs b/VAR.WebFormsCore/Code/Unit.cs index 52706ed..c99244e 100644 --- a/VAR.WebFormsCore/Code/Unit.cs +++ b/VAR.WebFormsCore/Code/Unit.cs @@ -1,28 +1,27 @@ -namespace VAR.WebFormsCore.Code +namespace VAR.WebFormsCore.Code; + +public class Unit { - public class Unit + private readonly int _value; + private readonly UnitType _unitType; + + public Unit(int value, UnitType type) { - private readonly int _value; - private readonly UnitType _unitType; - - public Unit(int value, UnitType type) - { - _value = value; - _unitType = type; - } - - public override string ToString() - { - if (_unitType == UnitType.Pixel) { return $"{_value}px"; } - - if (_unitType == UnitType.Percentage) { return $"{_value}%"; } - - return string.Empty; - } + _value = value; + _unitType = type; } - public enum UnitType + public override string ToString() { - Pixel, Percentage, + if (_unitType == UnitType.Pixel) { return $"{_value}px"; } + + if (_unitType == UnitType.Percentage) { return $"{_value}%"; } + + return string.Empty; } +} + +public enum UnitType +{ + Pixel, Percentage, } \ No newline at end of file diff --git a/VAR.WebFormsCore/Controls/Button.cs b/VAR.WebFormsCore/Controls/Button.cs index ca42558..fb12e33 100644 --- a/VAR.WebFormsCore/Controls/Button.cs +++ b/VAR.WebFormsCore/Controls/Button.cs @@ -1,42 +1,41 @@ using System; using System.IO; -namespace VAR.WebFormsCore.Controls +namespace VAR.WebFormsCore.Controls; + +public class Button : Control, IReceivePostbackEvent { - public class Button : Control, IReceivePostbackEvent + public Button() { CssClass = "button"; } + + private string _text = string.Empty; + + public string Text { - public Button() { CssClass = "button"; } - - private string _text = string.Empty; - - public string Text - { - get => _text; - set => _text = value; - } - - public string OnClientClick { get; set; } = string.Empty; - - public string CommandArgument { get; set; } = string.Empty; - - public event EventHandler? Click; - - protected override void Render(TextWriter textWriter) - { - textWriter.Write(""); - - base.Render(textWriter); - - textWriter.Write(""); - } - - public void ReceivePostBack() { Click?.Invoke(this, EventArgs.Empty); } + get => _text; + set => _text = value; } + + public string OnClientClick { get; set; } = string.Empty; + + public string CommandArgument { get; set; } = string.Empty; + + public event EventHandler? Click; + + protected override void Render(TextWriter textWriter) + { + textWriter.Write(""); + + base.Render(textWriter); + + textWriter.Write(""); + } + + public void ReceivePostBack() { Click?.Invoke(this, EventArgs.Empty); } } \ No newline at end of file diff --git a/VAR.WebFormsCore/Controls/CTextBox.cs b/VAR.WebFormsCore/Controls/CTextBox.cs index 516c491..15b5c01 100644 --- a/VAR.WebFormsCore/Controls/CTextBox.cs +++ b/VAR.WebFormsCore/Controls/CTextBox.cs @@ -3,193 +3,192 @@ using System.Collections.Generic; using System.Text; using VAR.Json; -namespace VAR.WebFormsCore.Controls +namespace VAR.WebFormsCore.Controls; + +public class CTextBox : Control, INamingContainer, IValidableControl { - public class CTextBox : Control, INamingContainer, IValidableControl + #region Declarations + + private readonly TextBox _txtContent = new(); + + private HiddenField? _hidSize; + + private const string CssClassBase = "textBox"; + private string _cssClassExtra = ""; + + private bool _allowEmpty = true; + + private string _placeHolder = string.Empty; + + private bool _markedInvalid; + + private Control? _nextFocusOnEnter; + + private bool _keepSize; + + #endregion Declarations + + #region Properties + + public string CssClassExtra { - #region Declarations + get => _cssClassExtra; + set => _cssClassExtra = value; + } - private readonly TextBox _txtContent = new(); + public bool AllowEmpty + { + get => _allowEmpty; + set => _allowEmpty = value; + } - private HiddenField? _hidSize; + public string PlaceHolder + { + get => _placeHolder; + set => _placeHolder = value; + } - private const string CssClassBase = "textBox"; - private string _cssClassExtra = ""; + public bool MarkedInvalid + { + get => _markedInvalid; + set => _markedInvalid = value; + } - private bool _allowEmpty = true; + public Control? NextFocusOnEnter + { + get => _nextFocusOnEnter; + set => _nextFocusOnEnter = value; + } - private string _placeHolder = string.Empty; + public bool KeepSize + { + get => _keepSize; + set => _keepSize = value; + } - private bool _markedInvalid; + public string Text + { + get => _txtContent.Text; + set => _txtContent.Text = value; + } - private Control? _nextFocusOnEnter; + public TextBoxMode TextMode + { + get => _txtContent.TextMode; + set => _txtContent.TextMode = value; + } - private bool _keepSize; + #endregion Properties - #endregion Declarations + #region Control life cycle - #region Properties + public CTextBox() + { + Init += CTextBox_Init; + PreRender += CTextBox_PreRender; + } - public string CssClassExtra + private void CTextBox_Init(object? sender, EventArgs e) + { + Controls.Add(_txtContent); + + if (TextMode == TextBoxMode.MultiLine) { - get => _cssClassExtra; - set => _cssClassExtra = value; - } - - public bool AllowEmpty - { - get => _allowEmpty; - set => _allowEmpty = value; - } - - public string PlaceHolder - { - get => _placeHolder; - set => _placeHolder = value; - } - - public bool MarkedInvalid - { - get => _markedInvalid; - set => _markedInvalid = value; - } - - public Control? NextFocusOnEnter - { - get => _nextFocusOnEnter; - set => _nextFocusOnEnter = value; - } - - public bool KeepSize - { - get => _keepSize; - set => _keepSize = value; - } - - public string Text - { - get => _txtContent.Text; - set => _txtContent.Text = value; - } - - public TextBoxMode TextMode - { - get => _txtContent.TextMode; - init => _txtContent.TextMode = value; - } - - #endregion Properties - - #region Control life cycle - - public CTextBox() - { - Init += CTextBox_Init; - PreRender += CTextBox_PreRender; - } - - private void CTextBox_Init(object? sender, EventArgs e) - { - Controls.Add(_txtContent); - - if (TextMode == TextBoxMode.MultiLine) + if (_keepSize) { - if (_keepSize) - { - _hidSize = new HiddenField(); - Controls.Add(_hidSize); - } - - string strCfgName = $"{ClientID}_cfg"; - Dictionary cfg = new() - { - {"txtContent", _txtContent.ClientID}, {"hidSize", _hidSize?.ClientID ?? string.Empty}, {"keepSize", _keepSize}, - }; - StringBuilder sbCfg = new StringBuilder(); - sbCfg.AppendFormat("\n"); - LiteralControl liScript = new LiteralControl(sbCfg.ToString()); - Controls.Add(liScript); - } - } - - private void CTextBox_PreRender(object? sender, EventArgs e) - { - _txtContent.CssClass = CssClassBase; - if (string.IsNullOrEmpty(_cssClassExtra) == false) - { - _txtContent.CssClass = $"{CssClassBase} {_cssClassExtra}"; + _hidSize = new HiddenField(); + Controls.Add(_hidSize); } - if (Page?.IsPostBack == true && (_allowEmpty == false && IsEmpty()) || _markedInvalid) + string strCfgName = $"{ClientID}_cfg"; + Dictionary cfg = new() { - _txtContent.CssClass += " textBoxInvalid"; - } + {"txtContent", _txtContent.ClientID}, {"hidSize", _hidSize?.ClientID ?? string.Empty}, {"keepSize", _keepSize}, + }; + StringBuilder sbCfg = new StringBuilder(); + sbCfg.AppendFormat("\n"); + LiteralControl liScript = new LiteralControl(sbCfg.ToString()); + Controls.Add(liScript); + } + } - _txtContent.Attributes.Add("onchange", "ElementRemoveClass(this, 'textBoxInvalid');"); - - if (string.IsNullOrEmpty(_placeHolder) == false) - { - _txtContent.Attributes.Add("placeholder", _placeHolder); - } - - if (_nextFocusOnEnter != null) - { - _txtContent.Attributes.Add( - "onkeydown", - $"if(event.keyCode==13){{document.getElementById('{_nextFocusOnEnter.ClientID}').focus(); return false;}}" - ); - } + private void CTextBox_PreRender(object? sender, EventArgs e) + { + _txtContent.CssClass = CssClassBase; + if (string.IsNullOrEmpty(_cssClassExtra) == false) + { + _txtContent.CssClass = $"{CssClassBase} {_cssClassExtra}"; } - #endregion Control life cycle - - #region Public methods - - private bool IsEmpty() { return string.IsNullOrEmpty(_txtContent.Text); } - - public bool IsValid() { return _allowEmpty || (string.IsNullOrEmpty(_txtContent.Text) == false); } - - public int? GetClientsideHeight() + if (Page?.IsPostBack == true && (_allowEmpty == false && IsEmpty()) || _markedInvalid) { - if (string.IsNullOrEmpty(_hidSize?.Value)) { return null; } - - JsonParser jsonParser = new JsonParser(); - Dictionary? sizeObj = jsonParser.Parse(_hidSize.Value) as Dictionary; - if (sizeObj == null) { return null; } - - if (sizeObj.ContainsKey("height") == false) { return null; } - - return (int) sizeObj["height"]; + _txtContent.CssClass += " textBoxInvalid"; } - public void SetClientsideHeight(int? height) + _txtContent.Attributes.Add("onchange", "ElementRemoveClass(this, 'textBoxInvalid');"); + + if (string.IsNullOrEmpty(_placeHolder) == false) { - if (height == null) - { - if (_hidSize != null) - { - _hidSize.Value = string.Empty; - } - return; - } + _txtContent.Attributes.Add("placeholder", _placeHolder); + } - Dictionary? sizeObj = null; - if (string.IsNullOrEmpty(_hidSize?.Value) == false) - { - JsonParser jsonParser = new JsonParser(); - sizeObj = jsonParser.Parse(_hidSize.Value) as Dictionary; - } - sizeObj ??= new Dictionary { { "height", height }, { "width", null }, { "scrollTop", null }, }; + if (_nextFocusOnEnter != null) + { + _txtContent.Attributes.Add( + "onkeydown", + $"if(event.keyCode==13){{document.getElementById('{_nextFocusOnEnter.ClientID}').focus(); return false;}}" + ); + } + } + #endregion Control life cycle + + #region Public methods + + private bool IsEmpty() { return string.IsNullOrEmpty(_txtContent.Text); } + + public bool IsValid() { return _allowEmpty || (string.IsNullOrEmpty(_txtContent.Text) == false); } + + public int? GetClientsideHeight() + { + if (string.IsNullOrEmpty(_hidSize?.Value)) { return null; } + + JsonParser jsonParser = new JsonParser(); + Dictionary? sizeObj = jsonParser.Parse(_hidSize?.Value) as Dictionary; + if (sizeObj == null) { return null; } + + if (sizeObj.ContainsKey("height") == false) { return null; } + + return (int) sizeObj["height"]; + } + + public void SetClientsideHeight(int? height) + { + if (height == null) + { if (_hidSize != null) { - _hidSize.Value = JsonWriter.WriteObject(sizeObj); + _hidSize.Value = string.Empty; } + return; } - #endregion Public methods + Dictionary? sizeObj = null; + if (string.IsNullOrEmpty(_hidSize?.Value) == false) + { + JsonParser jsonParser = new JsonParser(); + sizeObj = jsonParser.Parse(_hidSize?.Value) as Dictionary; + } + sizeObj ??= new Dictionary { { "height", height }, { "width", null }, { "scrollTop", null }, }; + + if (_hidSize != null) + { + _hidSize.Value = JsonWriter.WriteObject(sizeObj); + } } + + #endregion Public methods } \ No newline at end of file diff --git a/VAR.WebFormsCore/Controls/Control.cs b/VAR.WebFormsCore/Controls/Control.cs index f8c184b..0298a6c 100644 --- a/VAR.WebFormsCore/Controls/Control.cs +++ b/VAR.WebFormsCore/Controls/Control.cs @@ -5,194 +5,193 @@ using System.Text; using VAR.WebFormsCore.Code; using VAR.WebFormsCore.Pages; -namespace VAR.WebFormsCore.Controls +namespace VAR.WebFormsCore.Controls; + +public class Control { - public class Control + public event EventHandler? PreInit; + + protected void OnPreInit(EventArgs e) { - public event EventHandler? PreInit; + PreInit?.Invoke(this, e); + foreach (Control control in Controls) { control.OnPreInit(e); } + } - protected void OnPreInit(EventArgs e) + public event EventHandler? Init; + + protected void OnInit(EventArgs e) + { + Init?.Invoke(this, e); + foreach (Control control in Controls) { control.OnInit(e); } + } + + + public event EventHandler? Load; + + protected virtual void Process() { } + + protected void OnLoad(EventArgs e) + { + Process(); + Load?.Invoke(this, e); + foreach (Control control in Controls) { control.OnLoad(e); } + } + + public event EventHandler? PreRender; + + protected void OnPreRender(EventArgs e) + { + PreRender?.Invoke(this, e); + foreach (Control control in Controls) { control.OnPreRender(e); } + } + + private string? _id; + + public string? ID + { + get => _id; + set { - PreInit?.Invoke(this, e); - foreach (Control control in Controls) { control.OnPreInit(e); } - } - - public event EventHandler? Init; - - protected void OnInit(EventArgs e) - { - Init?.Invoke(this, e); - foreach (Control control in Controls) { control.OnInit(e); } - } - - - public event EventHandler? Load; - - protected virtual void Process() { } - - protected void OnLoad(EventArgs e) - { - Process(); - Load?.Invoke(this, e); - foreach (Control control in Controls) { control.OnLoad(e); } - } - - public event EventHandler? PreRender; - - protected void OnPreRender(EventArgs e) - { - PreRender?.Invoke(this, e); - foreach (Control control in Controls) { control.OnPreRender(e); } - } - - private string? _id; - - public string? ID - { - get => _id; - set - { - _id = value; - _clientID = null; - } - } - - private string? _clientID; - - public string ClientID - { - get { return _clientID ??= GenerateClientID(); } - } - - private Control? _parent; - - public Control? Parent - { - get => _parent; - set - { - _parent = value; - _clientID = null; - } - } - - private ControlCollection? _controls; - - public string CssClass { get; set; } = string.Empty; - - public ControlCollection Controls - { - get { return _controls ??= new ControlCollection(this); } - } - - private Page? _page; - - public Page? Page - { - get => _page; - set - { - _page = value; - foreach (Control control in Controls) { control.Page = value; } - } - } - - public bool Visible { get; set; } = true; - - private string GenerateClientID() - { - StringBuilder sbClientID = new(); - - if (string.IsNullOrEmpty(_id) == false) { sbClientID.Insert(0, _id); } - else - { - string currentID = $"ctl{Index:00}"; - sbClientID.Insert(0, currentID); - } - - Control? parent = Parent; - while (parent != null) - { - if (parent is INamingContainer) - { - sbClientID.Insert(0, "_"); - if (string.IsNullOrEmpty(parent.ID) == false) { sbClientID.Insert(0, parent.ID); } - else - { - string parentID = $"ctl{parent.Index:00}"; - sbClientID.Insert(0, parentID); - } - } - - parent = parent.Parent; - } - - return sbClientID.ToString(); - } - - public Dictionary Style { get; } = new(); - - public Dictionary Attributes { get; } = new(); - - public int Index { get; set; } - - protected virtual void Render(TextWriter textWriter) - { - foreach (Control control in Controls) - { - if (control.Visible == false) { continue; } - - control.Render(textWriter); - } - } - - protected static void RenderAttribute(TextWriter textWriter, string key, string value) - { - textWriter.Write(" {0}=\"{1}\"", key, ServerHelpers.HtmlEncode(value)); - } - - protected void RenderAttributes(TextWriter textWriter, bool forceId = false) - { - if (string.IsNullOrEmpty(_id) == false || forceId) - { - RenderAttribute(textWriter, "id", ClientID); - RenderAttribute(textWriter, "name", ClientID); - } - - if (string.IsNullOrEmpty(CssClass) == false) { RenderAttribute(textWriter, "class", CssClass); } - - foreach (KeyValuePair attributePair in Attributes) - { - RenderAttribute(textWriter, attributePair.Key, attributePair.Value); - } - - if (Style.Count > 0) - { - StringBuilder sbStyle = new(); - foreach (KeyValuePair stylePair in Style) - { - sbStyle.Append($"{stylePair.Key}: {stylePair.Value};"); - } - - RenderAttribute(textWriter, "style", sbStyle.ToString()); - } - } - - protected List ChildsOfType(List? controls = null) - { - controls ??= new List(); - - if (this is T) { controls.Add(this); } - - if (_controls != null) - { - foreach (Control child in _controls) - { - child.ChildsOfType(controls); - } - } - - return controls; + _id = value; + _clientID = null; } } + + private string? _clientID; + + public string ClientID + { + get { return _clientID ??= GenerateClientID(); } + } + + private Control? _parent; + + public Control? Parent + { + get => _parent; + set + { + _parent = value; + _clientID = null; + } + } + + private ControlCollection? _controls; + + public string CssClass { get; set; } = string.Empty; + + public ControlCollection Controls + { + get { return _controls ??= new ControlCollection(this); } + } + + private Page? _page; + + public Page? Page + { + get => _page; + set + { + _page = value; + foreach (Control control in Controls) { control.Page = value; } + } + } + + public bool Visible { get; set; } = true; + + private string GenerateClientID() + { + StringBuilder sbClientID = new(); + + if (string.IsNullOrEmpty(_id) == false) { sbClientID.Insert(0, _id); } + else + { + string currentID = $"ctl{Index:00}"; + sbClientID.Insert(0, currentID); + } + + Control? parent = Parent; + while (parent != null) + { + if (parent is INamingContainer) + { + sbClientID.Insert(0, "_"); + if (string.IsNullOrEmpty(parent.ID) == false) { sbClientID.Insert(0, parent.ID); } + else + { + string parentID = $"ctl{parent.Index:00}"; + sbClientID.Insert(0, parentID); + } + } + + parent = parent.Parent; + } + + return sbClientID.ToString(); + } + + public Dictionary Style { get; } = new(); + + public Dictionary Attributes { get; } = new(); + + public int Index { get; set; } + + protected virtual void Render(TextWriter textWriter) + { + foreach (Control control in Controls) + { + if (control.Visible == false) { continue; } + + control.Render(textWriter); + } + } + + protected static void RenderAttribute(TextWriter textWriter, string key, string value) + { + textWriter.Write(" {0}=\"{1}\"", key, ServerHelpers.HtmlEncode(value)); + } + + protected void RenderAttributes(TextWriter textWriter, bool forceId = false) + { + if (string.IsNullOrEmpty(_id) == false || forceId) + { + RenderAttribute(textWriter, "id", ClientID); + RenderAttribute(textWriter, "name", ClientID); + } + + if (string.IsNullOrEmpty(CssClass) == false) { RenderAttribute(textWriter, "class", CssClass); } + + foreach (KeyValuePair attributePair in Attributes) + { + RenderAttribute(textWriter, attributePair.Key, attributePair.Value); + } + + if (Style.Count > 0) + { + StringBuilder sbStyle = new(); + foreach (KeyValuePair stylePair in Style) + { + sbStyle.Append($"{stylePair.Key}: {stylePair.Value};"); + } + + RenderAttribute(textWriter, "style", sbStyle.ToString()); + } + } + + protected List ChildsOfType(List? controls = null) + { + controls ??= new List(); + + if (this is T) { controls.Add(this); } + + if (_controls != null) + { + foreach (Control child in _controls) + { + child.ChildsOfType(controls); + } + } + + return controls; + } } \ No newline at end of file diff --git a/VAR.WebFormsCore/Controls/ControlCollection.cs b/VAR.WebFormsCore/Controls/ControlCollection.cs index 62d2a41..1408861 100644 --- a/VAR.WebFormsCore/Controls/ControlCollection.cs +++ b/VAR.WebFormsCore/Controls/ControlCollection.cs @@ -1,21 +1,20 @@ using System.Collections.Generic; -namespace VAR.WebFormsCore.Controls +namespace VAR.WebFormsCore.Controls; + +public class ControlCollection : List { - public class ControlCollection : List + private readonly Control _parent; + private int _index; + + public ControlCollection(Control parent) { _parent = parent; } + + public new void Add(Control control) { - private readonly Control _parent; - private int _index; - - public ControlCollection(Control parent) { _parent = parent; } - - public new void Add(Control control) - { - control.Page = _parent.Page; - control.Parent = _parent; - control.Index = _index; - _index++; - base.Add(control); - } + control.Page = _parent.Page; + control.Parent = _parent; + control.Index = _index; + _index++; + base.Add(control); } } \ No newline at end of file diff --git a/VAR.WebFormsCore/Controls/HiddenField.cs b/VAR.WebFormsCore/Controls/HiddenField.cs index 9312d4d..5032cf2 100644 --- a/VAR.WebFormsCore/Controls/HiddenField.cs +++ b/VAR.WebFormsCore/Controls/HiddenField.cs @@ -1,33 +1,32 @@ using System.IO; -namespace VAR.WebFormsCore.Controls +namespace VAR.WebFormsCore.Controls; + +public class HiddenField : Control { - public class HiddenField : Control + private string _value = string.Empty; + + public string Value { - private string _value = string.Empty; + get => _value; + set => _value = value; + } - public string Value + protected override void Process() + { + if (Page?.IsPostBack == true && Page?.Context?.RequestForm.ContainsKey(ClientID) == true) { - get => _value; - set => _value = value; - } - - protected override void Process() - { - if (Page?.IsPostBack == true && Page?.Context?.Request.Form.ContainsKey(ClientID) == true) - { - Value = Page?.Context.Request.Form[ClientID][0] ?? string.Empty; - } - } - - protected override void Render(TextWriter textWriter) - { - textWriter.Write(""); - textWriter.Write(""); + Value = Page?.Context.RequestForm[ClientID] ?? string.Empty; } } + + protected override void Render(TextWriter textWriter) + { + textWriter.Write(""); + textWriter.Write(""); + } } \ No newline at end of file diff --git a/VAR.WebFormsCore/Controls/HtmlBody.cs b/VAR.WebFormsCore/Controls/HtmlBody.cs index 620c16e..052e80c 100644 --- a/VAR.WebFormsCore/Controls/HtmlBody.cs +++ b/VAR.WebFormsCore/Controls/HtmlBody.cs @@ -1,7 +1,6 @@ -namespace VAR.WebFormsCore.Controls +namespace VAR.WebFormsCore.Controls; + +public class HtmlBody : HtmlGenericControl { - public class HtmlBody : HtmlGenericControl - { - public HtmlBody() : base("body") { } - } + public HtmlBody() : base("body") { } } \ No newline at end of file diff --git a/VAR.WebFormsCore/Controls/HtmlForm.cs b/VAR.WebFormsCore/Controls/HtmlForm.cs index 82ad0e0..eff8053 100644 --- a/VAR.WebFormsCore/Controls/HtmlForm.cs +++ b/VAR.WebFormsCore/Controls/HtmlForm.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using System.IO; using System.Text; -using Microsoft.Extensions.Primitives; using VAR.WebFormsCore.Code; namespace VAR.WebFormsCore.Controls @@ -28,15 +27,15 @@ namespace VAR.WebFormsCore.Controls StringBuilder sbAction = new(); sbAction.Append(Page?.GetType().Name); - if ((Page?.Context?.Request.Query.Count ?? 0) <= 0) { return sbAction.ToString(); } + if ((Page?.Context?.RequestQuery.Count ?? 0) <= 0) { return sbAction.ToString(); } sbAction.Append('?'); - if (Page?.Context?.Request.Query != null) + if (Page?.Context?.RequestQuery != null) { - foreach (KeyValuePair queryParam in Page.Context.Request.Query) + foreach (KeyValuePair queryParam in Page.Context.RequestQuery) { string key = ServerHelpers.UrlEncode(queryParam.Key); - string value = ServerHelpers.UrlEncode(queryParam.Value[0] ?? string.Empty); + string value = ServerHelpers.UrlEncode(queryParam.Value ?? string.Empty); sbAction.Append($"&{key}={value}"); } } diff --git a/VAR.WebFormsCore/Controls/HtmlGenericControl.cs b/VAR.WebFormsCore/Controls/HtmlGenericControl.cs index 485c50a..c1a8594 100644 --- a/VAR.WebFormsCore/Controls/HtmlGenericControl.cs +++ b/VAR.WebFormsCore/Controls/HtmlGenericControl.cs @@ -1,22 +1,21 @@ using System.IO; -namespace VAR.WebFormsCore.Controls +namespace VAR.WebFormsCore.Controls; + +public class HtmlGenericControl : Control { - public class HtmlGenericControl : Control + private readonly string _tagName; + + public HtmlGenericControl(string tag) { _tagName = tag; } + + protected override void Render(TextWriter textWriter) { - private readonly string _tagName; + textWriter.Write("<{0} ", _tagName); + RenderAttributes(textWriter); + textWriter.Write(">"); - public HtmlGenericControl(string tag) { _tagName = tag; } + base.Render(textWriter); - protected override void Render(TextWriter textWriter) - { - textWriter.Write("<{0} ", _tagName); - RenderAttributes(textWriter); - textWriter.Write(">"); - - base.Render(textWriter); - - textWriter.Write("", _tagName); - } + textWriter.Write("", _tagName); } } \ No newline at end of file diff --git a/VAR.WebFormsCore/Controls/HtmlHead.cs b/VAR.WebFormsCore/Controls/HtmlHead.cs index 6584b9f..0295d7e 100644 --- a/VAR.WebFormsCore/Controls/HtmlHead.cs +++ b/VAR.WebFormsCore/Controls/HtmlHead.cs @@ -1,22 +1,21 @@ using System.IO; -namespace VAR.WebFormsCore.Controls +namespace VAR.WebFormsCore.Controls; + +public class HtmlHead : Control { - public class HtmlHead : Control + public string Title { get; set; } = string.Empty; + + protected override void Render(TextWriter textWriter) { - public string Title { get; set; } = string.Empty; + textWriter.Write(""); - protected override void Render(TextWriter textWriter) - { - textWriter.Write(""); + if (string.IsNullOrEmpty(Title) == false) { textWriter.Write("{0}", Title); } - if (string.IsNullOrEmpty(Title) == false) { textWriter.Write("{0}", Title); } + base.Render(textWriter); - base.Render(textWriter); - - textWriter.Write(""); - } + textWriter.Write(""); } } \ No newline at end of file diff --git a/VAR.WebFormsCore/Controls/HtmlMeta.cs b/VAR.WebFormsCore/Controls/HtmlMeta.cs index 6ece7c9..28a9fcb 100644 --- a/VAR.WebFormsCore/Controls/HtmlMeta.cs +++ b/VAR.WebFormsCore/Controls/HtmlMeta.cs @@ -1,24 +1,23 @@ using System.IO; -namespace VAR.WebFormsCore.Controls +namespace VAR.WebFormsCore.Controls; + +public class HtmlMeta : Control { - public class HtmlMeta : Control + public string Name { get; set; } = string.Empty; + public string Content { get; set; } = string.Empty; + public string HttpEquiv { get; set; } = string.Empty; + + protected override void Render(TextWriter textWriter) { - public string Name { get; init; } = string.Empty; - public string Content { get; init; } = string.Empty; - public string HttpEquiv { get; internal init; } = string.Empty; + textWriter.Write(""); - } + textWriter.Write(" />"); } } \ No newline at end of file diff --git a/VAR.WebFormsCore/Controls/HyperLink.cs b/VAR.WebFormsCore/Controls/HyperLink.cs index 32dd616..ae7c38a 100644 --- a/VAR.WebFormsCore/Controls/HyperLink.cs +++ b/VAR.WebFormsCore/Controls/HyperLink.cs @@ -1,25 +1,24 @@ using System.IO; -namespace VAR.WebFormsCore.Controls +namespace VAR.WebFormsCore.Controls; + +public class HyperLink : Control { - public class HyperLink : Control + public string NavigateUrl { get; set; } = string.Empty; + public string Text { get; set; } = string.Empty; + + protected override void Render(TextWriter textWriter) { - public string NavigateUrl { get; set; } = string.Empty; - public string Text { get; init; } = string.Empty; + textWriter.Write(""); - textWriter.Write(">"); + if (string.IsNullOrEmpty(Text) == false) { textWriter.Write(Text); } - if (string.IsNullOrEmpty(Text) == false) { textWriter.Write(Text); } + base.Render(textWriter); - base.Render(textWriter); - - textWriter.Write(""); - } + textWriter.Write(""); } } \ No newline at end of file diff --git a/VAR.WebFormsCore/Controls/INamingContainer.cs b/VAR.WebFormsCore/Controls/INamingContainer.cs index 84d9673..ee4201c 100644 --- a/VAR.WebFormsCore/Controls/INamingContainer.cs +++ b/VAR.WebFormsCore/Controls/INamingContainer.cs @@ -1,6 +1,5 @@ -namespace VAR.WebFormsCore.Controls +namespace VAR.WebFormsCore.Controls; + +public interface INamingContainer { - public interface INamingContainer - { - } } \ No newline at end of file diff --git a/VAR.WebFormsCore/Controls/IReceivePostbackEvent.cs b/VAR.WebFormsCore/Controls/IReceivePostbackEvent.cs index f66cf70..e5ce7c2 100644 --- a/VAR.WebFormsCore/Controls/IReceivePostbackEvent.cs +++ b/VAR.WebFormsCore/Controls/IReceivePostbackEvent.cs @@ -1,7 +1,6 @@ -namespace VAR.WebFormsCore.Controls +namespace VAR.WebFormsCore.Controls; + +public interface IReceivePostbackEvent { - public interface IReceivePostbackEvent - { - void ReceivePostBack(); - } + void ReceivePostBack(); } \ No newline at end of file diff --git a/VAR.WebFormsCore/Controls/IValidableControl.cs b/VAR.WebFormsCore/Controls/IValidableControl.cs index be6ff62..c3cc40f 100644 --- a/VAR.WebFormsCore/Controls/IValidableControl.cs +++ b/VAR.WebFormsCore/Controls/IValidableControl.cs @@ -1,7 +1,6 @@ -namespace VAR.WebFormsCore.Controls +namespace VAR.WebFormsCore.Controls; + +public interface IValidableControl { - public interface IValidableControl - { - bool IsValid(); - } + bool IsValid(); } \ No newline at end of file diff --git a/VAR.WebFormsCore/Controls/Label.cs b/VAR.WebFormsCore/Controls/Label.cs index 37ad32e..89cd82a 100644 --- a/VAR.WebFormsCore/Controls/Label.cs +++ b/VAR.WebFormsCore/Controls/Label.cs @@ -1,45 +1,44 @@ using System.IO; using VAR.WebFormsCore.Code; -namespace VAR.WebFormsCore.Controls +namespace VAR.WebFormsCore.Controls; + +public class Label : Control { - public class Label : Control + #region Properties + + private string _tagName = "span"; + + public string Tag { - #region Properties - - private string _tagName = "span"; - - public string Tag - { - get => _tagName; - set => _tagName = value; - } - - private string _text = string.Empty; - - public string Text - { - get => _text; - set => _text = value; - } - - #endregion Properties - - #region Life cycle - - protected override void Render(TextWriter textWriter) - { - textWriter.Write("<{0} ", _tagName); - RenderAttributes(textWriter); - textWriter.Write(">"); - - textWriter.Write(ServerHelpers.HtmlEncode(_text)); - - base.Render(textWriter); - - textWriter.Write("", _tagName); - } - - #endregion Life cycle + get => _tagName; + set => _tagName = value; } + + private string _text = string.Empty; + + public string Text + { + get => _text; + set => _text = value; + } + + #endregion Properties + + #region Life cycle + + protected override void Render(TextWriter textWriter) + { + textWriter.Write("<{0} ", _tagName); + RenderAttributes(textWriter); + textWriter.Write(">"); + + textWriter.Write(ServerHelpers.HtmlEncode(_text)); + + base.Render(textWriter); + + textWriter.Write("", _tagName); + } + + #endregion Life cycle } \ No newline at end of file diff --git a/VAR.WebFormsCore/Controls/LiteralControl.cs b/VAR.WebFormsCore/Controls/LiteralControl.cs index da91318..0f37b40 100644 --- a/VAR.WebFormsCore/Controls/LiteralControl.cs +++ b/VAR.WebFormsCore/Controls/LiteralControl.cs @@ -1,14 +1,13 @@ using System.IO; -namespace VAR.WebFormsCore.Controls +namespace VAR.WebFormsCore.Controls; + +public class LiteralControl : Control { - public class LiteralControl : Control - { - public string Content { get; set; } = string.Empty; + public string Content { get; set; } = string.Empty; - public LiteralControl() { } - public LiteralControl(string content) { Content = content; } + public LiteralControl() { } + public LiteralControl(string content) { Content = content; } - protected override void Render(TextWriter textWriter) { textWriter.Write(Content); } - } + protected override void Render(TextWriter textWriter) { textWriter.Write(Content); } } \ No newline at end of file diff --git a/VAR.WebFormsCore/Controls/Panel.cs b/VAR.WebFormsCore/Controls/Panel.cs index 19f7536..f49300e 100644 --- a/VAR.WebFormsCore/Controls/Panel.cs +++ b/VAR.WebFormsCore/Controls/Panel.cs @@ -1,7 +1,6 @@ -namespace VAR.WebFormsCore.Controls +namespace VAR.WebFormsCore.Controls; + +public class Panel : HtmlGenericControl, INamingContainer { - public class Panel : HtmlGenericControl, INamingContainer - { - public Panel() : base("div") { } - } + public Panel() : base("div") { } } \ No newline at end of file diff --git a/VAR.WebFormsCore/Controls/TextBox.cs b/VAR.WebFormsCore/Controls/TextBox.cs index 0ad9b43..8ba0bcc 100644 --- a/VAR.WebFormsCore/Controls/TextBox.cs +++ b/VAR.WebFormsCore/Controls/TextBox.cs @@ -1,55 +1,54 @@ using System.IO; using VAR.WebFormsCore.Code; -namespace VAR.WebFormsCore.Controls +namespace VAR.WebFormsCore.Controls; + +public class TextBox : Control { - public class TextBox : Control + public string Text { get; set; } = string.Empty; + + public TextBoxMode TextMode { get; set; } = TextBoxMode.Normal; + + protected override void Process() { - public string Text { get; set; } = string.Empty; - - public TextBoxMode TextMode { get; set; } = TextBoxMode.Normal; - - protected override void Process() + if (Page?.IsPostBack == true && Page?.Context?.RequestForm.ContainsKey(ClientID) == true) { - if (Page?.IsPostBack == true && Page?.Context?.Request.Form.ContainsKey(ClientID) == true) - { - Text = Page?.Context.Request.Form[ClientID][0] ?? string.Empty; - } - } - - protected override void Render(TextWriter textWriter) - { - if (TextMode == TextBoxMode.MultiLine) - { - textWriter.Write(""); - } - else if (TextMode == TextBoxMode.Normal) - { - textWriter.Write(""); - textWriter.Write(""); - } - else if (TextMode == TextBoxMode.Password) - { - textWriter.Write(""); - textWriter.Write(""); - } + Text = Page?.Context.RequestForm[ClientID] ?? string.Empty; } } - public enum TextBoxMode + protected override void Render(TextWriter textWriter) { - Normal, Password, MultiLine, + if (TextMode == TextBoxMode.MultiLine) + { + textWriter.Write(""); + } + else if (TextMode == TextBoxMode.Normal) + { + textWriter.Write(""); + textWriter.Write(""); + } + else if (TextMode == TextBoxMode.Password) + { + textWriter.Write(""); + textWriter.Write(""); + } } +} + +public enum TextBoxMode +{ + Normal, Password, MultiLine, } \ No newline at end of file diff --git a/VAR.WebFormsCore/Pages/FormUtils.cs b/VAR.WebFormsCore/Pages/FormUtils.cs index fb96a33..f912bcd 100644 --- a/VAR.WebFormsCore/Pages/FormUtils.cs +++ b/VAR.WebFormsCore/Pages/FormUtils.cs @@ -1,66 +1,65 @@ using VAR.WebFormsCore.Controls; -namespace VAR.WebFormsCore.Pages +namespace VAR.WebFormsCore.Pages; + +public static class FormUtils { - public static class FormUtils + public static Control CreatePanel(string cssClass, Control? ctrl = null) { - public static Control CreatePanel(string cssClass, Control? ctrl = null) + Panel pnl = new Panel(); + if (ctrl != null) { pnl.Controls.Add(ctrl); } + + if (string.IsNullOrEmpty(cssClass) == false) { pnl.CssClass = cssClass; } + + return pnl; + } + + public static Control CreateField(string label, Control fieldControl) + { + Panel pnlRow = new Panel {CssClass = "formRow"}; + + Panel pnlLabelContainer = new Panel {CssClass = "formLabel width25pc"}; + pnlRow.Controls.Add(pnlLabelContainer); + + if (string.IsNullOrEmpty(label) == false) { - Panel pnl = new Panel(); - if (ctrl != null) { pnl.Controls.Add(ctrl); } - - if (string.IsNullOrEmpty(cssClass) == false) { pnl.CssClass = cssClass; } - - return pnl; + Label lblField = new Label {Text = label}; + pnlLabelContainer.Controls.Add(lblField); } - public static Control CreateField(string label, Control fieldControl) + Panel pnlFieldContainer = new Panel {CssClass = "formField width75pc"}; + pnlRow.Controls.Add(pnlFieldContainer); + + pnlFieldContainer.Controls.Add(fieldControl); + + return pnlRow; + } + + public static bool Control_IsValid(Control control) + { + return (control as IValidableControl)?.IsValid() != false; + } + + public static bool Controls_AreValid(ControlCollection controls) + { + bool valid = true; + foreach (Control control in controls) { - Panel pnlRow = new Panel {CssClass = "formRow"}; - - Panel pnlLabelContainer = new Panel {CssClass = "formLabel width25pc"}; - pnlRow.Controls.Add(pnlLabelContainer); - - if (string.IsNullOrEmpty(label) == false) + if (Control_IsValid(control)) { - Label lblField = new Label {Text = label}; - pnlLabelContainer.Controls.Add(lblField); - } - - Panel pnlFieldContainer = new Panel {CssClass = "formField width75pc"}; - pnlRow.Controls.Add(pnlFieldContainer); - - pnlFieldContainer.Controls.Add(fieldControl); - - return pnlRow; - } - - public static bool Control_IsValid(Control control) - { - return (control as IValidableControl)?.IsValid() != false; - } - - public static bool Controls_AreValid(ControlCollection controls) - { - bool valid = true; - foreach (Control control in controls) - { - if (Control_IsValid(control)) - { - if (Controls_AreValid(control.Controls) == false) - { - valid = false; - break; - } - } - else + if (Controls_AreValid(control.Controls) == false) { valid = false; break; } } - - return valid; + else + { + valid = false; + break; + } } + + return valid; } } \ No newline at end of file diff --git a/VAR.WebFormsCore/Pages/FrmEcho.cs b/VAR.WebFormsCore/Pages/FrmEcho.cs index ce6eccd..005dfa9 100644 --- a/VAR.WebFormsCore/Pages/FrmEcho.cs +++ b/VAR.WebFormsCore/Pages/FrmEcho.cs @@ -1,20 +1,21 @@ -using Microsoft.AspNetCore.Http; -using VAR.Json; +using VAR.Json; using VAR.WebFormsCore.Code; -namespace VAR.WebFormsCore.Pages +namespace VAR.WebFormsCore.Pages; + +public class FrmEcho : IHttpHandler { - public class FrmEcho : IHttpHandler + #region IHttpHandler + + public void ProcessRequest(IWebContext context) { - #region IHttpHandler - - public void ProcessRequest(HttpContext context) - { - context.Response.WriteAsync("
").GetAwaiter().GetResult();
-            context.Response.WriteAsync(JsonWriter.WriteObject(context.Request, indent: true)).GetAwaiter().GetResult();
-            context.Response.WriteAsync("
").GetAwaiter().GetResult(); - } - - #endregion IHttpHandler + context.ResponseContentType = "text/html"; + context.ResponseWrite("
");
+        context.ResponseWrite($"Header:{JsonWriter.WriteObject(context.RequestHeader, indent: true)}\n");
+        context.ResponseWrite($"Query:{JsonWriter.WriteObject(context.RequestQuery, indent: true)}\n");
+        context.ResponseWrite($"Form:{JsonWriter.WriteObject(context.RequestForm, indent: true)}\n");
+        context.ResponseWrite("
"); } + + #endregion IHttpHandler } \ No newline at end of file diff --git a/VAR.WebFormsCore/Pages/FrmError.cs b/VAR.WebFormsCore/Pages/FrmError.cs index e89bf0e..7e6ac5b 100644 --- a/VAR.WebFormsCore/Pages/FrmError.cs +++ b/VAR.WebFormsCore/Pages/FrmError.cs @@ -2,60 +2,59 @@ using System.Web; using VAR.WebFormsCore.Controls; -namespace VAR.WebFormsCore.Pages +namespace VAR.WebFormsCore.Pages; + +public class FrmError : PageCommon { - public class FrmError : PageCommon + #region Declarations + + private readonly Exception _ex; + + #endregion Declarations + + #region Page life cycle + + public FrmError(Exception ex) { - #region Declarations - - private readonly Exception _ex; - - #endregion Declarations - - #region Page life cycle - - public FrmError(Exception ex) - { - MustBeAuthenticated = false; - _ex = ex; - Init += FrmError_Init; - } - - private void FrmError_Init(object? sender, EventArgs e) { InitializeControls(); } - - #endregion Page life cycle - - #region Private methods - - private void InitializeControls() - { - Title = "Application Error"; - - Label lblErrorTitle = new Label {Text = Title, Tag = "h2"}; - Controls.Add(lblErrorTitle); - - Exception? exAux = _ex; - //if (exAux is HttpUnhandledException && exAux.InnerException != null) { exAux = exAux.InnerException; } - while (exAux != null) - { - LiteralControl lblMessage = new LiteralControl($"

Message: {HttpUtility.HtmlEncode(exAux.Message)}

"); - Controls.Add(lblMessage); - - LiteralControl lblStacktraceTitle = new LiteralControl("

Stacktrace:

"); - Controls.Add(lblStacktraceTitle); - Panel pnlStacktrace = new Panel - { - CssClass = "divCode" - }; - Controls.Add(pnlStacktrace); - LiteralControl litStackTrace = new LiteralControl( - $"
{HttpUtility.HtmlEncode(exAux.StackTrace)}
"); - pnlStacktrace.Controls.Add(litStackTrace); - - exAux = exAux.InnerException; - } - } - - #endregion Private methods + MustBeAuthenticated = false; + _ex = ex; + Init += FrmError_Init; } + + private void FrmError_Init(object? sender, EventArgs e) { InitializeControls(); } + + #endregion Page life cycle + + #region Private methods + + private void InitializeControls() + { + Title = "Application Error"; + + Label lblErrorTitle = new Label {Text = Title, Tag = "h2"}; + Controls.Add(lblErrorTitle); + + Exception? exAux = _ex; + //if (exAux is HttpUnhandledException && exAux.InnerException != null) { exAux = exAux.InnerException; } + while (exAux != null) + { + LiteralControl lblMessage = new LiteralControl($"

Message: {HttpUtility.HtmlEncode(exAux.Message)}

"); + Controls.Add(lblMessage); + + LiteralControl lblStacktraceTitle = new LiteralControl("

Stacktrace:

"); + Controls.Add(lblStacktraceTitle); + Panel pnlStacktrace = new Panel + { + CssClass = "divCode" + }; + Controls.Add(pnlStacktrace); + LiteralControl litStackTrace = new LiteralControl( + $"
{HttpUtility.HtmlEncode(exAux.StackTrace)}
"); + pnlStacktrace.Controls.Add(litStackTrace); + + exAux = exAux.InnerException; + } + } + + #endregion Private methods } \ No newline at end of file diff --git a/VAR.WebFormsCore/Pages/Page.cs b/VAR.WebFormsCore/Pages/Page.cs index ec9ba6f..4edc6e1 100644 --- a/VAR.WebFormsCore/Pages/Page.cs +++ b/VAR.WebFormsCore/Pages/Page.cs @@ -2,76 +2,75 @@ using System.Collections.Generic; using System.IO; using System.Text; -using Microsoft.AspNetCore.Http; using VAR.WebFormsCore.Code; using VAR.WebFormsCore.Controls; -namespace VAR.WebFormsCore.Pages +namespace VAR.WebFormsCore.Pages; + +public class Page : Control, IHttpHandler { - public class Page : Control, IHttpHandler + protected string Title { get; set; } = string.Empty; + + public IWebContext? Context { get; private set; } + + private static readonly Encoding Utf8Encoding = new UTF8Encoding(); + + public void ProcessRequest(IWebContext context) { - protected string Title { get; set; } = string.Empty; - - public HttpContext? Context { get; private set; } - - private static readonly Encoding Utf8Encoding = new UTF8Encoding(); - - public void ProcessRequest(HttpContext context) + try { - try + StringWriter stringWriter = new(); + + Context = context; + Page = this; + + if (context.RequestMethod == "POST") { _isPostBack = true; } + + OnPreInit(EventArgs.Empty); + if (context.ResponseHasStarted) { return; } + + OnInit(EventArgs.Empty); + if (context.ResponseHasStarted) { return; } + + OnLoad(EventArgs.Empty); + if (context.ResponseHasStarted) { return; } + + if (_isPostBack) { - StringWriter stringWriter = new(); - - Context = context; - Page = this; - - if (context.Request.Method == "POST") { _isPostBack = true; } - - OnPreInit(EventArgs.Empty); - if (context.Response.HasStarted) { return; } - - OnInit(EventArgs.Empty); - if (context.Response.HasStarted) { return; } - - OnLoad(EventArgs.Empty); - if (context.Response.HasStarted) { return; } - - if (_isPostBack) + List controls = ChildsOfType(); + foreach (Control control in controls) { - List controls = ChildsOfType(); - foreach (Control control in controls) + string clientID = control.ClientID; + if (context.RequestForm.ContainsKey(clientID)) { - string clientID = control.ClientID; - if (context.Request.Form.ContainsKey(clientID)) - { - (control as IReceivePostbackEvent)?.ReceivePostBack(); - if (context.Response.HasStarted) { return; } - } + (control as IReceivePostbackEvent)?.ReceivePostBack(); + if (context.ResponseHasStarted) { return; } } } - - OnPreRender(EventArgs.Empty); - if (context.Response.HasStarted) { return; } - - Render(stringWriter); - if (context.Response.HasStarted) { return; } - - context.Response.Headers.SafeSet("Content-Type", "text/html"); - byte[] byteObject = Utf8Encoding.GetBytes(stringWriter.ToString()); - context.Response.Body.WriteAsync(byteObject).GetAwaiter().GetResult(); } - catch (Exception ex) - { - // TODO: Implement better error logging - Console.WriteLine("!!!!!!!!!!"); - Console.Write("Message: {0}\nStacktrace: {1}\n", ex.Message, ex.StackTrace); - GlobalErrorHandler.HandleError(context, ex); - } + OnPreRender(EventArgs.Empty); + if (context.ResponseHasStarted) { return; } + + Render(stringWriter); + if (context.ResponseHasStarted) { return; } + + //context.SetResponseHeader("Content-Type", "text/html"); + context.ResponseContentType = "text/html"; + byte[] byteObject = Utf8Encoding.GetBytes(stringWriter.ToString()); + context.ResponseWriteBin(byteObject); } + catch (Exception ex) + { + // TODO: Implement better error logging + Console.WriteLine("!!!!!!!!!!"); + Console.Write("Message: {0}\nStacktrace: {1}\n", ex.Message, ex.StackTrace); - private bool _isPostBack; - - public bool IsPostBack => _isPostBack; + GlobalErrorHandler.HandleError(context, ex); + } } + + private bool _isPostBack; + + public bool IsPostBack => _isPostBack; } \ No newline at end of file diff --git a/VAR.WebFormsCore/Pages/PageCommon.cs b/VAR.WebFormsCore/Pages/PageCommon.cs index 75593f1..7002abc 100644 --- a/VAR.WebFormsCore/Pages/PageCommon.cs +++ b/VAR.WebFormsCore/Pages/PageCommon.cs @@ -3,147 +3,146 @@ using System.Reflection; using VAR.WebFormsCore.Code; using VAR.WebFormsCore.Controls; -namespace VAR.WebFormsCore.Pages +namespace VAR.WebFormsCore.Pages; + +public class PageCommon : Page { - public class PageCommon : Page + #region Declarations + + private readonly HtmlHead _head = new(); + private readonly HtmlBody _body = new(); + private readonly HtmlForm _form = new() {ID = "formMain"}; + private readonly Panel _pnlContainer = new(); + private readonly Button _btnPostback = new(); + private readonly Button _btnLogout = new(); + + private bool _isAuthenticated; + + #endregion Declarations + + #region Properties + + public new ControlCollection Controls => _pnlContainer.Controls; + + public bool MustBeAuthenticated { get; set; } = true; + + #endregion Properties + + #region Life cycle + + public PageCommon() { - #region Declarations - - private readonly HtmlHead _head = new(); - private readonly HtmlBody _body = new(); - private readonly HtmlForm _form = new() {ID = "formMain"}; - private readonly Panel _pnlContainer = new(); - private readonly Button _btnPostback = new(); - private readonly Button _btnLogout = new(); - - private bool _isAuthenticated; - - #endregion Declarations - - #region Properties - - public new ControlCollection Controls => _pnlContainer.Controls; - - public bool MustBeAuthenticated { get; init; } = true; - - #endregion Properties - - #region Life cycle - - public PageCommon() - { - PreInit += PageCommon_PreInit; - Init += PageCommon_Init; - PreRender += PageCommon_PreRender; - } - - private void PageCommon_PreInit(object? sender, EventArgs e) - { - Context?.Response.PrepareUncacheableResponse(); - - if (Context != null) - { - _isAuthenticated = GlobalConfig.Get().IsUserAuthenticated(Context); - } - - if (MustBeAuthenticated && _isAuthenticated == false) - { - Context?.Response.Redirect(GlobalConfig.Get().LoginHandler); - } - } - - private void PageCommon_Init(object? sender, EventArgs e) { CreateControls(); } - - private void PageCommon_PreRender(object? sender, EventArgs e) - { - _head.Title = string.IsNullOrEmpty(Title) - ? GlobalConfig.Get().Title - : string.Concat(Title, GlobalConfig.Get().TitleSeparator, GlobalConfig.Get().Title); - _btnLogout.Visible = _isAuthenticated; - } - - #endregion Life cycle - - #region UI Events - - private void btnLogout_Click(object? sender, EventArgs e) - { - if(Context != null) - { - GlobalConfig.Get().UserDeauthenticate(Context); - } - if (MustBeAuthenticated) { Context?.Response.Redirect(GlobalConfig.Get().LoginHandler); } - } - - #endregion UI Events - - #region Private methods - - private void CreateControls() - { - //Context.Response.Charset = Encoding.UTF8.WebName; - - var doctype = new LiteralControl("\n"); - base.Controls.Add(doctype); - - var html = new HtmlGenericControl("html"); - base.Controls.Add(html); - - html.Controls.Add(_head); - - _head.Controls.Add(new HtmlMeta {HttpEquiv = "X-UA-Compatible", Content = "IE=Edge"}); - _head.Controls.Add(new HtmlMeta {HttpEquiv = "content-type", Content = "text/html; charset=utf-8"}); - _head.Controls.Add(new HtmlMeta {Name = "author", Content = GlobalConfig.Get().Author}); - _head.Controls.Add(new HtmlMeta {Name = "Copyright", Content = GlobalConfig.Get().Copyright}); - _head.Controls.Add( - new HtmlMeta - { - Name = "viewport", - Content = "width=device-width, initial-scale=1, maximum-scale=4, user-scalable=1" - } - ); - - string? version = Assembly.GetExecutingAssembly().GetName().Version?.ToString(); - _head.Controls.Add( - new LiteralControl($"\n") - ); - _head.Controls.Add( - new LiteralControl($"\n") - ); - - html.Controls.Add(_body); - _body.Controls.Add(_form); - - var pnlHeader = new Panel {CssClass = "divHeader"}; - _form.Controls.Add(pnlHeader); - - HyperLink lnkTitle = new HyperLink {NavigateUrl = "."}; - pnlHeader.Controls.Add(lnkTitle); - - var lblTitle = new Label {Text = GlobalConfig.Get().Title, Tag = "h1"}; - lnkTitle.Controls.Add(lblTitle); - - _btnPostback.ID = "btnPostback"; - _btnPostback.Text = "Postback"; - pnlHeader.Controls.Add(_btnPostback); - _btnPostback.Style.Add("display", "none"); - - var pnlUserInfo = new Panel {CssClass = "divUserInfo"}; - pnlHeader.Controls.Add(pnlUserInfo); - - _btnLogout.ID = "btnLogout"; - _btnLogout.Text = MultiLang.GetLiteral("Logout"); - _btnLogout.Click += btnLogout_Click; - _btnLogout.Attributes.Add( - "onclick", - $"return confirm('{MultiLang.GetLiteral("ConfirmExit")}');" - ); - pnlUserInfo.Controls.Add(_btnLogout); - - _pnlContainer.CssClass = "divContent"; - _form.Controls.Add(_pnlContainer); - } - - #endregion Private methods + PreInit += PageCommon_PreInit; + Init += PageCommon_Init; + PreRender += PageCommon_PreRender; } + + private void PageCommon_PreInit(object? sender, EventArgs e) + { + Context?.PrepareUncacheableResponse(); + + if (Context != null) + { + _isAuthenticated = GlobalConfig.Get().IsUserAuthenticated(Context); + } + + if (MustBeAuthenticated && _isAuthenticated == false) + { + Context?.ResponseRedirect(GlobalConfig.Get().LoginHandler); + } + } + + private void PageCommon_Init(object? sender, EventArgs e) { CreateControls(); } + + private void PageCommon_PreRender(object? sender, EventArgs e) + { + _head.Title = string.IsNullOrEmpty(Title) + ? GlobalConfig.Get().Title + : string.Concat(Title, GlobalConfig.Get().TitleSeparator, GlobalConfig.Get().Title); + _btnLogout.Visible = _isAuthenticated; + } + + #endregion Life cycle + + #region UI Events + + private void btnLogout_Click(object? sender, EventArgs e) + { + if(Context != null) + { + GlobalConfig.Get().UserDeauthenticate(Context); + } + if (MustBeAuthenticated) { Context?.ResponseRedirect(GlobalConfig.Get().LoginHandler); } + } + + #endregion UI Events + + #region Private methods + + private void CreateControls() + { + //Context.Response.Charset = Encoding.UTF8.WebName; + + var doctype = new LiteralControl("\n"); + base.Controls.Add(doctype); + + var html = new HtmlGenericControl("html"); + base.Controls.Add(html); + + html.Controls.Add(_head); + + _head.Controls.Add(new HtmlMeta {HttpEquiv = "X-UA-Compatible", Content = "IE=Edge"}); + _head.Controls.Add(new HtmlMeta {HttpEquiv = "content-type", Content = "text/html; charset=utf-8"}); + _head.Controls.Add(new HtmlMeta {Name = "author", Content = GlobalConfig.Get().Author}); + _head.Controls.Add(new HtmlMeta {Name = "Copyright", Content = GlobalConfig.Get().Copyright}); + _head.Controls.Add( + new HtmlMeta + { + Name = "viewport", + Content = "width=device-width, initial-scale=1, maximum-scale=4, user-scalable=1" + } + ); + + string? version = Assembly.GetExecutingAssembly().GetName().Version?.ToString(); + _head.Controls.Add( + new LiteralControl($"\n") + ); + _head.Controls.Add( + new LiteralControl($"\n") + ); + + html.Controls.Add(_body); + _body.Controls.Add(_form); + + var pnlHeader = new Panel {CssClass = "divHeader"}; + _form.Controls.Add(pnlHeader); + + HyperLink lnkTitle = new HyperLink {NavigateUrl = "."}; + pnlHeader.Controls.Add(lnkTitle); + + var lblTitle = new Label {Text = GlobalConfig.Get().Title, Tag = "h1"}; + lnkTitle.Controls.Add(lblTitle); + + _btnPostback.ID = "btnPostback"; + _btnPostback.Text = "Postback"; + pnlHeader.Controls.Add(_btnPostback); + _btnPostback.Style.Add("display", "none"); + + var pnlUserInfo = new Panel {CssClass = "divUserInfo"}; + pnlHeader.Controls.Add(pnlUserInfo); + + _btnLogout.ID = "btnLogout"; + _btnLogout.Text = MultiLang.GetLiteral("Logout"); + _btnLogout.Click += btnLogout_Click; + _btnLogout.Attributes.Add( + "onclick", + $"return confirm('{MultiLang.GetLiteral("ConfirmExit")}');" + ); + pnlUserInfo.Controls.Add(_btnLogout); + + _pnlContainer.CssClass = "divContent"; + _form.Controls.Add(_pnlContainer); + } + + #endregion Private methods } \ No newline at end of file diff --git a/VAR.WebFormsCore/Properties/launchSettings.json b/VAR.WebFormsCore/Properties/launchSettings.json deleted file mode 100644 index 1fa47cd..0000000 --- a/VAR.WebFormsCore/Properties/launchSettings.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:58454/", - "sslPort": 44386 - } - }, - "profiles": { - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "VAR.WebFormsCore": { - "commandName": "Project", - "launchBrowser": true, - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "applicationUrl": "https://localhost:5001;http://localhost:5000" - } - } -} \ No newline at end of file diff --git a/VAR.WebFormsCore/VAR.WebFormsCore.csproj b/VAR.WebFormsCore/VAR.WebFormsCore.csproj index 541ba73..71ed762 100644 --- a/VAR.WebFormsCore/VAR.WebFormsCore.csproj +++ b/VAR.WebFormsCore/VAR.WebFormsCore.csproj @@ -1,9 +1,10 @@ - + Library - net7.0 + netstandard2.0 enable + 10