Extract AspNetCore dependency to VAR.WebFormsCore.AspNetCore.

* Abstract HttpContext with IWebContext.
* Move AspNetCore dependant code to isolated classes.
* Downgrade VAR.WebFormsCore to netstandard2.0.
This commit is contained in:
2023-05-28 04:33:44 +02:00
parent f52d80e643
commit 1eb0fea182
53 changed files with 1847 additions and 1708 deletions

View File

@@ -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<string, string?>? _requestHeader;
public Dictionary<string, string?> RequestHeader
{
get
{
if (_requestHeader == null)
{
_requestHeader = _context.Request.Headers
.ToDictionary(p => p.Key, p => p.Value[0]);
}
return _requestHeader;
}
}
private Dictionary<string, string?>? _requestQuery;
public Dictionary<string, string?> RequestQuery
{
get
{
if (_requestQuery == null)
{
_requestQuery = _context.Request.Query
.ToDictionary(p => p.Key, p => p.Value[0]);
}
return _requestQuery;
}
}
private Dictionary<string, string?>? _requestForm;
public Dictionary<string, string?> 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<string, string?>();
}
}
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");
}
}

View File

@@ -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
}
}

View File

@@ -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<GlobalRouterMiddleware>(env);
}
}

View File

@@ -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<Startup>();
});
}

View File

@@ -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<KestrelServerOptions>(options =>
{
options.AddServerHeader = false;
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseGlobalRouterMiddleware(env);
}
}

View File

@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\VAR.WebFormsCore\VAR.WebFormsCore.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,3 +1,4 @@
using System;
using VAR.WebFormsCore.Code; using VAR.WebFormsCore.Code;
using VAR.WebFormsCore.Controls; using VAR.WebFormsCore.Controls;
using VAR.WebFormsCore.Pages; using VAR.WebFormsCore.Pages;

View File

@@ -1,17 +1,12 @@
namespace VAR.WebFormsCore.TestWebApp using VAR.WebFormsCore.AspNetCore;
namespace VAR.WebFormsCore.TestWebApp;
public static class Program
{ {
public static class Program
{
public static void Main(string[] args) public static void Main(string[] args)
{ {
CreateHostBuilder(args).Build().Run(); DefaultMain.WebFormCoreMain(args);
} }
private static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
} }

View File

@@ -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<KestrelServerOptions>(options =>
{
options.AddServerHeader = false;
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseGlobalRouterMiddleware(env);
}
}
}

View File

@@ -1,3 +1,4 @@
using System.Collections.Generic;
using VAR.WebFormsCore.Code; using VAR.WebFormsCore.Code;
namespace VAR.WebFormsCore.TestWebApp; namespace VAR.WebFormsCore.TestWebApp;
@@ -14,12 +15,12 @@ public class TestWebAppGlobalConfig : IGlobalConfig
public List<string> AllowedExtensions { get; } = new() public List<string> AllowedExtensions { get; } = new()
{ ".png", ".jpg", ".jpeg", ".gif", ".ico", ".wav", ".mp3", ".ogg", ".mp4", ".webm", ".webp", ".mkv", ".avi" }; { ".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; return false;
} }
public void UserDeauthenticate(HttpContext context) public void UserDeauthenticate(IWebContext context)
{ {
} }
} }

View File

@@ -3,10 +3,10 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\VAR.WebFormsCore.AspNetCore\VAR.WebFormsCore.AspNetCore.csproj" />
<ProjectReference Include="..\VAR.WebFormsCore\VAR.WebFormsCore.csproj" /> <ProjectReference Include="..\VAR.WebFormsCore\VAR.WebFormsCore.csproj" />
</ItemGroup> </ItemGroup>

View File

@@ -4,6 +4,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VAR.WebFormsCore", "VAR.Web
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VAR.WebFormsCore.TestWebApp", "VAR.WebFormsCore.TestWebApp\VAR.WebFormsCore.TestWebApp.csproj", "{0D81464B-802D-4ECA-92C8-427F481A4583}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VAR.WebFormsCore.TestWebApp", "VAR.WebFormsCore.TestWebApp\VAR.WebFormsCore.TestWebApp.csproj", "{0D81464B-802D-4ECA-92C8-427F481A4583}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VAR.WebFormsCore.AspNetCore", "VAR.WebFormsCore.AspNetCore\VAR.WebFormsCore.AspNetCore.csproj", "{378B98EF-9269-4B96-B894-1B0F9B24EEC2}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU 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}.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.ActiveCfg = Release|Any CPU
{0D81464B-802D-4ECA-92C8-427F481A4583}.Release|Any CPU.Build.0 = 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 EndGlobalSection
EndGlobal EndGlobal

