Refactoring
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.HttpOverrides;
|
||||
|
||||
namespace Microsoft.AspNetCore.Builder
|
||||
{
|
||||
/// <summary>
|
||||
/// Extensions for the <see cref="IApplicationBuilder"/>.
|
||||
/// </summary>
|
||||
public static class ApplicationBuilderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds settings to run behind a reverse proxy (e.g. NginX).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A base path (e.g. running in a sub-directory /app) for the application is defined via<br/>
|
||||
/// - <c>ASPNETCORE_APPL_PATH</c> environment variable (preferred)<br/>
|
||||
/// - <c>AspNetCore_Appl_Path</c> in the settings file<br/>
|
||||
/// <br/>
|
||||
/// Additionally you can specify the proxy server by using <paramref name="address"/> or a <paramref name="network"/> when there are multiple proxy servers.
|
||||
/// <br/>
|
||||
/// When no <paramref name="address"/> oder <paramref name="network"/> is set, the default IPv4 private subnets are configured:<br/>
|
||||
/// - <c>10.0.0.0/8</c><br/>
|
||||
/// - <c>172.16.0.0/12</c><br/>
|
||||
/// - <c>192.168.0.0/16</c>
|
||||
/// </remarks>
|
||||
/// <param name="app">The application builder.</param>
|
||||
/// <param name="network">The <see cref="IPNetwork"/> where proxy requests are received from (optional).</param>
|
||||
/// <param name="address">The <see cref="IPAddress"/> where proxy requests are received from (optional).</param>
|
||||
public static void UseProxyHosting(this IApplicationBuilder app, IPNetwork network = null, IPAddress address = null)
|
||||
{
|
||||
string path = Environment.GetEnvironmentVariable("ASPNETCORE_APPL_PATH");
|
||||
if (!string.IsNullOrWhiteSpace(path))
|
||||
app.UsePathBase(new PathString(path));
|
||||
|
||||
var options = new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.All };
|
||||
options.KnownProxies.Clear();
|
||||
options.KnownNetworks.Clear();
|
||||
|
||||
if (network == null && address == null)
|
||||
{
|
||||
options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("10.0.0.0"), 8));
|
||||
options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("172.16.0.0"), 12));
|
||||
options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("192.168.0.0"), 16));
|
||||
}
|
||||
|
||||
if (network != null)
|
||||
options.KnownNetworks.Add(network);
|
||||
|
||||
if (address != null)
|
||||
options.KnownProxies.Add(address);
|
||||
|
||||
app.UseForwardedHeaders(options);
|
||||
}
|
||||
}
|
||||
}
|
||||
80
AMWD.Common.AspNetCore/Extensions/HtmlExtensions.cs
Normal file
80
AMWD.Common.AspNetCore/Extensions/HtmlExtensions.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Mvc.Razor;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
|
||||
namespace AMWD.Common.AspNetCore.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Extensions for the HTML (e.g. <see cref="IHtmlHelper"/>).
|
||||
/// </summary>
|
||||
public static class HtmlExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// The prefix used to identify JavaScript parts.
|
||||
/// </summary>
|
||||
public static string JSPrefix { get; set; } = "_JS_";
|
||||
|
||||
/// <summary>
|
||||
/// The prefix used to identify CascadingStyleSheet parts.
|
||||
/// </summary>
|
||||
public static string CSSPrefix { get; set; } = "_CSS_";
|
||||
|
||||
/// <summary>
|
||||
/// Add a js snippet.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The dynamic type of the <see cref="IHtmlHelper"/>.</typeparam>
|
||||
/// <param name="htmlHelper">The <see cref="IHtmlHelper"/> instance.</param>
|
||||
/// <param name="template">The template to use to add the snippet.</param>
|
||||
/// <returns></returns>
|
||||
public static T AddJS<T>(this IHtmlHelper<T> htmlHelper, Func<object, HelperResult> template)
|
||||
{
|
||||
htmlHelper.ViewContext.HttpContext.Items[$"{JSPrefix}{Guid.NewGuid()}"] = template;
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders the js snippets into the view.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The dynamic type of the <see cref="IHtmlHelper"/>.</typeparam>
|
||||
/// <param name="htmlHelper">The <see cref="IHtmlHelper"/> instance.</param>
|
||||
/// <returns></returns>
|
||||
public static T RenderJS<T>(this IHtmlHelper<T> htmlHelper)
|
||||
{
|
||||
foreach (object key in htmlHelper.ViewContext.HttpContext.Items.Keys)
|
||||
{
|
||||
if (key.ToString().StartsWith(JSPrefix) && htmlHelper.ViewContext.HttpContext.Items[key] is Func<object, HelperResult> template)
|
||||
htmlHelper.ViewContext.Writer.WriteLine(template(null));
|
||||
}
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a css snippet.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The dynamic type of the <see cref="IHtmlHelper"/>.</typeparam>
|
||||
/// <param name="htmlHelper">The <see cref="IHtmlHelper"/> instance.</param>
|
||||
/// <param name="template">The template to use to add the snippet.</param>
|
||||
/// <returns></returns>
|
||||
public static T AddCSS<T>(this IHtmlHelper<T> htmlHelper, Func<object, HelperResult> template)
|
||||
{
|
||||
htmlHelper.ViewContext.HttpContext.Items[$"{CSSPrefix}{Guid.NewGuid()}"] = template;
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders the css snippets into the view.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The dynamic type of the <see cref="IHtmlHelper"/>.</typeparam>
|
||||
/// <param name="htmlHelper">The <see cref="IHtmlHelper"/> instance.</param>
|
||||
/// <returns></returns>
|
||||
public static T RenderCSS<T>(this IHtmlHelper<T> htmlHelper)
|
||||
{
|
||||
foreach (object key in htmlHelper.ViewContext.HttpContext.Items.Keys)
|
||||
{
|
||||
if (key.ToString().StartsWith(CSSPrefix) && htmlHelper.ViewContext.HttpContext.Items[key] is Func<object, HelperResult> template)
|
||||
htmlHelper.ViewContext.Writer.WriteLine(template(null));
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
}
|
||||
63
AMWD.Common.AspNetCore/Extensions/HttpContextExtensions.cs
Normal file
63
AMWD.Common.AspNetCore/Extensions/HttpContextExtensions.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using System.Net;
|
||||
using Microsoft.AspNetCore.Antiforgery;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNetCore.Http
|
||||
{
|
||||
/// <summary>
|
||||
/// Extensions for the <see cref="HttpContext"/>.
|
||||
/// </summary>
|
||||
public static class HttpContextExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieves the antiforgery token.
|
||||
/// </summary>
|
||||
/// <param name="httpContext">The web context.</param>
|
||||
/// <returns>Name and value of the token.</returns>
|
||||
public static (string Name, string Value) GetAntiforgeryToken(this HttpContext httpContext)
|
||||
{
|
||||
var af = httpContext.RequestServices.GetService<IAntiforgery>();
|
||||
var set = af?.GetAndStoreTokens(httpContext);
|
||||
|
||||
return (Name: set?.FormFieldName, Value: set?.RequestToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the remote ip address.
|
||||
/// </summary>
|
||||
/// <param name="httpContext">The web context.</param>
|
||||
/// <param name="headerName">The name of the header to resolve the <see cref="IPAddress"/> when behind a proxy (Default: X-Forwarded-For).</param>
|
||||
/// <returns>The ip address of the client.</returns>
|
||||
public static IPAddress GetRemoteIpAddress(this HttpContext httpContext, string headerName = "X-Forwarded-For")
|
||||
{
|
||||
var remote = httpContext.Connection.RemoteIpAddress;
|
||||
|
||||
string forwardedHeader = httpContext.Request.Headers[headerName].ToString();
|
||||
if (!string.IsNullOrWhiteSpace(forwardedHeader) && IPAddress.TryParse(forwardedHeader, out var forwarded))
|
||||
return forwarded;
|
||||
|
||||
return remote;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to retrieve the return url.
|
||||
/// </summary>
|
||||
/// <param name="httpContext"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetReturnUrl(this HttpContext httpContext)
|
||||
{
|
||||
string url = httpContext.Items["OriginalRequest"]?.ToString();
|
||||
if (string.IsNullOrWhiteSpace(url))
|
||||
url = httpContext.Request.Query["ReturnUrl"].ToString();
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears a session when available.
|
||||
/// </summary>
|
||||
/// <param name="httpContext">The current <see cref="HttpContext"/>.</param>
|
||||
public static void ClearSession(this HttpContext httpContext)
|
||||
=> httpContext?.Session?.Clear();
|
||||
}
|
||||
}
|
||||
98
AMWD.Common.AspNetCore/Extensions/LoggerExtensions.cs
Normal file
98
AMWD.Common.AspNetCore/Extensions/LoggerExtensions.cs
Normal file
@@ -0,0 +1,98 @@
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
|
||||
|
||||
namespace Microsoft.Extensions.Logging
|
||||
{
|
||||
/// <summary>
|
||||
/// Extensions for the <see cref="ILogger"/>.
|
||||
/// </summary>
|
||||
internal static class LoggerExtensions
|
||||
{
|
||||
// Found here:
|
||||
// https://github.com/dotnet/aspnetcore/blob/a4c45262fb8549bdb4f5e4f76b16f98a795211ae/src/Mvc/Mvc.Core/src/MvcCoreLoggerExtensions.cs
|
||||
|
||||
public static void AttemptingToBindModel(this ILogger logger, ModelBindingContext bindingContext)
|
||||
{
|
||||
if (!logger.IsEnabled(LogLevel.Debug))
|
||||
return;
|
||||
|
||||
var modelMetadata = bindingContext.ModelMetadata;
|
||||
switch (modelMetadata.MetadataKind)
|
||||
{
|
||||
case ModelMetadataKind.Parameter:
|
||||
logger.Log(LogLevel.Debug,
|
||||
new EventId(44, "AttemptingToBindParameterModel"),
|
||||
$"Attempting to bind parameter '{modelMetadata.ParameterName}' of type '{modelMetadata.ModelType}' using the name '{bindingContext.ModelName}' in request data ...");
|
||||
break;
|
||||
|
||||
case ModelMetadataKind.Property:
|
||||
logger.Log(LogLevel.Debug,
|
||||
new EventId(13, "AttemptingToBindPropertyModel"),
|
||||
$"Attempting to bind property '{modelMetadata.ContainerType}.{modelMetadata.PropertyName}' of type '{modelMetadata.ModelType}' using the name '{bindingContext.ModelName}' in request data ...");
|
||||
break;
|
||||
|
||||
case ModelMetadataKind.Type:
|
||||
logger.Log(LogLevel.Debug,
|
||||
new EventId(24, "AttemptingToBindModel"),
|
||||
$"Attempting to bind model of type '{bindingContext.ModelType}' using the name '{bindingContext.ModelName}' in request data ...");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void FoundNoValueInRequest(this ILogger logger, ModelBindingContext bindingContext)
|
||||
{
|
||||
if (!logger.IsEnabled(LogLevel.Debug))
|
||||
return;
|
||||
|
||||
var modelMetadata = bindingContext.ModelMetadata;
|
||||
switch (modelMetadata.MetadataKind)
|
||||
{
|
||||
case ModelMetadataKind.Parameter:
|
||||
logger.Log(LogLevel.Debug,
|
||||
new EventId(16, "FoundNoValueForParameterInRequest"),
|
||||
$"Could not find a value in the request with name '{bindingContext.ModelName}' for binding parameter '{modelMetadata.ParameterName}' of typ//(('{bindingContext.ModelType}'.");
|
||||
break;
|
||||
|
||||
case ModelMetadataKind.Property:
|
||||
logger.Log(LogLevel.Debug,
|
||||
new EventId(15, "FoundNoValueForPropertyInRequest"),
|
||||
$"Could not find a value in the request with name '{bindingContext.ModelName}' for binding property '{modelMetadata.ContainerType}.{modelMetadata.PropertyName}' of type '{bindingContext.ModelType}'.");
|
||||
break;
|
||||
|
||||
case ModelMetadataKind.Type:
|
||||
logger.Log(LogLevel.Debug,
|
||||
new EventId(46, "FoundNoValueInRequest"),
|
||||
$"Could not find a value in the request with name '{bindingContext.ModelName}' of type '{bindingContext.ModelType}'.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void DoneAttemptingToBindModel(this ILogger logger, ModelBindingContext bindingContext)
|
||||
{
|
||||
if (!logger.IsEnabled(LogLevel.Debug))
|
||||
return;
|
||||
|
||||
var modelMetadata = bindingContext.ModelMetadata;
|
||||
switch (modelMetadata.MetadataKind)
|
||||
{
|
||||
case ModelMetadataKind.Parameter:
|
||||
logger.Log(LogLevel.Debug,
|
||||
new EventId(45, "DoneAttemptingToBindParameterModel"),
|
||||
$"Done attempting to bind parameter '{modelMetadata.ParameterName}' of type '{modelMetadata.ModelType}'.");
|
||||
break;
|
||||
|
||||
case ModelMetadataKind.Property:
|
||||
logger.Log(LogLevel.Debug,
|
||||
new EventId(14, "DoneAttemptingToBindPropertyModel"),
|
||||
$"Done attempting to bind property '{modelMetadata.ContainerType}.{modelMetadata.PropertyName}' of type '{modelMetadata.ModelType}'.");
|
||||
break;
|
||||
|
||||
case ModelMetadataKind.Type:
|
||||
logger.Log(LogLevel.Debug,
|
||||
new EventId(25, "DoneAttemptingToBindModel"),
|
||||
$"Done attempting to bind model of type '{bindingContext.ModelType}' using the name '{bindingContext.ModelName}'.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides extension methods for the ASP.NET Core application.
|
||||
/// </summary>
|
||||
public static class ModelStateDictionaryExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds the specified <paramref name="errorMessage"/> to the <see cref="ModelStateEntry.Errors"/>
|
||||
/// instance that is associated with the key specified as a <see cref="MemberExpression"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TModel">The type of the model.</typeparam>
|
||||
/// <typeparam name="TProperty">The type of the property.</typeparam>
|
||||
/// <param name="modelState">The <see cref="ModelStateDictionary"/> instance.</param>
|
||||
/// <param name="model">The model. Only used to infer the model type.</param>
|
||||
/// <param name="keyExpression">The <see cref="MemberExpression"/> that specifies the property.</param>
|
||||
/// <param name="errorMessage">The error message to add.</param>
|
||||
/// <exception cref="InvalidOperationException">No member expression provided.</exception>
|
||||
#pragma warning disable IDE0060 // remove unused parameters
|
||||
public static void AddModelError<TModel, TProperty>(this ModelStateDictionary modelState, TModel model, Expression<Func<TModel, TProperty>> keyExpression, string errorMessage)
|
||||
#pragma warning restore IDE0060 // remove unused parameters
|
||||
{
|
||||
if (modelState is null)
|
||||
throw new ArgumentNullException(nameof(modelState));
|
||||
|
||||
string key = "";
|
||||
var expr = keyExpression.Body as MemberExpression;
|
||||
while (expr != null)
|
||||
{
|
||||
key = expr.Member.Name + (key != "" ? "." + key : "");
|
||||
expr = expr.Expression as MemberExpression;
|
||||
}
|
||||
if (key == "")
|
||||
throw new InvalidOperationException("No member expression provided.");
|
||||
|
||||
modelState.AddModelError(key, errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace Microsoft.Extensions.DependencyInjection
|
||||
{
|
||||
/// <summary>
|
||||
/// Extensions for the <see cref="IServiceCollection"/>.
|
||||
/// </summary>
|
||||
public static class ServiceCollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds a hosted service that is instanciated only once.
|
||||
/// </summary>
|
||||
/// <typeparam name="TService">The type of the service to add.</typeparam>
|
||||
/// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param>
|
||||
/// <returns>A reference to this instance after the operation has completed.</returns>
|
||||
public static IServiceCollection AddSingletonHostedService<TService>(this IServiceCollection services)
|
||||
where TService : class, IHostedService
|
||||
{
|
||||
services.AddSingleton<TService>();
|
||||
services.AddSingleton<IHostedService, BackgroundServiceStarter<TService>>();
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
||||
56
AMWD.Common.AspNetCore/Extensions/SessionExtensions.cs
Normal file
56
AMWD.Common.AspNetCore/Extensions/SessionExtensions.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.AspNetCore.Http
|
||||
{
|
||||
/// <summary>
|
||||
/// Extensions for the <see cref="ISession"/> object.
|
||||
/// </summary>
|
||||
public static class SessionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Sets a strong typed value.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The value type.</typeparam>
|
||||
/// <param name="session">The current session.</param>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
public static void SetValue<T>(this ISession session, string key, T value)
|
||||
=> session.SetString(key, JsonConvert.SerializeObject(value));
|
||||
|
||||
/// <summary>
|
||||
/// Gets a strong typed value.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The value type.</typeparam>
|
||||
/// <param name="session">The current session.</param>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <returns>The value.</returns>
|
||||
public static T GetValue<T>(this ISession session, string key)
|
||||
=> session.HasKey(key) ? JsonConvert.DeserializeObject<T>(session.GetString(key)) : default;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a strong typed value or the fallback value.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The value type.</typeparam>
|
||||
/// <param name="session">The current session.</param>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <param name="fallback">A fallback value when the key is not present.</param>
|
||||
/// <returns>The value.</returns>
|
||||
public static T GetValue<T>(this ISession session, string key, T fallback)
|
||||
{
|
||||
if (session.HasKey(key))
|
||||
return session.GetValue<T>(key);
|
||||
|
||||
return fallback;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the session has the key available.
|
||||
/// </summary>
|
||||
/// <param name="session">The current session.</param>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <returns><c>true</c> when the key was found, otherwise <c>false</c>.</returns>
|
||||
public static bool HasKey(this ISession session, string key)
|
||||
=> session.Keys.Contains(key);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user