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:
134
VAR.WebFormsCore.AspNetCore/Code/AspnetCoreWebContext.cs
Normal file
134
VAR.WebFormsCore.AspNetCore/Code/AspnetCoreWebContext.cs
Normal 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");
|
||||
}
|
||||
|
||||
}
|
||||
18
VAR.WebFormsCore.AspNetCore/Code/ExtensionMethods.cs
Normal file
18
VAR.WebFormsCore.AspNetCore/Code/ExtensionMethods.cs
Normal 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
|
||||
}
|
||||
}
|
||||
61
VAR.WebFormsCore.AspNetCore/Code/GlobalRouterMiddleware.cs
Normal file
61
VAR.WebFormsCore.AspNetCore/Code/GlobalRouterMiddleware.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
19
VAR.WebFormsCore.AspNetCore/Program.cs
Normal file
19
VAR.WebFormsCore.AspNetCore/Program.cs
Normal 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>();
|
||||
});
|
||||
}
|
||||
24
VAR.WebFormsCore.AspNetCore/Startup.cs
Normal file
24
VAR.WebFormsCore.AspNetCore/Startup.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user