View File

@@ -3,12 +3,11 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
using Microsoft.AspNetCore.Http;
namespace VAR.WebFormsCore.Code namespace VAR.WebFormsCore.Code;
public class Bundler
{ {
public class Bundler
{
#region Declarations #region Declarations
private readonly Assembly? _assembly; private readonly Assembly? _assembly;
@@ -75,10 +74,10 @@ namespace VAR.WebFormsCore.Code
private static readonly Encoding Utf8Encoding = new UTF8Encoding(); private static readonly Encoding Utf8Encoding = new UTF8Encoding();
public void WriteResponse(HttpResponse response, string contentType) public void WriteResponse(IWebContext context, string contentType)
{ {
StringWriter textWriter = new StringWriter(); StringWriter textWriter = new StringWriter();
response.ContentType = contentType; context.ResponseContentType = contentType;
foreach (string fileName in AssemblyFiles) foreach (string fileName in AssemblyFiles)
{ {
Stream? resourceStream = _assembly?.GetManifestResourceStream(fileName); Stream? resourceStream = _assembly?.GetManifestResourceStream(fileName);
@@ -99,9 +98,8 @@ namespace VAR.WebFormsCore.Code
} }
byte[] byteObject = Utf8Encoding.GetBytes(textWriter.ToString()); byte[] byteObject = Utf8Encoding.GetBytes(textWriter.ToString());
response.Body.WriteAsync(byteObject).GetAwaiter().GetResult(); context.ResponseWriteBin(byteObject);
} }
#endregion Public methods #endregion Public methods
}
} }

View File

@@ -1,27 +1,31 @@
using System;
using System.Text; using System.Text;
using Microsoft.AspNetCore.Http;
using VAR.Json; using VAR.Json;
namespace VAR.WebFormsCore.Code namespace VAR.WebFormsCore.Code;
public static class ExtensionMethods
{ {
public static class ExtensionMethods #region IWebContext
{
#region HttpContext
public static string GetRequestParameter(this HttpContext context, string parameter) public static string GetRequestParameter(this IWebContext context, string parameter)
{ {
if (context.Request.Method == "POST") if (context.RequestMethod == "POST")
{ {
foreach (string key in context.Request.Form.Keys) foreach (string key in context.RequestForm.Keys)
{ {
if (string.IsNullOrEmpty(key) == false && key == parameter) { return context.Request.Form[key][0] ?? string.Empty; } if (string.IsNullOrEmpty(key) == false && key == parameter)
{
return context.RequestForm[key] ?? string.Empty;
}
} }
} }
foreach (string key in context.Request.Query.Keys) foreach (string key in context.RequestQuery.Keys)
{ {
if (string.IsNullOrEmpty(key) == false && key == parameter) { return context.Request.Query[key][0] ?? string.Empty; } if (string.IsNullOrEmpty(key) == false && key == parameter)
{
return context.RequestQuery[key] ?? string.Empty;
}
} }
return string.Empty; return string.Empty;
@@ -29,38 +33,13 @@ namespace VAR.WebFormsCore.Code
private static readonly Encoding Utf8Encoding = new UTF8Encoding(); private static readonly Encoding Utf8Encoding = new UTF8Encoding();
public static void ResponseObject(this HttpContext context, object obj, string contentType = "text/json") public static void ResponseObject(this IWebContext context, object obj, string contentType = "text/json")
{ {
context.Response.ContentType = contentType; context.ResponseContentType = contentType;
string strObject = JsonWriter.WriteObject(obj); string strObject = JsonWriter.WriteObject(obj);
byte[] byteObject = Utf8Encoding.GetBytes(strObject); byte[] byteObject = Utf8Encoding.GetBytes(strObject);
context.Response.Body.WriteAsync(byteObject).GetAwaiter().GetResult(); context.ResponseWriteBin(byteObject);
} }
public static void SafeSet(this IHeaderDictionary header, string key, string value) { header[key] = value; } #endregion IWebContext
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
}
} }

View File

@@ -1,12 +1,11 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; 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; private static IGlobalConfig? _globalConfig;
public static IGlobalConfig Get() public static IGlobalConfig Get()
@@ -41,14 +40,13 @@ namespace VAR.WebFormsCore.Code
public string LoginHandler => string.Empty; public string LoginHandler => string.Empty;
public List<string> AllowedExtensions { get; } = new(); public List<string> AllowedExtensions { get; } = new();
public bool IsUserAuthenticated(HttpContext context) public bool IsUserAuthenticated(IWebContext context)
{ {
return false; return false;
} }
public void UserDeauthenticate(HttpContext context) public void UserDeauthenticate(IWebContext context)
{ {
} }
} }
}
} }

