using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.IO; using System.Linq; using System.Reflection; using System.Text.Encodings.Web; using System.Threading.Tasks; using gehGassi.Domain.Common; using gehGassi.Web.Controllers; using gehGassi.Web.Models; using gehGassi.Web.Services; using Microsoft.AspNetCore.Html; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.Extensions.Localization; using Microsoft.Extensions.Options; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; namespace gehGassi.Web.Helper { /// /// Hilfsklasse mit Erweiterungen /// public static class Extensions { /// /// Erweiterung für PartialViewResults. /// Erstellt aus dem Partialview einen String /// /// Gewünschter PartialView /// Instanz des ActionContext /// View-Ergebnis als String public static async Task ToStringAsync(this PartialViewResult partialView, ActionContext actionContext) { using (var writer = new StringWriter()) { var serviceProvider = (IServiceProvider)actionContext.HttpContext.RequestServices; var executor = (PartialViewResultExecutor)serviceProvider.GetService(typeof(PartialViewResultExecutor)); var view = executor.FindView(actionContext, partialView).View; var viewContext = new ViewContext(actionContext, view, partialView.ViewData, partialView.TempData, writer, new HtmlHelperOptions()); await view.RenderAsync(viewContext); return writer.ToString(); } } /// /// Erweiterung für ViewResults. /// Erstellt aus dem View einen String /// /// Gewünschter PartialView /// Instanz des ActionContext /// View-Ergebnis als String public static async Task ToStringAsync(this ViewResult viewResult, ActionContext actionContext) { using (var writer = new StringWriter()) { var serviceProvider = (IServiceProvider)actionContext.HttpContext.RequestServices; var executor = (ViewResultExecutor)serviceProvider.GetService(typeof(ViewResultExecutor)); var view = executor.FindView(actionContext, viewResult).View; var viewContext = new ViewContext(actionContext, view, viewResult.ViewData, viewResult.TempData, writer, new HtmlHelperOptions()); await view.RenderAsync(viewContext); return writer.ToString(); } } /// /// Prüft ob eine URL lokal ist. Wenn nicht, wird eine lokale zurückgegeben /// /// Instanz eines IUrlHelper /// zu prüfende URL /// URL public static string GetLocalUrl(this IUrlHelper urlHelper, string localUrl) { if (!urlHelper.IsLocalUrl(localUrl)) { return urlHelper.Page("/Index"); } return localUrl; } /// /// Gibt zurück ob ein String mit "http" startet. /// Wird bei Fotos verwendet um zwischen lokalen und online Fotos zu unterscheiden /// /// Text der geprüft werden soll /// true wenn mit http startet, false sonst public static bool StartsWithHttp(this string text) { if (!string.IsNullOrWhiteSpace(text)) { return text.ToLower().StartsWith("http"); } return false; } /// /// Erstellt einen Link für das Zurücksetzen des Passwortes /// /// Instanz eines IUrlHelper /// Benutzer-ID /// Bestätigungscode /// HTTP-Scheme (http/https) /// Link public static string ResetPasswordCallbackLink(this IUrlHelper urlHelper, string userId, string code, string scheme) { return urlHelper.Action( action: nameof(AccountController.ResetPassword), controller: "Account", values: new { userId, code }, protocol: scheme); } /// /// Erstellt einen Link für das Zurücksetzen des Passwortes für die APP /// /// Instanz eines IUrlHelper /// Benutzer-ID /// Bestätigungscode /// HTTP-Scheme (http/https) /// Link public static string ResetPasswordCallbackLinkApp(this IUrlHelper urlHelper, string userId, string code, string scheme) { return urlHelper.Action( action: nameof(AccountController.ResetPasswordApp), controller: "Account", values: new { userId, code }, protocol: scheme); } /// /// Erstellt einen Link für das Löschen eines Accounts /// /// Instanz eines IUrlHelper /// Benutzer-ID /// Bestätigungscode /// HTTP-Scheme (http/https) /// Link public static string DeleteAccountCallbackLinkApp(this IUrlHelper urlHelper, string userId, string code, string scheme) { return urlHelper.Action( action: nameof(AppController.DoDeleteAccount), controller: "App", values: new { userId, code }, protocol: scheme); } /// /// Sendet eine Email an gehgassi, dass ein Benutzer gelöscht werden soll /// /// Instanz eines IEmailSender /// Email Adresse des Benutzers = Benutzername /// Vorname des Benutzers /// Nachname des Benutzers /// Instanz eines IStringLocalizer /// Instanz eines IOptions EmailSenderOptions /// Task public static Task SendDeleteAccountEmailAsync(this IEmailSender emailSender, string userAccountEmail, string userFirstName, string userLastName, IStringLocalizer localizer, IOptions emailSenderOptions) { string subject = localizer["DeleteAccountEmail_Subject"]; string message = localizer["DeleteAccountEmail_Message"]; message = string.Format(message, userFirstName, userLastName, userAccountEmail); var targetEmail = "support@gehgassi.com"; #if DEBUG targetEmail = "mihalits@creativebits.com"; #endif return emailSender.SendEmailAsync(targetEmail, subject, message); } /// /// Sendet eine Email für die Bestätigung der Email-Adresse /// /// Instanz eines IEmailSender /// Ziel-Adresse /// Link für die Bestätigung /// Instanz eines IStringLocalizer /// Instanz eines IOptions LicenseOptions /// Task public static Task SendEmailConfirmationAsync(this IEmailSender emailSender, string email, string link, IStringLocalizer localizer, IOptions licenseOptions) { string subject = localizer["ConfirmEmail_Subject"]; string message = localizer["ConfirmEmail_Message"]; subject = string.Format(subject, licenseOptions.Value.Software); message = string.Format(message, HtmlEncoder.Default.Encode(link), licenseOptions.Value.Software); return emailSender.SendEmailAsync(email, subject, message); } /// /// Sendet eine Email für die Bestätigung der Email-Adresse für die App /// /// Instanz eines IEmailSender /// Ziel-Adresse /// Link für die Bestätigung /// Instanz eines IStringLocalizer /// Instanz eines IOptions LicenseOptions /// Task public static Task SendEmailConfirmationAppAsync(this IEmailSender emailSender, string email, string link, IStringLocalizer localizer, IOptions licenseOptions) { string subject = localizer["ConfirmEmail_Subject_App"]; string message = localizer["ConfirmEmail_Message_App"]; subject = string.Format(subject, licenseOptions.Value.Software); message = string.Format(message, HtmlEncoder.Default.Encode(link), licenseOptions.Value.Software); return emailSender.SendEmailAsync(email, subject, message); } /// /// Sendet eine Email für die Bestätigung des Passwort Zurücksetzens /// /// Instanz eines IEmailSender /// Ziel-Adresse /// Link für die Bestätigung /// Instanz eines IStringLocalizer /// Instanz eines IOptions LicenseOptions /// Task public static Task SendPasswordResetAsync(this IEmailSender emailSender, string email, string link, IStringLocalizer localizer, IOptions licenseOptions) { string subject = localizer["ResetPassword_Subject"]; string message = localizer["ResetPassword_Message"]; subject = string.Format(subject, licenseOptions.Value.Software); message = string.Format(message, HtmlEncoder.Default.Encode(link), licenseOptions.Value.Software); return emailSender.SendEmailAsync(email, subject, message); } /// /// Sendet eine Email für die Bestätigung des Passwort Zurücksetzens für die APP /// /// Instanz eines IEmailSender /// Ziel-Adresse /// Link für die Bestätigung /// Instanz eines IStringLocalizer /// Instanz eines IOptions LicenseOptions /// Task public static Task SendPasswordResetAppAsync(this IEmailSender emailSender, string email, string link, IStringLocalizer localizer, IOptions licenseOptions) { string subject = localizer["ResetPassword_Subject_App"]; string message = localizer["ResetPassword_Message_App"]; subject = string.Format(subject, licenseOptions.Value.Software); message = string.Format(message, HtmlEncoder.Default.Encode(link), licenseOptions.Value.Software); return emailSender.SendEmailAsync(email, subject, message); } /// /// Sendet eine Email für die Bestätigung der Löschung des Accounts /// /// Instanz eines IEmailSender /// Ziel-Adresse /// Link für die Bestätigung /// Instanz eines IStringLocalizer /// Task public static Task SendDeleteAccountAsync(this IEmailSender emailSender, string email, string link, IStringLocalizer localizer) { string subject = localizer["DeleteAccount_Subject"]; string message = localizer["DeleteAccount_Message"]; message = string.Format(message, HtmlEncoder.Default.Encode(link)); return emailSender.SendEmailAsync(email, subject, message); } /// /// Serialisiert ein Objekt für die Speicherung in einer Session /// /// Typ des Objektes /// ISession /// Key /// Objekt public static void Set(this ISession session, string key, T value) { session.SetString(key, JsonConvert.SerializeObject(value)); } /// /// Deserialisiert ein Objekt aus einer Session /// /// Typ des Objektes /// ISession /// Key /// Deserialisiertes Objekt public static T Get(this ISession session, string key) { var value = session.GetString(key); return value == null ? default(T) : JsonConvert.DeserializeObject(value); } /// /// Serialisiert ein Objekt in JSON mit CamelCase Resolver. /// /// Objekt das Serialisiert werden soll /// JSON-string public static string ToCamelCaseJson(this object item) { var jsonOptions = new JsonSerializerSettings() { NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore, DateFormatHandling = Newtonsoft.Json.DateFormatHandling.IsoDateFormat, ReferenceLoopHandling = ReferenceLoopHandling.Ignore, ContractResolver = new CamelCasePropertyNamesContractResolver() }; jsonOptions.Converters.Add(new NetTopologySuite.IO.Converters.GeometryConverter()); return JsonConvert.SerializeObject(item, jsonOptions); } /// /// Erstellt aus einem Dateinamen einen eineutigen durch das Anhängen der Ticks der aktuellen Systemzeit /// /// Dateiname /// Eindeutiger Dateiname public static string ToUniqueFilename(this string filename) { if (!string.IsNullOrWhiteSpace(filename)) { if (filename.Contains(".")) { var lastIndex = filename.LastIndexOf('.'); if (lastIndex + 1 < filename.Length) { var firstPart = filename.Substring(0, lastIndex); var secondPart = filename.Substring(lastIndex + 1); return firstPart + "_" + DateTime.UtcNow.Ticks + "." + secondPart; } } } return filename; } public static IEnumerable GetColumn(this IList items, string columnName) { var values = items.Select(x => x.GetType().GetProperty(columnName)?.GetValue(x)); return values; } /// /// Ist ein HTTP-Request eine Ajax Request? /// /// HttpRequest /// true wenn ja, false sonst public static bool IsAjaxRequest(this HttpRequest request) { if (request == null) throw new ArgumentNullException(nameof(request)); if (request.Headers != null) return !string.IsNullOrEmpty(request.Headers["X-Requested-With"]) && string.Equals( request.Headers["X-Requested-With"], "XmlHttpRequest", StringComparison.OrdinalIgnoreCase); return false; } /// /// Gibt die Subdomain des aktuellen Requests zurück /// /// HttpRequest /// Subdomain wenn gefunden, string.empty sonst public static string GetSubdomain(this HttpRequest request) { if (request == null) return string.Empty; if (!string.IsNullOrWhiteSpace(request.Host.Host)) { var parts = request.Host.Host.Split("."); if (parts.Length > 1) return parts[0]; } return string.Empty; } /// /// Gibt die aktuelle URL mit der subdomain eingesetzt zurück. /// Das Betrifft scheme und host und port /// /// HttpRequest /// Subdomain die gesetzt werden soll /// neue url mit subdomain public static string GetWithSubdomain(this HttpRequest request, string subdomain) { if (request == null || string.IsNullOrWhiteSpace(subdomain)) return string.Empty; if (!string.IsNullOrWhiteSpace(request.Host.Host)) { var host = request.Host.Host; var parts = request.Host.Host.Split("."); if (parts.Length == 3) { host = host.Replace(parts[0], subdomain); } if (parts.Length <= 2) { host = $"{subdomain}.{host}"; } if (request.Host.Port.HasValue) { host += $":{request.Host.Port}"; } return $"{request.Scheme}://{host}"; } return string.Empty; } /// /// Gibt die aktuelle URL mit der subdomain eingesetzt zurück. /// Das Betrifft scheme und host und port /// /// HttpRequest /// neue url mit subdomain public static string GetBaseDomain(this HttpRequest request) { if (request == null) return string.Empty; if (!string.IsNullOrWhiteSpace(request.Host.Host)) { var host = request.Host.Host; var parts = request.Host.Host.Split("."); if (parts.Length == 3) { host = host.Replace(parts[0] + ".", ""); } else if (parts.Length <= 2) { host = $"{host}"; } return host; } return string.Empty; } /// /// Convert a standard string into a htmlstring for rendering in a view /// /// /// public static HtmlString ToHtmlString(this string value) { return new HtmlString(value); } /// /// Wenn eine Web-Adresse nicht mit https:// beginnt, wird diese mit https:// zurückgegeben /// /// /// public static string ToHttpsWebAddress(this string value) { if (!value.ToLower().StartsWith("https://")) return $"https://{value}"; else if (value.ToLower().StartsWith("http://")) return value.ToLower().Replace("http://", "https://"); else return value; } /// /// Anonymisieren eines vollen Namen. /// Optimalerweise in das Forma Vorname N. /// /// /// Anonymisierter Name public static string AnonymizeFullName(this string value) { if (!string.IsNullOrWhiteSpace(value)) { var name = value.Trim(' '); if (name.Contains(" ")) { var nameSplit = name.Split(' '); var result = string.Empty; for (int i = 0; i < nameSplit.Length; i++) { if (i > 0) result += " "; if (i < nameSplit.Length - 1) result += nameSplit[i]; else result += nameSplit[i].Substring(0, 1) + "."; } return result; } else { return name.Substring(0, 1) + "."; } } return "Anonymous"; } /// /// Erstellt aus einem Text der Environment.Newline beinhaltet eine Liste von

xxx

///
/// /// public static HtmlString ToParagraphs(this string value) { if (string.IsNullOrWhiteSpace(value)) return new HtmlString(value); else { var result = string.Empty; var lines = value.Split(Environment.NewLine); result = lines.Aggregate(result, (current, line) => current + $"

{line}

"); return new HtmlString(result); } } /// /// Gibt den Display-Name für einen Enum-Wert zurück /// /// enum-Wert /// Stringlocalizer der verwendet werden soll /// Displayname public static string GetDisplayName(this Enum enumValue, IStringLocalizer stringLocalizer) { var displayAttribute = enumValue.GetType().GetMember(enumValue.ToString()).First().GetCustomAttribute(); var name = displayAttribute.GetName(); var translation = stringLocalizer[name]; return translation; } /// /// Prüft ob eine Adresse gegenüber dem Viewmodel Änderungen hat /// /// Adresse /// Viewmodel der Adresse /// true wenn es Änderungen gab, false sonst public static bool HasChanges(this Address address, AddressVm addressVm) { if (address.AddressLine1 != addressVm.AddressLine1) return true; if (address.AddressLine2 != addressVm.AddressLine2) return true; if (address.Zip != addressVm.Zip) return true; if (address.City != addressVm.City) return true; if (address.State != addressVm.State) return true; if (address.CountryCode != addressVm.CountryCode) return true; return false; } /// /// Prüft ob eine Adresse gegenüber dem Viewmodel Änderungen hat /// /// Adresse /// Viewmodel der Adresse /// true wenn es Änderungen gab, false sonst public static bool HasChanges(this Address address, AddressRequiredVm addressVm) { if (address.AddressLine1 != addressVm.AddressLine1) return true; if (address.AddressLine2 != addressVm.AddressLine2) return true; if (address.Zip != addressVm.Zip) return true; if (address.City != addressVm.City) return true; if (address.State != addressVm.State) return true; if (address.CountryCode != addressVm.CountryCode) return true; return false; } } }