Skip to content

Instantly share code, notes, and snippets.

@jstemerdink
Created November 13, 2016 11:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jstemerdink/8c6717ddd70ac09c1a82254e717dda46 to your computer and use it in GitHub Desktop.
Save jstemerdink/8c6717ddd70ac09c1a82254e717dda46 to your computer and use it in GitHub Desktop.
A validation controller that uses the Moderation API from Microsoft Cognitive services to validate content
public class CommentViewModel
{
/// <summary>Gets the body content of the comment.</summary>
[Remote("IsSafeTextContent", "ModeratorValidation")]
public virtual string Body { get; set; }
}
using System;
using System.Configuration;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Mvc;
using System.Web.UI;
using EPiServer.Framework.Localization;
using EPiServer.Globalization;
using Microsoft.CognitiveServices.ContentModerator;
using Microsoft.CognitiveServices.ContentModerator.Contract.Text;
/// <summary>
/// Class ModeratorValidationController.
/// </summary>
/// <seealso cref="System.Web.Mvc.Controller" />
/// <author>Jeroen Stemerdink</author>
[OutputCache(Location = OutputCacheLocation.None, NoStore = true)]
public class ModeratorValidationController : Controller
{
/// <summary>
/// The subscription key
/// </summary>
private static readonly string SubscriptionKey =
ConfigurationManager.AppSettings["contentmoderator:subscriptionkey"];
/// <summary>
/// The moderator client
/// </summary>
private readonly ModeratorClient client;
/// <summary>
/// The localization service
/// </summary>
private readonly LocalizationService localizationService;
/// <summary>
/// Initializes a new instance of the <see cref="ModeratorValidationController"/> class.
/// </summary>
/// <param name="localizationService">The localization service.</param>
public ModeratorValidationController(LocalizationService localizationService)
{
this.client = new ModeratorClient(SubscriptionKey);
this.localizationService = localizationService;
}
/// <summary>
/// Determines whether [the specified body] [is safe text content].
/// </summary>
/// <param name="body">The body.</param>
/// <returns>A <see cref="JsonResult"/> with either true or an error message.</returns>
public JsonResult IsSafeTextContent(string body)
{
return this.CheckContent(body, Constants.MediaType.Plain, false, false);
}
/// <summary>
/// Determines whether [is safe HTML content] [the specified body].
/// </summary>
/// <param name="body">The body.</param>
/// <returns>A <see cref="JsonResult"/> with either true or an error message.</returns>
public JsonResult IsSafeHtmlContent(string body)
{
return this.CheckContent(body, Constants.MediaType.Html, false, false);
}
/// <summary>
/// Determines whether [is safe text content with urls] [the specified body].
/// </summary>
/// <param name="body">The body.</param>
/// <returns>A <see cref="JsonResult"/> with either true or an error message.</returns>
public JsonResult IsSafeTextContentWithUrls(string body)
{
return this.CheckContent(body, Constants.MediaType.Plain, true, false);
}
/// <summary>
/// Determines whether [is safe HTML content with urls] [the specified body].
/// </summary>
/// <param name="body">The body.</param>
/// <returns>A <see cref="JsonResult"/> with either true or an error message.</returns>
public JsonResult IsSafeHtmlContentWithUrls(string body)
{
return this.CheckContent(body, Constants.MediaType.Html, true, false);
}
/// <summary>
/// Determines whether [is safe text content with pii] [the specified body].
/// </summary>
/// <param name="body">The body.</param>
/// <returns>A <see cref="JsonResult"/> with either true or an error message.</returns>
public JsonResult IsSafeTextContentWithPii(string body)
{
return this.CheckContent(body, Constants.MediaType.Plain, false, true);
}
/// <summary>
/// Determines whether [is safe HTML content with pii] [the specified body].
/// </summary>
/// <param name="body">The body.</param>
/// <returns>A <see cref="JsonResult"/> with either true or an error message.</returns>
public JsonResult IsSafeHtmlContentWithPii(string body)
{
return this.CheckContent(body, Constants.MediaType.Html, false, true);
}
/// <summary>
/// Determines whether [is safe text content only text] [the specified body].
/// </summary>
/// <param name="body">The body.</param>
/// <returns>A <see cref="JsonResult"/> with either true or an error message.</returns>
public JsonResult IsSafeTextContentOnlyText(string body)
{
return this.CheckContent(body, Constants.MediaType.Plain, true, true);
}
/// <summary>
/// Determines whether [is safe HTML content only text] [the specified body].
/// </summary>
/// <param name="body">The body.</param>
/// <returns>A <see cref="JsonResult"/> with either true or an error message.</returns>
public JsonResult IsSafeHtmlContentOnlyText(string body)
{
return this.CheckContent(body, Constants.MediaType.Html, true, true);
}
/// <summary>
/// Checks the content.
/// </summary>
/// <param name="body">The body.</param>
/// <param name="mediaType">Type of the media.</param>
/// <param name="allowUrls">if set to <c>true</c> [allow urls].</param>
/// <param name="allowPii">if set to <c>true</c> [allow pii].</param>
/// <returns>A <see cref="JsonResult"/> with either true or an error message.</returns>
private JsonResult CheckContent(string body, Constants.MediaType mediaType, bool allowUrls, bool allowPii)
{
Task<ScreenTextResult> moderate = this.client.ScreenTextAsync(
body,
mediaType,
ContentLanguage.PreferredCulture.Name,
true,
true,
true,
string.Empty);
ScreenTextResult result = moderate.Result;
if (!ResultSuccess(result))
{
return this.Json(this.Translate("/validation/moderatornotavailable"), JsonRequestBehavior.AllowGet);
}
bool safeText = IsSafeText(result);
bool safeUrl = allowUrls ? IsSafeUrl(result) : ContainsNoUrl(result);
bool safePii = allowPii ? IsSafePii(result) : ContainsNoPii(result);
bool noMisrepresentation = !IsMisrepresentation(result);
if (safeText && safeUrl && safePii && noMisrepresentation)
{
return this.Json(true, JsonRequestBehavior.AllowGet);
}
return this.Json(this.Translate("/validation/moderation"), JsonRequestBehavior.AllowGet);
}
/// <summary>
/// Results the success.
/// </summary>
/// <param name="result">The result.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
private static bool ResultSuccess(Result result)
{
return (result.Status != null) && (result.Status.Code == "3000");
}
/// <summary>
/// Determines whether the specified result is misrepresentation.
/// </summary>
/// <param name="result">The result.</param>
/// <returns><c>true</c> if the specified result is misrepresentation; otherwise, <c>false</c>.</returns>
private static bool IsMisrepresentation(ScreenTextResult result)
{
return !string.IsNullOrWhiteSpace(result.Misrepresentation);
}
/// <summary>
/// Determines whether [is safe pii] [the specified result].
/// </summary>
/// <param name="result">The result.</param>
/// <returns><c>true</c> if [is safe pii] [the specified result]; otherwise, <c>false</c>.</returns>
private static bool IsSafePii(ScreenTextResult result)
{
if (result.PII == null)
{
return true;
}
return (result.PII.Email == null) || (result.PII.Email.Count <= 0)
|| result.PII.Email.All(email => email.SubType.Equals("Regular", StringComparison.OrdinalIgnoreCase));
}
/// <summary>
/// Determines whether [contains no pii] [the specified result].
/// </summary>
/// <param name="result">The result.</param>
/// <returns><c>true</c> if [contains no pii] [the specified result]; otherwise, <c>false</c>.</returns>
private static bool ContainsNoPii(ScreenTextResult result)
{
return result.PII == null;
}
/// <summary>
/// Determines whether [is safe text] [the specified result].
/// </summary>
/// <param name="result">The result.</param>
/// <returns><c>true</c> if [is safe text] [the specified result]; otherwise, <c>false</c>.</returns>
private static bool IsSafeText(ScreenTextResult result)
{
return (result.Terms == null) || (result.Terms.Length == 0);
}
/// <summary>
/// Determines whether [contains no URL] [the specified result].
/// </summary>
/// <param name="result">The result.</param>
/// <returns><c>true</c> if [contains no URL] [the specified result]; otherwise, <c>false</c>.</returns>
private static bool ContainsNoUrl(ScreenTextResult result)
{
return (result.Urls == null) || (result.Urls.Length == 0);
}
/// <summary>
/// Determines whether [is safe URL] [the specified result].
/// </summary>
/// <param name="result">The result.</param>
/// <returns><c>true</c> if [is safe URL] [the specified result]; otherwise, <c>false</c>.</returns>
private static bool IsSafeUrl(ScreenTextResult result)
{
bool safeUrl = true;
if ((result.Urls == null) || (result.Urls.Length == 0))
{
return true;
}
foreach (MatchUrl matchUrl in result.Urls)
{
if (matchUrl.categories.Adult > 0.0)
{
safeUrl = false;
}
if (matchUrl.categories.Malware > 0.0)
{
safeUrl = false;
}
if (matchUrl.categories.Phishing > 0.0)
{
safeUrl = false;
}
}
return safeUrl;
}
/// <summary>
/// Translates the specified resurce key.
/// </summary>
/// <param name="resurceKey">The resurce key.</param>
/// <returns>System.String.</returns>
private string Translate(string resurceKey)
{
string value;
if (!this.localizationService.TryGetString(resurceKey, out value))
{
value = resurceKey;
}
return value;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment