ASP.NET Core  

Implementing Sentiment Analysis in ASP.NET Core + Angular Applications

Sentiment analysis is the process of automatically detecting the emotional tone of text. Businesses use it to monitor customer feedback, social media posts, product reviews, and support tickets. Integrating sentiment analysis into a modern web application can provide actionable insights and improve user experience.

In this article, we will walk through a production-ready approach to integrating sentiment analysis in a full-stack application using ASP.NET Core as backend and Angular as frontend. We will cover:

  1. Architecture overview

  2. Choosing a sentiment analysis approach

  3. Backend implementation in ASP.NET Core

  4. Exposing REST APIs for Angular consumption

  5. Angular frontend integration

  6. Performance and scalability considerations

  7. Real-world best practices

This guide assumes you have a good understanding of both Angular and ASP.NET Core, as well as general knowledge of Natural Language Processing (NLP) concepts.

1. Architecture Overview

A sentiment analysis system in a web application typically follows this architecture:

Angular Frontend <---- REST API ----> ASP.NET Core Backend <---- Sentiment Engine / ML Model

Responsibilities

Angular Frontend

  • Capture user input (feedback, comments, or text)

  • Display sentiment results

  • Visualise analytics if needed

ASP.NET Core Backend

  • Expose REST API endpoints

  • Receive text data from frontend

  • Call sentiment analysis logic or external services

  • Store results in database if required

Sentiment Analysis Engine

  • Could be a built-in .NET ML.NET model,

  • Or an external API (like Azure Cognitive Services or OpenAI)

  • Returns sentiment score (positive, negative, neutral) and confidence

2. Choosing a Sentiment Analysis Approach

There are three common approaches:

2.1 Using Pre-trained NLP APIs

  • Examples: Azure Cognitive Services, OpenAI API, Google NLP API

  • Pros:

    • Quick to integrate

    • High accuracy

    • No model training required

  • Cons:

    • API costs

    • Dependency on external services

2.2 Using ML.NET in ASP.NET Core

  • Build and train a sentiment analysis model using ML.NET

  • Pros:

    • Fully controlled

    • No external dependencies

    • Can train on custom datasets

  • Cons:

    • Requires model training

    • Slightly slower than cloud APIs on large-scale input

2.3 Hybrid Approach

  • Use pre-trained model first

  • Fine-tune with ML.NET on your own dataset if needed

For enterprise applications, ML.NET or Azure Cognitive Services are most commonly used.

3. Setting Up ASP.NET Core Backend

We will use ML.NET for sentiment analysis. ML.NET is a production-ready, cross-platform machine learning framework for .NET.

3.1 Create a New ASP.NET Core Web API

dotnet new webapi -n SentimentApi
cd SentimentApi

Add ML.NET NuGet package:

dotnet add package Microsoft.ML

3.2 Define Data Models

Create Models/SentimentData.cs:

using Microsoft.ML.Data;

public class SentimentData
{
    [LoadColumn(0)]
    public string Text { get; set; }
}

public class SentimentPrediction
{
    [ColumnName("PredictedLabel")]
    public bool IsPositive { get; set; }

    public float Score { get; set; }
}

3.3 Load Pre-trained Model or Train New Model

You can train a simple model using a CSV dataset (data/sentiment.csv) with two columns: Text and Label (0 = negative, 1 = positive).

Create Services/SentimentService.cs:

using Microsoft.ML;
using Microsoft.ML.Data;

public class SentimentService
{
    private readonly MLContext _mlContext;
    private ITransformer _mlModel;
    private PredictionEngine<SentimentData, SentimentPrediction> _predEngine;

    public SentimentService()
    {
        _mlContext = new MLContext();
        LoadModel();
    }

    private void LoadModel()
    {
        // Option 1: Load pre-trained model from file
        if (File.Exists("Models/SentimentModel.zip"))
        {
            _mlModel = _mlContext.Model.Load("Models/SentimentModel.zip", out _);
        }
        else
        {
            // Option 2: Train a new model
            var data = _mlContext.Data.LoadFromTextFile<SentimentData>("data/sentiment.csv", hasHeader: true, separatorChar: ',');
            var pipeline = _mlContext.Transforms.Text.FeaturizeText("Features", nameof(SentimentData.Text))
                            .Append(_mlContext.BinaryClassification.Trainers.SdcaLogisticRegression(labelColumnName: "Label", featureColumnName: "Features"));

            _mlModel = pipeline.Fit(data);

            // Save model for later use
            _mlContext.Model.Save(_mlModel, data.Schema, "Models/SentimentModel.zip");
        }

        _predEngine = _mlContext.Model.CreatePredictionEngine<SentimentData, SentimentPrediction>(_mlModel);
    }

    public SentimentPrediction Predict(string text)
    {
        return _predEngine.Predict(new SentimentData { Text = text });
    }
}

3.4 Create Controller

Controllers/SentimentController.cs:

using Microsoft.AspNetCore.Mvc;

[Route("api/[controller]")]
[ApiController]
public class SentimentController : ControllerBase
{
    private readonly SentimentService _sentimentService;

    public SentimentController(SentimentService sentimentService)
    {
        _sentimentService = sentimentService;
    }

    [HttpPost("analyze")]
    public IActionResult Analyze([FromBody] SentimentRequest request)
    {
        if (string.IsNullOrWhiteSpace(request.Text))
            return BadRequest("Text cannot be empty");

        var result = _sentimentService.Predict(request.Text);
        return Ok(new
        {
            sentiment = result.IsPositive ? "Positive" : "Negative",
            score = result.Score
        });
    }
}

public class SentimentRequest
{
    public string Text { get; set; }
}

3.5 Register Service in Program.cs

builder.Services.AddSingleton<SentimentService>();

4. Angular Frontend Integration

4.1 Create Angular Service

// sentiment.service.ts
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';

export interface SentimentResponse {
  sentiment: string;
  score: number;
}

@Injectable({
  providedIn: 'root'
})
export class SentimentService {
  private apiUrl = 'https://localhost:5001/api/sentiment/analyze';

  constructor(private http: HttpClient) {}

  analyzeText(text: string) {
    return this.http.post<SentimentResponse>(this.apiUrl, { text });
  }
}

4.2 Angular Component for Sentiment Input

// sentiment.component.ts
import { Component } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { SentimentService } from './sentiment.service';

@Component({
  selector: 'app-sentiment',
  templateUrl: './sentiment.component.html'
})
export class SentimentComponent {
  form: FormGroup;
  sentimentResult: string | null = null;
  score: number | null = null;

  constructor(private fb: FormBuilder, private sentimentService: SentimentService) {
    this.form = this.fb.group({
      text: ['']
    });
  }

  analyze() {
    const text = this.form.value.text;
    if (!text) return;

    this.sentimentService.analyzeText(text).subscribe(res => {
      this.sentimentResult = res.sentiment;
      this.score = res.score;
    });
  }
}

4.3 Component Template

<div>
  <textarea formControlName="text" placeholder="Enter your text"></textarea>
  <button (click)="analyze()">Analyze Sentiment</button>
</div>

<div *ngIf="sentimentResult">
  <p>Sentiment: {{ sentimentResult }}</p>
  <p>Score: {{ score | number:'1.2-2' }}</p>
</div>

5. Real-World Best Practices

5.1 Asynchronous Processing

For large text or batch analysis, offload sentiment analysis to a background queue (e.g., Azure Functions, RabbitMQ, or Hangfire).

5.2 Model Versioning

Keep versions of your trained models. When updating a model, do not overwrite production model until fully tested.

5.3 Caching Results

For repeated analyses of the same text (e.g., product reviews), cache results to reduce compute.

5.4 Logging and Monitoring

Log API calls, text length, sentiment score distribution for monitoring accuracy and potential misuse.

5.5 Security

  • Validate input text to avoid injection attacks

  • Rate-limit API if publicly exposed

5.6 Frontend UX

  • Show a loading spinner for analysis

  • Limit text length for performance

  • Highlight positive/negative words for user feedback

6. Scaling Sentiment Analysis

6.1 Using Cloud NLP APIs

For enterprise workloads, consider cloud APIs:

  • Azure Cognitive Services Text Analytics

  • Google Cloud Natural Language API

  • OpenAI API

Advantages:

  • Auto-scaling

  • High accuracy

  • Multilingual support

6.2 Batch Processing

  • Store incoming text in a queue or database

  • Process asynchronously

  • Update frontend via SignalR or polling

7. Performance Considerations

  1. ML.NET PredictionEngine is not thread-safe. Use singleton pattern carefully. For high throughput, create PredictionEnginePool:

builder.Services.AddPredictionEnginePool<SentimentData, SentimentPrediction>()
                .FromFile("Models/SentimentModel.zip");
  1. For Angular, debounce input to avoid excessive API calls:

this.form.get('text')?.valueChanges
  .pipe(debounceTime(500))
  .subscribe(value => this.analyze());
  1. Compress API responses for large data sets using GZIP.

8. Handling Multilingual Text

ML.NET supports only the language your model was trained on. For multi-language support:

  1. Translate text to English using Azure Translator API

  2. Apply sentiment analysis

  3. Store original and translated text

Alternatively, cloud NLP APIs often support multilingual sentiment detection natively.

9. Advanced Features

9.1 Entity Sentiment

Detect sentiment towards specific entities in a text:

  • Product name

  • Feature

  • Brand

9.2 Word-Level Highlighting

Frontend can highlight positive and negative words for UX:

  • Split text by words

  • Match words against positive/negative dictionaries

  • Apply CSS classes

9.3 Analytics Dashboard

Aggregate sentiment over time:

  • Daily/weekly sentiment trends

  • Average score per product/service

  • Visualize via charts (Angular + Chart.js or ngx-charts)

10. Testing

10.1 Unit Tests

  • Test sentiment service with known inputs

  • Verify API returns correct sentiment labels

[Fact]
public void Predict_PositiveText_ReturnsPositive()
{
    var service = new SentimentService();
    var result = service.Predict("I love this product!");
    Assert.True(result.IsPositive);
}

10.2 Angular Tests

  • Test service calls using HttpClientTestingModule

  • Test component displays correct sentiment

11. Security Considerations

  1. Sanitize user input before analysis

  2. Limit input size to prevent denial-of-service

  3. Use HTTPS for API

  4. Implement API rate limiting

Summary

We have covered end-to-end implementation of sentiment analysis in an ASP.NET Core + Angular application:

  1. Architecture design

  2. Choosing ML.NET or cloud-based sentiment analysis

  3. Backend service creation and API exposure

  4. Angular service and component integration

  5. Real-world best practices for performance, security, and scalability

  6. Advanced features like multilingual support, entity-level sentiment, and dashboards

This approach is production-ready, modular, and maintainable. It allows developers to extend features like batch processing, background jobs, or multi-language sentiment detection without rewriting the system.

By combining ML.NET with Angular reactive forms, you get a robust, full-stack solution that provides actionable sentiment insights in real time.