Quickstart: Content Moderator client library for .NET

Get started with the Content Moderator client library for .NET. Follow these steps to install the package and try out the example code for basic tasks. Content Moderator is a cognitive service that checks text, image, and video content for material that is potentially offensive, risky, or otherwise undesirable. When such material is found, the service applies appropriate labels (flags) to the content. Your app can then handle flagged content to comply with regulations or maintain the intended environment for users.

Use the Content Moderator client library for .NET to:

Reference documentation | Library source code | Package (NuGet) | Samples

Prerequisites

Setting up

Create a Content Moderator Azure resource

Azure Cognitive Services are represented by Azure resources that you subscribe to. Create a resource for Content Moderator using the Azure portal or Azure CLI on your local machine. You can also:

After you get a key from your trial subscription or resource, create environment variables for the key and endpoint URL, named CONTENT_MODERATOR_SUBSCRIPTION_KEY and CONTENT_MODERATOR_ENDPOINT, respectively.

Create a new C# application

Create a new .NET Core application in your preferred text editor or IDE.

In a console window (such as cmd, PowerShell, or Bash), use the dotnet new command to create a new console app with the name content-moderator-quickstart. This command creates a simple "Hello World" C# project with a single source file: Program.cs.

dotnet new console -n content-moderator-quickstart

Change your directory to the newly created app folder. You can build the application with:

dotnet build

The build output should contain no warnings or errors.

...
Build succeeded.
 0 Warning(s)
 0 Error(s)
...

From the project directory, open the Program.cs file in your preferred editor or IDE. Add the following using statements:

using Microsoft.Azure.CognitiveServices.ContentModerator;
using Microsoft.Azure.CognitiveServices.ContentModerator.Models;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;

In the Program class, create variables for your resource's endpoint location and key as environment variables.

// Your Content Moderator subscription key is found in your Azure portal resource on the 'Keys' page. Add to your environment variables.
private static readonly string SubscriptionKey = Environment.GetEnvironmentVariable("CONTENT_MODERATOR_SUBSCRIPTION_KEY");
// Base endpoint URL. Add this to your environment variables. Found on 'Overview' page in Azure resource. For example: https://westus.api.cognitive.microsoft.com
private static readonly string Endpoint = Environment.GetEnvironmentVariable("CONTENT_MODERATOR_ENDPOINT");

Note

If you created the environment variables after you launched the application, you will need to close and reopen the editor, IDE, or shell running it to access the variables.

Install the client library

Within the application directory, install the Content Moderator client library for .NET with the following command:

dotnet add package Microsoft.Azure.CognitiveServices.ContentModerator --version 2.0.0

If you're using the Visual Studio IDE, the client library is available as a downloadable NuGet package.

Object model

The following classes handle some of the major features of the Content Moderator .NET SDK.

Name Description
ContentModeratorClient This class is needed for all Content Moderator functionality. You instantiate it with your subscription information, and you use it to produce instances of other classes.
ImageModeration This class provides the functionality for analyzing images for adult content, personal information, or human faces.
TextModeration This class provides the functionality for analyzing text for language, profanity, errors, and personal information.
Reviews This class provides the functionality of the Review APIs, including the methods for creating jobs, custom workflows, and human reviews.

Code examples

These code snippets show you how to do the following tasks with the Content Moderator client library for .NET:

Authenticate the client

In a new method, instantiate client objects with your endpoint and key. You don't need a different client for every scenario, but it can help keep your code organized.

// Create an image review client
ContentModeratorClient clientImage = Authenticate(SubscriptionKey, Endpoint);
// Create a text review client
ContentModeratorClient clientText = Authenticate(SubscriptionKey, Endpoint);
// Create a human reviews client
ContentModeratorClient clientReviews = Authenticate(SubscriptionKey, Endpoint);

Moderate text

The following code uses a Content Moderator client to analyze a body of text and print the results to the console. In the root of your Program class, define input and output files:

// TEXT MODERATION
// Name of the file that contains text
private static readonly string TextFile = "TextFile.txt";
// The name of the file to contain the output from the evaluation.
private static string TextOutputFile = "TextModerationOutput.txt";

Then at the root of your project and add a TextFile.txt file. Add your own text to this file, or use the following sample text:

Is this a grabage email abcdef@abcd.com, phone: 4255550111, IP: 255.255.255.255, 1234 Main Boulevard, Panapolis WA 96555.
Crap is the profanity here. Is this information PII? phone 4255550111

Add the following method call to your Main method:

// Moderate text from text in a file
ModerateText(clientText, TextFile, TextOutputFile);

Then define the text moderation method somewhere in your Program class:

/*
 * TEXT MODERATION
 * This example moderates text from file.
 */
public static void ModerateText(ContentModeratorClient client, string inputFile, string outputFile)
{
    Console.WriteLine("--------------------------------------------------------------");
    Console.WriteLine();
    Console.WriteLine("TEXT MODERATION");
    Console.WriteLine();
    // Load the input text.
    string text = File.ReadAllText(inputFile);

    // Remove carriage returns
    text = text.Replace(Environment.NewLine, " ");
    // Convert string to a byte[], then into a stream (for parameter in ScreenText()).
    byte[] textBytes = Encoding.UTF8.GetBytes(text);
    MemoryStream stream = new MemoryStream(textBytes);

    Console.WriteLine("Screening {0}...", outputFile);
    // Format text

    // Save the moderation results to a file.
    using (StreamWriter outputWriter = new StreamWriter(outputFile, false))
    {
        using (client)
        {
            // Screen the input text: check for profanity, classify the text into three categories,
            // do autocorrect text, and check for personally identifying information (PII)
            outputWriter.WriteLine("Autocorrect typos, check for matching terms, PII, and classify.");

            // Moderate the text
            var screenResult = client.TextModeration.ScreenText("text/plain", stream, "eng", true, true, null, true);
            outputWriter.WriteLine(JsonConvert.SerializeObject(screenResult, Formatting.Indented));
        }

        outputWriter.Flush();
        outputWriter.Close();
    }

    Console.WriteLine("Results written to {0}", outputFile);
    Console.WriteLine();
}

Moderate images

The following code uses a Content Moderator client, along with an ImageModeration object, to analyze remote images for adult and racy content.

Note

You can also analyze the content of a local image. See the reference documentation for methods and operations that work with local images.

Get sample images

Define your input and output files:

// IMAGE MODERATION
//The name of the file that contains the image URLs to evaluate.
private static readonly string ImageUrlFile = "ImageFiles.txt";
// The name of the file to contain the output from the evaluation.
private static string ImageOutputFile = "ImageModerationOutput.json";

Then create the input file, ImageFiles.txt, at the root of your project. In this file, you add the URLs of images to analyze—one URL on each line. You can use the following sample images:

https://moderatorsampleimages.blob.core.windows.net/samples/sample2.jpg
https://moderatorsampleimages.blob.core.windows.net/samples/sample5.png

Pass your input and output files into the following method call in the Main method. You'll define this method at a later step.

// Moderate text from text in a file
ModerateText(clientText, TextFile, TextOutputFile);

Define helper class

Add the following class definition within the Program class. This inner class will handle image moderation results.

// Contains the image moderation results for an image, 
// including text and face detection results.
public class EvaluationData
{
    // The URL of the evaluated image.
    public string ImageUrl;

    // The image moderation results.
    public Evaluate ImageModeration;

    // The text detection results.
    public OCR TextDetection;

    // The face detection results;
    public FoundFaces FaceDetection;
}

Define the image moderation method

The following method iterates through the image URLs in a text file, creates an EvaluationData instance, and analyzes the image for adult/racy content, text, and human faces. Then it adds the final EvaluationData instance to a list and writes the complete list of returned data to the console.

Iterate through image URLs

/*
 * IMAGE MODERATION
 * This example moderates images from URLs.
 */
public static void ModerateImages(ContentModeratorClient client, string urlFile, string outputFile)
{
    Console.WriteLine("--------------------------------------------------------------");
    Console.WriteLine();
    Console.WriteLine("IMAGE MODERATION");
    Console.WriteLine();
    // Create an object to store the image moderation results.
    List<EvaluationData> evaluationData = new List<EvaluationData>();

    using (client)
    {
        // Read image URLs from the input file and evaluate each one.
        using (StreamReader inputReader = new StreamReader(urlFile))
        {
            while (!inputReader.EndOfStream)
            {
                string line = inputReader.ReadLine().Trim();
                if (line != String.Empty)
                {
                    Console.WriteLine("Evaluating {0}...", Path.GetFileName(line));
                    var imageUrl = new BodyModel("URL", line.Trim());

Analyze content

For more information on the image attributes that Content Moderator screens for, see the Image moderation concepts guide.

            var imageData = new EvaluationData
            {
                ImageUrl = imageUrl.Value,

                // Evaluate for adult and racy content.
                ImageModeration =
                client.ImageModeration.EvaluateUrlInput("application/json", imageUrl, true)
            };
            Thread.Sleep(1000);

            // Detect and extract text.
            imageData.TextDetection =
                client.ImageModeration.OCRUrlInput("eng", "application/json", imageUrl, true);
            Thread.Sleep(1000);

            // Detect faces.
            imageData.FaceDetection =
                client.ImageModeration.FindFacesUrlInput("application/json", imageUrl, true);
            Thread.Sleep(1000);

            // Add results to Evaluation object
            evaluationData.Add(imageData);
        }
    }
}

Write moderation results to file

        // Save the moderation results to a file.
        using (StreamWriter outputWriter = new StreamWriter(outputFile, false))
        {
            outputWriter.WriteLine(JsonConvert.SerializeObject(
                evaluationData, Formatting.Indented));

            outputWriter.Flush();
            outputWriter.Close();
        }
        Console.WriteLine();
        Console.WriteLine("Image moderation results written to output file: " + outputFile);
        Console.WriteLine();
    }
}

Create a review

You can use the Content Moderator .NET SDK to feed content into the Review tool so that human moderators can review it. To learn more about the Review tool, see the Review tool conceptual guide.

The method in this section uses the Reviews class to create a review, retrieve its ID, and check its details after receiving human input through the Review tool's web portal. It logs all of this information in an output text file. Call the method from your Main method:

// Create image reviews for human reviewers
CreateReviews(clientReviews, IMAGE_URLS_FOR_REVIEW, TEAM_NAME, ReviewsEndpoint);

Get sample images

Declare the following array at the root of your Program class. This variable references a sample image to use to create the review.

// The list of URLs of the images to create review jobs for.
private static readonly string[] IMAGE_URLS_FOR_REVIEW = new string[] { "https://moderatorsampleimages.blob.core.windows.net/samples/sample5.png" };

Get review credentials

Sign in to the Review tool and retrieve your team name. Then assign it to the appropriate variable in the Program class. Optionally, you can set up a callback endpoint to receive updates on the activity of the review.

// The name of the team to assign the review to. Must be the team name used to create your Content Moderator website account. 
// If you do not yet have an account, follow this: https://docs.microsoft.com/en-us/azure/cognitive-services/content-moderator/quick-start
// Select the gear symbol (settings)-->Credentials to retrieve it. Your team name is the Id associated with your subscription.
private static readonly string TEAM_NAME = Environment.GetEnvironmentVariable("CONTENT_MODERATOR_TEAM_NAME");
// The callback endpoint for completed human reviews. Add to your environment variables. 
// For example: https://westus.api.cognitive.microsoft.com/contentmoderator/review/v1.0
// As reviewers complete reviews, results are sent using an HTTP POST request.
private static readonly string ReviewsEndpoint = Environment.GetEnvironmentVariable("CONTENT_MODERATOR_REVIEWS_ENDPOINT");

Define helper class

Add the following class definition within your Program class. This class will be used to represent a single review instance that is submitted to the Review tool.

// Associates the review ID (assigned by the service) to the internal.
public class ReviewItem
{
    // The media type for the item to review. 
    public string Type;
    // The URL of the item to review.
    public string Url;
    // The internal content ID for the item to review.
    public string ContentId;
    // The ID that the service assigned to the review.
    public string ReviewId;
}

Define helper method

Add the following method to the Program class. This method will write the results of review queries to the output text file.

// Helper function that writes a message to the log file, and optionally to the console.
// If echo is set to true, details will be written to the console.
private static void WriteLine(TextWriter writer, string message = null, bool echo = true)
{
    writer.WriteLine(message ?? String.Empty);
    if (echo) { Console.WriteLine(message ?? String.Empty); }
}

Define the review creation method

Now you're ready to define the method that will handle the review creation and querying. Add a new method, CreateReviews, and define the following local variables.

// Create the reviews using the fixed list of images.
private static void CreateReviews(ContentModeratorClient client, string[] ImageUrls, string teamName, string endpoint)
{
    Console.WriteLine("--------------------------------------------------------------");
    Console.WriteLine();
    Console.WriteLine("CREATE HUMAN IMAGE REVIEWS");

    // The minimum amount of time, in milliseconds, to wait between calls to the Image List API.
    const int throttleRate = 2000;
    // The number of seconds to delay after a review has finished before getting the review results from the server.
    const int latencyDelay = 45;

    // The name of the log file to create. Relative paths are relative to the execution directory.
    const string OutputFile = "OutputLog.txt";

    // The optional name of the subteam to assign the review to. Not used for this example.
    const string Subteam = null;

    // The media type for the item to review. Valid values are "image", "text", and "video".
    const string MediaType = "image";

    // The metadata key to initially add to each review item. This is short for 'score'.
    // It will enable the keys to be 'a' (adult) and 'r' (racy) in the response,
    // with a value of true or false if the human reviewer marked them as adult and/or racy.
    const string MetadataKey = "sc";
    // The metadata value to initially add to each review item.
    const string MetadataValue = "true";

    // A static reference to the text writer to use for logging.
    TextWriter writer;

    // The cached review information, associating a local content ID to the created review ID for each item.
    List<ReviewItem> reviewItems = new List<ReviewItem>();

Post reviews to the Review tool

Then, add the following code to iterate through the given sample images, add metadata, and send them to the Review tool in a single batch.

using (TextWriter outputWriter = new StreamWriter(OutputFile, false))
{
    writer = outputWriter;
    WriteLine(writer, null, true);
    WriteLine(writer, "Creating reviews for the following images:", true);

    // Create the structure to hold the request body information.
    List<CreateReviewBodyItem> requestInfo = new List<CreateReviewBodyItem>();

    // Create some standard metadata to add to each item.
    List<CreateReviewBodyItemMetadataItem> metadata =
        new List<CreateReviewBodyItemMetadataItem>(new CreateReviewBodyItemMetadataItem[]
        { new CreateReviewBodyItemMetadataItem(MetadataKey, MetadataValue) });

    // Populate the request body information and the initial cached review information.
    for (int i = 0; i < ImageUrls.Length; i++)
    {
        // Cache the local information with which to create the review.
        var itemInfo = new ReviewItem()
        {
            Type = MediaType,
            ContentId = i.ToString(),
            Url = ImageUrls[i],
            ReviewId = null
        };

        WriteLine(writer, $" {Path.GetFileName(itemInfo.Url)} with id = {itemInfo.ContentId}.", true);

        // Add the item informaton to the request information.
        requestInfo.Add(new CreateReviewBodyItem(itemInfo.Type, itemInfo.Url, itemInfo.ContentId, endpoint, metadata));

        // Cache the review creation information.
        reviewItems.Add(itemInfo);
    }

    var reviewResponse = client.Reviews.CreateReviewsWithHttpMessagesAsync("application/json", teamName, requestInfo);

The object returned from the API call will contain unique ID values for each image uploaded. The following code parses these IDs and then uses them to query Content Moderator for the status of each image in the batch.

// Update the local cache to associate the created review IDs with the associated content.
var reviewIds = reviewResponse.Result.Body;
for (int i = 0; i < reviewIds.Count; i++) { reviewItems[i].ReviewId = reviewIds[i]; }

WriteLine(outputWriter, JsonConvert.SerializeObject(reviewIds, Formatting.Indented));
Thread.Sleep(throttleRate);

// Get details of the reviews created that were sent to the Content Moderator website.
WriteLine(outputWriter, null, true);
WriteLine(outputWriter, "Getting review details:", true);
foreach (var item in reviewItems)
{
    var reviewDetail = client.Reviews.GetReviewWithHttpMessagesAsync(teamName, item.ReviewId);
    WriteLine(outputWriter, $"Review {item.ReviewId} for item ID {item.ContentId} is " +
        $"{reviewDetail.Result.Body.Status}.", true);
    WriteLine(outputWriter, JsonConvert.SerializeObject(reviewDetail.Result.Body, Formatting.Indented));
    Thread.Sleep(throttleRate);
}

Get review details

The following code causes the program to wait for user input. When you come to this step at runtime, you can go to the Review tool yourself, verify that the sample image was uploaded, and interact with it. For information on how to interact with a review, see the Reviews how-to guide. When you're finished, you can press any key to continue the program and retrieve the results of the review process.

        Console.WriteLine();
        Console.WriteLine("Perform manual reviews on the Content Moderator site.");
        Console.WriteLine("Then, press any key to continue.");
        Console.ReadKey();

        // After the human reviews, the results are confirmed.
        Console.WriteLine();
        Console.WriteLine($"Waiting {latencyDelay} seconds for results to propagate.");
        Thread.Sleep(latencyDelay * 1000);

        // Get details from the human review.
        WriteLine(writer, null, true);
        WriteLine(writer, "Getting review details:", true);
        foreach (var item in reviewItems)
        {
            var reviewDetail = client.Reviews.GetReviewWithHttpMessagesAsync(teamName, item.ReviewId);
            WriteLine(writer, $"Review {item.ReviewId} for item ID {item.ContentId} is " + $"{reviewDetail.Result.Body.Status}.", true);
            WriteLine(outputWriter, JsonConvert.SerializeObject(reviewDetail.Result.Body, Formatting.Indented));

            Thread.Sleep(throttleRate);
        }

        Console.WriteLine();
        Console.WriteLine("Check the OutputLog.txt file for results of the review.");

        writer = null;
        outputWriter.Flush();
        outputWriter.Close();
    }
    Console.WriteLine("--------------------------------------------------------------");
}

If you used a callback endpoint in this scenario, it should receive an event in this format:

{'callback_endpoint': 'https://requestb.in/qmsakwqm',
 'content': '',
 'content_id': '3ebe16cb-31ed-4292-8b71-1dfe9b0e821f',
 'created_by': 'cspythonsdk',
 'metadata': [{'key': 'sc', 'value': 'True'}],
 'review_id': '201901i14682e2afe624fee95ebb248643139e7',
 'reviewer_result_tags': [{'key': 'a', 'value': 'True'},
                          {'key': 'r', 'value': 'True'}],
 'status': 'Complete',
 'sub_team': 'public',
 'type': 'Image'}

Run the application

Run the application from your application directory with the dotnet run command.

dotnet run 

Clean up resources

If you want to clean up and remove a Cognitive Services subscription, you can delete the resource or resource group. Deleting the resource group also deletes any other resources associated with it.

Next steps

In this quickstart, you learned how to use the Content Moderator .NET library to do moderation tasks. Next, learn more about the moderation of images or other media by reading a conceptual guide.