Skip to content

Instantly share code, notes, and snippets.

@luebster
Last active March 21, 2019 14:20
Show Gist options
  • Save luebster/7c68cbf2c2789a92faf92b8c8ebef330 to your computer and use it in GitHub Desktop.
Save luebster/7c68cbf2c2789a92faf92b8c8ebef330 to your computer and use it in GitHub Desktop.
Extend All The Things: A set of helpers for ASP.NET Core
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;
}
}
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;
}
}
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