View File

@@ -1,19 +1,18 @@
using System; using System;
using System.Text; using System.Text;
using Microsoft.AspNetCore.Http;
using VAR.WebFormsCore.Pages; using VAR.WebFormsCore.Pages;
namespace VAR.WebFormsCore.Code namespace VAR.WebFormsCore.Code;
public static class GlobalErrorHandler
{ {
public static class GlobalErrorHandler
{
#region Private methods #region Private methods
private static void ShowInternalError(HttpContext context, Exception ex) private static void ShowInternalError(IWebContext context, Exception ex)
{ {
try try
{ {
context.Response.StatusCode = 500; context.ResponseStatusCode = 500;
StringBuilder sbOutput = new StringBuilder(); StringBuilder sbOutput = new StringBuilder();
sbOutput.Append("<h2>Internal error</h2>"); sbOutput.Append("<h2>Internal error</h2>");
@@ -35,8 +34,8 @@ namespace VAR.WebFormsCore.Code
sbOutput.Append("-->"); sbOutput.Append("-->");
} }
context.Response.WriteAsync(sbOutput.ToString()).GetAwaiter().GetResult(); context.ResponseWrite(sbOutput.ToString());
context.Response.Body.FlushAsync().GetAwaiter().GetResult(); context.ResponseFlush();
} }
catch catch
{ {
@@ -48,7 +47,7 @@ namespace VAR.WebFormsCore.Code
#region Public methods #region Public methods
public static void HandleError(HttpContext context, Exception ex) public static void HandleError(IWebContext context, Exception ex)
{ {
try try
{ {
@@ -56,11 +55,10 @@ namespace VAR.WebFormsCore.Code
//context.Response.Clear(); //context.Response.Clear();
//context.Handler = frmError; //context.Handler = frmError;
frmError.ProcessRequest(context); frmError.ProcessRequest(context);
context.Response.Body.FlushAsync().GetAwaiter().GetResult(); context.ResponseFlush();
} }
catch { ShowInternalError(context, ex); } catch { ShowInternalError(context, ex); }
} }
#endregion Public methods #endregion Public methods
}
} }

View File

@@ -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<string, Type> 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;
}
}

View File

@@ -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<string, Type> 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<GlobalRouterMiddleware>(env);
}
}
}

View File

@@ -1,10 +1,9 @@
using System.Collections.Generic; 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 Title { get; }
string TitleSeparator { get; } string TitleSeparator { get; }
string Author { get; } string Author { get; }
@@ -13,7 +12,6 @@ namespace VAR.WebFormsCore.Code
string LoginHandler { get; } string LoginHandler { get; }
List<string> AllowedExtensions { get; } List<string> AllowedExtensions { get; }
bool IsUserAuthenticated(HttpContext context); bool IsUserAuthenticated(IWebContext context);
void UserDeauthenticate(HttpContext context); void UserDeauthenticate(IWebContext context);
}
} }

View File

@@ -1,9 +1,6 @@
using Microsoft.AspNetCore.Http; namespace VAR.WebFormsCore.Code;
namespace VAR.WebFormsCore.Code public interface IHttpHandler
{ {
public interface IHttpHandler void ProcessRequest(IWebContext context);
{
void ProcessRequest(HttpContext context);
}
} }

View File

@@ -0,0 +1,25 @@
using System.Collections.Generic;
namespace VAR.WebFormsCore.Code;
public interface IWebContext
{
string RequestPath { get; }
string RequestMethod { get; }
Dictionary<string, string?> RequestForm { get; }
Dictionary<string, string?> RequestQuery { get; }
Dictionary<string, string?> 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();
}

View File

@@ -2,10 +2,10 @@
using System.IO; using System.IO;
using VAR.Json; 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 currentDir = Directory.GetCurrentDirectory();
@@ -92,5 +92,4 @@ namespace VAR.WebFormsCore.Code
return (literalCurrentCulture[resource] as string) ?? resource; return (literalCurrentCulture[resource] as string) ?? resource;
} }
}
} }

View File

@@ -2,10 +2,10 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq.Expressions; using System.Linq.Expressions;
namespace VAR.WebFormsCore.Code namespace VAR.WebFormsCore.Code;
public static class ObjectActivator
{ {
public static class ObjectActivator
{
private static readonly Dictionary<Type, Func<object>> Creators = new(); private static readonly Dictionary<Type, Func<object>> Creators = new();
private static Func<object> GetLambdaNew(Type type) private static Func<object> GetLambdaNew(Type type)
@@ -29,5 +29,4 @@ namespace VAR.WebFormsCore.Code
Func<object> creator = GetLambdaNew(type); Func<object> creator = GetLambdaNew(type);
return creator(); return creator();
} }
}
} }

View File

@@ -1,23 +1,21 @@
using System.Reflection; 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 #region IHttpHandler
public void ProcessRequest(HttpContext context) public void ProcessRequest(IWebContext context)
{ {
Bundler bundler = new Bundler( Bundler bundler = new Bundler(
assembly: Assembly.GetExecutingAssembly(), assembly: Assembly.GetExecutingAssembly(),
assemblyNamespace: "Scripts", assemblyNamespace: "Scripts",
absolutePath: ServerHelpers.MapContentPath("Scripts") absolutePath: ServerHelpers.MapContentPath("Scripts")
); );
context.Response.PrepareCacheableResponse(); context.PrepareCacheableResponse();
bundler.WriteResponse(context.Response, "text/javascript"); bundler.WriteResponse(context, "text/javascript");
} }
#endregion IHttpHandler #endregion IHttpHandler
}
} }

View File

@@ -1,10 +1,10 @@
using System.Globalization; using System.Globalization;
using System.Text; using System.Text;
namespace VAR.WebFormsCore.Code namespace VAR.WebFormsCore.Code;
public static class ServerHelpers
{ {
public static class ServerHelpers
{
private static string? _contentRoot; private static string? _contentRoot;
public static void SetContentRoot(string contentRoot) public static void SetContentRoot(string contentRoot)
@@ -114,5 +114,4 @@ namespace VAR.WebFormsCore.Code
return false; return false;
} }
}
} }

View File

@@ -1,11 +1,10 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; 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<string, string> MimeTypeByExtension = new() private static readonly Dictionary<string, string> MimeTypeByExtension = new()
{ {
{".aac", "audio/aac"}, {".aac", "audio/aac"},
@@ -68,17 +67,16 @@ namespace VAR.WebFormsCore.Code
{".7z", "application/x-7z-compressed"}, {".7z", "application/x-7z-compressed"},
}; };
public static void ResponseStaticFile(HttpContext context, string filePath) public static void ResponseStaticFile(IWebContext context, string filePath)
{ {
string extension = Path.GetExtension(filePath).ToLower(); string extension = Path.GetExtension(filePath).ToLower();
MimeTypeByExtension.TryGetValue(extension, out string? contentType); 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); byte[] fileData = File.ReadAllBytes(filePath);
context.Response.Body.WriteAsync(fileData).GetAwaiter().GetResult(); context.ResponseWriteBin(fileData);
}
} }
} }

View File

@@ -1,23 +1,21 @@
using System.Reflection; 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 #region IHttpHandler
public void ProcessRequest(HttpContext context) public void ProcessRequest(IWebContext context)
{ {
Bundler bundler = new Bundler( Bundler bundler = new Bundler(
assembly: Assembly.GetExecutingAssembly(), assembly: Assembly.GetExecutingAssembly(),
assemblyNamespace: "Styles", assemblyNamespace: "Styles",
absolutePath: ServerHelpers.MapContentPath("Styles") absolutePath: ServerHelpers.MapContentPath("Styles")
); );
context.Response.PrepareCacheableResponse(); context.PrepareCacheableResponse();
bundler.WriteResponse(context.Response, "text/css"); bundler.WriteResponse(context, "text/css");
} }
#endregion IHttpHandler #endregion IHttpHandler
}
} }

View File

@@ -1,7 +1,7 @@
namespace VAR.WebFormsCore.Code namespace VAR.WebFormsCore.Code;
public class Unit
{ {
public class Unit
{
private readonly int _value; private readonly int _value;
private readonly UnitType _unitType; private readonly UnitType _unitType;
@@ -19,10 +19,9 @@
return string.Empty; return string.Empty;
} }
} }
public enum UnitType public enum UnitType
{ {
Pixel, Percentage, Pixel, Percentage,
}
} }

View File

@@ -1,10 +1,10 @@
using System; using System;
using System.IO; 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"; } public Button() { CssClass = "button"; }
private string _text = string.Empty; private string _text = string.Empty;
@@ -38,5 +38,4 @@ namespace VAR.WebFormsCore.Controls
} }
public void ReceivePostBack() { Click?.Invoke(this, EventArgs.Empty); } public void ReceivePostBack() { Click?.Invoke(this, EventArgs.Empty); }
}
} }

View File

@@ -3,10 +3,10 @@ using System.Collections.Generic;
using System.Text; using System.Text;
using VAR.Json; 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 #region Declarations
private readonly TextBox _txtContent = new(); private readonly TextBox _txtContent = new();
@@ -75,7 +75,7 @@ namespace VAR.WebFormsCore.Controls
public TextBoxMode TextMode public TextBoxMode TextMode
{ {
get => _txtContent.TextMode; get => _txtContent.TextMode;
init => _txtContent.TextMode = value; set => _txtContent.TextMode = value;
} }
#endregion Properties #endregion Properties
@@ -157,7 +157,7 @@ namespace VAR.WebFormsCore.Controls
if (string.IsNullOrEmpty(_hidSize?.Value)) { return null; } if (string.IsNullOrEmpty(_hidSize?.Value)) { return null; }
JsonParser jsonParser = new JsonParser(); JsonParser jsonParser = new JsonParser();
Dictionary<string, object>? sizeObj = jsonParser.Parse(_hidSize.Value) as Dictionary<string, object>; Dictionary<string, object>? sizeObj = jsonParser.Parse(_hidSize?.Value) as Dictionary<string, object>;
if (sizeObj == null) { return null; } if (sizeObj == null) { return null; }
if (sizeObj.ContainsKey("height") == false) { return null; } if (sizeObj.ContainsKey("height") == false) { return null; }
@@ -180,7 +180,7 @@ namespace VAR.WebFormsCore.Controls
if (string.IsNullOrEmpty(_hidSize?.Value) == false) if (string.IsNullOrEmpty(_hidSize?.Value) == false)
{ {
JsonParser jsonParser = new JsonParser(); JsonParser jsonParser = new JsonParser();
sizeObj = jsonParser.Parse(_hidSize.Value) as Dictionary<string, object?>; sizeObj = jsonParser.Parse(_hidSize?.Value) as Dictionary<string, object?>;
} }
sizeObj ??= new Dictionary<string, object?> { { "height", height }, { "width", null }, { "scrollTop", null }, }; sizeObj ??= new Dictionary<string, object?> { { "height", height }, { "width", null }, { "scrollTop", null }, };
@@ -191,5 +191,4 @@ namespace VAR.WebFormsCore.Controls
} }
#endregion Public methods #endregion Public methods
}
} }

View File

@@ -5,10 +5,10 @@ using System.Text;
using VAR.WebFormsCore.Code; using VAR.WebFormsCore.Code;
using VAR.WebFormsCore.Pages; using VAR.WebFormsCore.Pages;
namespace VAR.WebFormsCore.Controls namespace VAR.WebFormsCore.Controls;
public class Control
{ {
public class Control
{
public event EventHandler? PreInit; public event EventHandler? PreInit;
protected void OnPreInit(EventArgs e) protected void OnPreInit(EventArgs e)
@@ -194,5 +194,4 @@ namespace VAR.WebFormsCore.Controls
return controls; return controls;
} }
}
} }

View File

@@ -1,9 +1,9 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace VAR.WebFormsCore.Controls namespace VAR.WebFormsCore.Controls;
public class ControlCollection : List<Control>
{ {
public class ControlCollection : List<Control>
{
private readonly Control _parent; private readonly Control _parent;
private int _index; private int _index;
@@ -17,5 +17,4 @@ namespace VAR.WebFormsCore.Controls
_index++; _index++;
base.Add(control); base.Add(control);
} }
}
} }

View File

@@ -1,9 +1,9 @@
using System.IO; using System.IO;
namespace VAR.WebFormsCore.Controls namespace VAR.WebFormsCore.Controls;
public class HiddenField : Control
{ {
public class HiddenField : Control
{
private string _value = string.Empty; private string _value = string.Empty;
public string Value public string Value
@@ -14,9 +14,9 @@ namespace VAR.WebFormsCore.Controls
protected override void Process() protected override void Process()
{ {
if (Page?.IsPostBack == true && Page?.Context?.Request.Form.ContainsKey(ClientID) == true) if (Page?.IsPostBack == true && Page?.Context?.RequestForm.ContainsKey(ClientID) == true)
{ {
Value = Page?.Context.Request.Form[ClientID][0] ?? string.Empty; Value = Page?.Context.RequestForm[ClientID] ?? string.Empty;
} }
} }
@@ -29,5 +29,4 @@ namespace VAR.WebFormsCore.Controls
textWriter.Write(">"); textWriter.Write(">");
textWriter.Write("</input>"); textWriter.Write("</input>");
} }
}
} }

View File

@@ -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") { }
}
} }

View File

@@ -1,7 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text; using System.Text;
using Microsoft.Extensions.Primitives;
using VAR.WebFormsCore.Code; using VAR.WebFormsCore.Code;
namespace VAR.WebFormsCore.Controls namespace VAR.WebFormsCore.Controls
@@ -28,15 +27,15 @@ namespace VAR.WebFormsCore.Controls
StringBuilder sbAction = new(); StringBuilder sbAction = new();
sbAction.Append(Page?.GetType().Name); 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('?'); sbAction.Append('?');
if (Page?.Context?.Request.Query != null) if (Page?.Context?.RequestQuery != null)
{ {
foreach (KeyValuePair<string, StringValues> queryParam in Page.Context.Request.Query) foreach (KeyValuePair<string, string?> queryParam in Page.Context.RequestQuery)
{ {
string key = ServerHelpers.UrlEncode(queryParam.Key); 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}"); sbAction.Append($"&{key}={value}");
} }
} }

View File

@@ -1,9 +1,9 @@
using System.IO; using System.IO;
namespace VAR.WebFormsCore.Controls namespace VAR.WebFormsCore.Controls;
public class HtmlGenericControl : Control
{ {
public class HtmlGenericControl : Control
{
private readonly string _tagName; private readonly string _tagName;
public HtmlGenericControl(string tag) { _tagName = tag; } public HtmlGenericControl(string tag) { _tagName = tag; }
@@ -18,5 +18,4 @@ namespace VAR.WebFormsCore.Controls
textWriter.Write("</{0}>", _tagName); textWriter.Write("</{0}>", _tagName);
} }
}
} }

View File

@@ -1,9 +1,9 @@
using System.IO; 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; public string Title { get; set; } = string.Empty;
protected override void Render(TextWriter textWriter) protected override void Render(TextWriter textWriter)
@@ -18,5 +18,4 @@ namespace VAR.WebFormsCore.Controls
textWriter.Write("</head>"); textWriter.Write("</head>");
} }
}
} }

View File

@@ -1,12 +1,12 @@
using System.IO; 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 Name { get; init; } = string.Empty; public string HttpEquiv { get; set; } = string.Empty;
public string Content { get; init; } = string.Empty;
public string HttpEquiv { get; internal init; } = string.Empty;
protected override void Render(TextWriter textWriter) protected override void Render(TextWriter textWriter)
{ {
@@ -20,5 +20,4 @@ namespace VAR.WebFormsCore.Controls
textWriter.Write(" />"); textWriter.Write(" />");
} }
}
} }

View File

@@ -1,11 +1,11 @@
using System.IO; 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 NavigateUrl { get; set; } = string.Empty;
public string Text { get; init; } = string.Empty; public string Text { get; set; } = string.Empty;
protected override void Render(TextWriter textWriter) protected override void Render(TextWriter textWriter)
{ {
@@ -21,5 +21,4 @@ namespace VAR.WebFormsCore.Controls
textWriter.Write("</a>"); textWriter.Write("</a>");
} }
}
} }

View File

@@ -1,6 +1,5 @@
namespace VAR.WebFormsCore.Controls namespace VAR.WebFormsCore.Controls;
public interface INamingContainer
{ {
public interface INamingContainer
{
}
} }

View File

@@ -1,7 +1,6 @@
namespace VAR.WebFormsCore.Controls namespace VAR.WebFormsCore.Controls;
public interface IReceivePostbackEvent
{ {
public interface IReceivePostbackEvent
{
void ReceivePostBack(); void ReceivePostBack();
}
} }

View File

@@ -1,7 +1,6 @@
namespace VAR.WebFormsCore.Controls namespace VAR.WebFormsCore.Controls;
public interface IValidableControl
{ {
public interface IValidableControl
{
bool IsValid(); bool IsValid();
}
} }

View File

@@ -1,10 +1,10 @@
using System.IO; using System.IO;
using VAR.WebFormsCore.Code; using VAR.WebFormsCore.Code;
namespace VAR.WebFormsCore.Controls namespace VAR.WebFormsCore.Controls;
public class Label : Control
{ {
public class Label : Control
{
#region Properties #region Properties
private string _tagName = "span"; private string _tagName = "span";
@@ -41,5 +41,4 @@ namespace VAR.WebFormsCore.Controls
} }
#endregion Life cycle #endregion Life cycle
}
} }

View File

@@ -1,14 +1,13 @@
using System.IO; 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() { }
public LiteralControl(string content) { Content = content; } public LiteralControl(string content) { Content = content; }
protected override void Render(TextWriter textWriter) { textWriter.Write(Content); } protected override void Render(TextWriter textWriter) { textWriter.Write(Content); }
}
} }

View File

@@ -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") { }
}
} }

View File

@@ -1,19 +1,19 @@
using System.IO; using System.IO;
using VAR.WebFormsCore.Code; 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 string Text { get; set; } = string.Empty;
public TextBoxMode TextMode { get; set; } = TextBoxMode.Normal; public TextBoxMode TextMode { get; set; } = TextBoxMode.Normal;
protected override void Process() protected override void Process()
{ {
if (Page?.IsPostBack == true && Page?.Context?.Request.Form.ContainsKey(ClientID) == true) if (Page?.IsPostBack == true && Page?.Context?.RequestForm.ContainsKey(ClientID) == true)
{ {
Text = Page?.Context.Request.Form[ClientID][0] ?? string.Empty; Text = Page?.Context.RequestForm[ClientID] ?? string.Empty;
} }
} }
@@ -46,10 +46,9 @@ namespace VAR.WebFormsCore.Controls
textWriter.Write("</input>"); textWriter.Write("</input>");
} }
} }
} }
public enum TextBoxMode public enum TextBoxMode
{ {
Normal, Password, MultiLine, Normal, Password, MultiLine,
}
} }

View File

@@ -1,9 +1,9 @@
using VAR.WebFormsCore.Controls; 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(); Panel pnl = new Panel();
@@ -62,5 +62,4 @@ namespace VAR.WebFormsCore.Pages
return valid; return valid;
} }
}
} }

View File

@@ -1,20 +1,21 @@
using Microsoft.AspNetCore.Http; using VAR.Json;
using VAR.Json;
using VAR.WebFormsCore.Code; using VAR.WebFormsCore.Code;
namespace VAR.WebFormsCore.Pages namespace VAR.WebFormsCore.Pages;
public class FrmEcho : IHttpHandler
{ {
public class FrmEcho : IHttpHandler
{
#region IHttpHandler #region IHttpHandler
public void ProcessRequest(HttpContext context) public void ProcessRequest(IWebContext context)
{ {
context.Response.WriteAsync("<pre><code>").GetAwaiter().GetResult(); context.ResponseContentType = "text/html";
context.Response.WriteAsync(JsonWriter.WriteObject(context.Request, indent: true)).GetAwaiter().GetResult(); context.ResponseWrite("<pre><code>");
context.Response.WriteAsync("</code></pre>").GetAwaiter().GetResult(); 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("</code></pre>");
} }
#endregion IHttpHandler #endregion IHttpHandler
}
} }

View File

@@ -2,10 +2,10 @@
using System.Web; using System.Web;
using VAR.WebFormsCore.Controls; using VAR.WebFormsCore.Controls;
namespace VAR.WebFormsCore.Pages namespace VAR.WebFormsCore.Pages;
public class FrmError : PageCommon
{ {
public class FrmError : PageCommon
{
#region Declarations #region Declarations
private readonly Exception _ex; private readonly Exception _ex;
@@ -57,5 +57,4 @@ namespace VAR.WebFormsCore.Pages
} }
#endregion Private methods #endregion Private methods
}
} }

View File

@@ -2,21 +2,20 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text; using System.Text;
using Microsoft.AspNetCore.Http;
using VAR.WebFormsCore.Code; using VAR.WebFormsCore.Code;
using VAR.WebFormsCore.Controls; 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; protected string Title { get; set; } = string.Empty;
public HttpContext? Context { get; private set; } public IWebContext? Context { get; private set; }
private static readonly Encoding Utf8Encoding = new UTF8Encoding(); private static readonly Encoding Utf8Encoding = new UTF8Encoding();
public void ProcessRequest(HttpContext context) public void ProcessRequest(IWebContext context)
{ {
try try
{ {
@@ -25,16 +24,16 @@ namespace VAR.WebFormsCore.Pages
Context = context; Context = context;
Page = this; Page = this;
if (context.Request.Method == "POST") { _isPostBack = true; } if (context.RequestMethod == "POST") { _isPostBack = true; }
OnPreInit(EventArgs.Empty); OnPreInit(EventArgs.Empty);
if (context.Response.HasStarted) { return; } if (context.ResponseHasStarted) { return; }
OnInit(EventArgs.Empty); OnInit(EventArgs.Empty);
if (context.Response.HasStarted) { return; } if (context.ResponseHasStarted) { return; }
OnLoad(EventArgs.Empty); OnLoad(EventArgs.Empty);
if (context.Response.HasStarted) { return; } if (context.ResponseHasStarted) { return; }
if (_isPostBack) if (_isPostBack)
{ {
@@ -42,23 +41,24 @@ namespace VAR.WebFormsCore.Pages
foreach (Control control in controls) foreach (Control control in controls)
{ {
string clientID = control.ClientID; string clientID = control.ClientID;
if (context.Request.Form.ContainsKey(clientID)) if (context.RequestForm.ContainsKey(clientID))
{ {
(control as IReceivePostbackEvent)?.ReceivePostBack(); (control as IReceivePostbackEvent)?.ReceivePostBack();
if (context.Response.HasStarted) { return; } if (context.ResponseHasStarted) { return; }
} }
} }
} }
OnPreRender(EventArgs.Empty); OnPreRender(EventArgs.Empty);
if (context.Response.HasStarted) { return; } if (context.ResponseHasStarted) { return; }
Render(stringWriter); Render(stringWriter);
if (context.Response.HasStarted) { return; } if (context.ResponseHasStarted) { return; }
context.Response.Headers.SafeSet("Content-Type", "text/html"); //context.SetResponseHeader("Content-Type", "text/html");
context.ResponseContentType = "text/html";
byte[] byteObject = Utf8Encoding.GetBytes(stringWriter.ToString()); byte[] byteObject = Utf8Encoding.GetBytes(stringWriter.ToString());
context.Response.Body.WriteAsync(byteObject).GetAwaiter().GetResult(); context.ResponseWriteBin(byteObject);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -73,5 +73,4 @@ namespace VAR.WebFormsCore.Pages
private bool _isPostBack; private bool _isPostBack;
public bool IsPostBack => _isPostBack; public bool IsPostBack => _isPostBack;
}
} }

View File

@@ -3,10 +3,10 @@ using System.Reflection;
using VAR.WebFormsCore.Code; using VAR.WebFormsCore.Code;
using VAR.WebFormsCore.Controls; using VAR.WebFormsCore.Controls;
namespace VAR.WebFormsCore.Pages namespace VAR.WebFormsCore.Pages;
public class PageCommon : Page
{ {
public class PageCommon : Page
{
#region Declarations #region Declarations
private readonly HtmlHead _head = new(); private readonly HtmlHead _head = new();
@@ -24,7 +24,7 @@ namespace VAR.WebFormsCore.Pages
public new ControlCollection Controls => _pnlContainer.Controls; public new ControlCollection Controls => _pnlContainer.Controls;
public bool MustBeAuthenticated { get; init; } = true; public bool MustBeAuthenticated { get; set; } = true;
#endregion Properties #endregion Properties
@@ -39,7 +39,7 @@ namespace VAR.WebFormsCore.Pages
private void PageCommon_PreInit(object? sender, EventArgs e) private void PageCommon_PreInit(object? sender, EventArgs e)
{ {
Context?.Response.PrepareUncacheableResponse(); Context?.PrepareUncacheableResponse();
if (Context != null) if (Context != null)
{ {
@@ -48,7 +48,7 @@ namespace VAR.WebFormsCore.Pages
if (MustBeAuthenticated && _isAuthenticated == false) if (MustBeAuthenticated && _isAuthenticated == false)
{ {
Context?.Response.Redirect(GlobalConfig.Get().LoginHandler); Context?.ResponseRedirect(GlobalConfig.Get().LoginHandler);
} }
} }
@@ -72,7 +72,7 @@ namespace VAR.WebFormsCore.Pages
{ {
GlobalConfig.Get().UserDeauthenticate(Context); GlobalConfig.Get().UserDeauthenticate(Context);
} }
if (MustBeAuthenticated) { Context?.Response.Redirect(GlobalConfig.Get().LoginHandler); } if (MustBeAuthenticated) { Context?.ResponseRedirect(GlobalConfig.Get().LoginHandler); }
} }
#endregion UI Events #endregion UI Events
@@ -145,5 +145,4 @@ namespace VAR.WebFormsCore.Pages
} }
#endregion Private methods #endregion Private methods
}
} }

View File

@@ -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"
}
}
}

View File

@@ -1,9 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<LangVersion>10</LangVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>