Last active
March 21, 2019 14:20
-
-
Save luebster/7c68cbf2c2789a92faf92b8c8ebef330 to your computer and use it in GitHub Desktop.
Extend All The Things: A set of helpers for ASP.NET Core
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Linq; | |
using System.Security.Principal; | |
public static class AuthorizationExtensions | |
{ | |
public static bool IsInAllRoles(this IPrincipal principal, string[] roles) | |
{ | |
return roles.All(r => principal.IsInRole(r)); | |
} | |
public static bool IsInAllRoles(this IPrincipal principal, string roles) | |
{ | |
string[] rolesEnumerable = roles.Split(','); | |
return principal.IsInAllRoles(rolesEnumerable); | |
} | |
public static bool IsInAnyRoles(this IPrincipal principal, string[] roles) | |
{ | |
return roles.Any(r => principal.IsInRole(r)); | |
} | |
public static bool IsInAnyRoles(this IPrincipal principal, string roles) | |
{ | |
string[] rolesEnumerable = roles.Split(','); | |
return principal.IsInAnyRoles(rolesEnumerable); | |
} | |
public static string GetUserName(this IPrincipal principal) | |
{ | |
return principal.Identity.Name; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.Text; | |
using System.Text.RegularExpressions; | |
public static class StringExtensions | |
{ | |
/// <summary> | |
/// Truncates a string containing HTML to a number of text characters, keeping whole words. | |
/// The result contains HTML and any tags left open are closed. | |
/// </summary> | |
/// <param name="s"></param> | |
/// <returns></returns> | |
public static string TruncateHtml(this string html, int maxCharacters, string trailingText) | |
{ | |
if (string.IsNullOrEmpty(html)) | |
return html; | |
// find the spot to truncate | |
// count the text characters and ignore tags | |
int textCount = 0; | |
int charCount = 0; | |
bool ignore = false; | |
foreach (char c in html) | |
{ | |
charCount++; | |
if (c == '<') | |
ignore = true; | |
else if (!ignore) | |
textCount++; | |
if (c == '>') | |
ignore = false; | |
// stop once we hit the limit | |
if (textCount >= maxCharacters) | |
break; | |
} | |
// Truncate the html and keep whole words only | |
var trunc = new StringBuilder(html.TruncateWords(charCount)); | |
// keep track of open tags and close any tags left open | |
var tags = new Stack<string>(); | |
var matches = Regex.Matches(trunc.ToString(), | |
@"<((?<tag>[^\s/>]+)|/(?<closeTag>[^\s>]+)).*?(?<selfClose>/)?\s*>", | |
RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Multiline); | |
foreach (Match match in matches) | |
{ | |
if (match.Success) | |
{ | |
string tag = match.Groups["tag"].Value; | |
string closeTag = match.Groups["closeTag"].Value; | |
// push to stack if open tag and ignore it if it is self-closing, i.e. <br /> | |
if (!string.IsNullOrEmpty(tag) && string.IsNullOrEmpty(match.Groups["selfClose"].Value)) | |
tags.Push(tag); | |
// pop from stack if close tag | |
else if (!string.IsNullOrEmpty(closeTag)) | |
{ | |
// pop the tag to close it.. find the matching opening tag | |
// ignore any unclosed tags | |
while (tags.Pop() != closeTag && tags.Count > 0) | |
{ } | |
} | |
} | |
} | |
if (html.Length > charCount) | |
// add the trailing text | |
trunc.Append(trailingText); | |
// pop the rest off the stack to close remainder of tags | |
while (tags.Count > 0) | |
{ | |
trunc.Append("</"); | |
trunc.Append(tags.Pop()); | |
trunc.Append('>'); | |
} | |
return trunc.ToString(); | |
} | |
/// <summary> | |
/// Truncates a string containing HTML to a number of text characters, keeping whole words. | |
/// The result contains HTML and any tags left open are closed. | |
/// </summary> | |
/// <param name="s"></param> | |
/// <returns></returns> | |
public static string TruncateHtml(this string html, int maxCharacters) | |
{ | |
return html.TruncateHtml(maxCharacters, null); | |
} | |
public static string StripHtml(this string html) | |
{ | |
if (string.IsNullOrEmpty(html)) | |
return html; | |
return Regex.Replace(html, @"<(.|\n)*?>", string.Empty); | |
} | |
/// <summary> | |
/// Truncates text to a number of characters | |
/// </summary> | |
/// <param name="text"></param> | |
/// <param name="maxCharacters"></param> | |
/// <param name="trailingText"></param> | |
/// <returns></returns> | |
public static string Truncate(this string text, int maxCharacters) | |
{ | |
return text.Truncate(maxCharacters, null); | |
} | |
/// <summary> | |
/// Truncates text to a number of characters and adds trailing text, i.e. elipses, to the end | |
/// </summary> | |
/// <param name="text"></param> | |
/// <param name="maxCharacters"></param> | |
/// <param name="trailingText"></param> | |
/// <returns></returns> | |
public static string Truncate(this string text, int maxCharacters, string trailingText) | |
{ | |
if (string.IsNullOrEmpty(text) || maxCharacters <= 0 || text.Length <= maxCharacters) | |
return text; | |
else | |
return text.Substring(0, maxCharacters) + trailingText; | |
} | |
/// <summary> | |
/// Truncates text and discars any partial words left at the end | |
/// </summary> | |
/// <param name="text"></param> | |
/// <param name="maxCharacters"></param> | |
/// <param name="trailingText"></param> | |
/// <returns></returns> | |
public static string TruncateWords(this string text, int maxCharacters) | |
{ | |
return text.TruncateWords(maxCharacters, null); | |
} | |
/// <summary> | |
/// Truncates text and discars any partial words left at the end | |
/// </summary> | |
/// <param name="text"></param> | |
/// <param name="maxCharacters"></param> | |
/// <param name="trailingText"></param> | |
/// <returns></returns> | |
public static string TruncateWords(this string text, int maxCharacters, string trailingText) | |
{ | |
if (string.IsNullOrEmpty(text) || maxCharacters <= 0 || text.Length <= maxCharacters) | |
return text; | |
// trunctate the text, then remove the partial word at the end | |
return Regex.Replace(text.Truncate(maxCharacters), | |
@"\s+[^\s]+$", string.Empty, RegexOptions.IgnoreCase | RegexOptions.Compiled) + trailingText; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.ComponentModel.DataAnnotations; | |
using System.Globalization; | |
namespace ExtendAllTheThings | |
{ | |
/// <summary> | |
/// Make a property required if another property has a specified value | |
/// </summary> | |
public class RequiredIfAttribute : ValidationAttribute | |
{ | |
/// <summary> | |
/// The name of the other property to check the value of | |
/// </summary> | |
public string _otherProperty { get; set; } | |
/// <summary> | |
/// Value of the other property that causes this property to be required | |
/// </summary> | |
public object _otherPropertyValue { get; set; } | |
public RequiredIfAttribute(string otherProperty, object otherProperyValue) | |
{ | |
_otherProperty = otherProperty; | |
_otherPropertyValue = otherProperyValue; | |
} | |
protected override ValidationResult IsValid(object value, ValidationContext validationContext) | |
{ | |
// Get the other property and check its value | |
var otherProperty = validationContext.ObjectType.GetProperty(_otherProperty); | |
if (otherProperty == null) | |
{ | |
return new ValidationResult(string.Format(CultureInfo.CurrentCulture, "Could not find a property named {0}.", _otherProperty)); | |
} | |
object otherValue = otherProperty.GetValue(validationContext.ObjectInstance); | |
if (Equals(otherValue, _otherPropertyValue)) | |
{ | |
if (value == null) | |
{ | |
return new ValidationResult(FormatErrorMessage(validationContext.DisplayName)); | |
} | |
// additional check for strings so they're not empty | |
if (value is string val && val.Trim().Length == 0) | |
{ | |
return new ValidationResult(FormatErrorMessage(validationContext.DisplayName)); | |
} | |
} | |
return ValidationResult.Success; | |
} | |
private string GetErrorMessage() | |
{ | |
return $"This field is required if {_otherProperty} is {_otherPropertyValue}."; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment