Building SmartTask Manager API
Building SmartTask Manager API
This step-by-step guide walks you through creating a complete **Web API to manage tasks** in a real-world style. You’ll use **ASP.NET Core Web API** for building the service endpoints and **Entity Framework Core (EF Core)** for database interaction. This API is designed to be a robust backend, ready to be integrated with any frontend, including a full-stack Blazor application.
Step 1: Create the Project
First, let's set up our ASP.NET Core Web API project. Open your terminal or command prompt and run the following commands:
dotnet new webapi -n SmartTaskManager.Api
cd SmartTaskManager.Api
✅ This command creates a new ASP.NET Core Web API project named `SmartTaskManager.Api`. By default, this project comes with Swagger (OpenAPI) enabled for easy API testing and a sample `WeatherForecastController`. For our task manager, you can remove the `WeatherForecastController.cs` and `WeatherForecast.cs` files.
Step 2: Define the Model
Next, we'll define the C# model that represents a single task item. This model will be used by both our API and our database.
Create a new folder named `Models` in your `SmartTaskManager.Api` project, and then add a new C# class file named `TaskItem.cs` inside it.
// Models/TaskItem.cs
using System.ComponentModel.DataAnnotations; // Required for Data Annotations
namespace SmartTaskManager.Api.Models
{
public class TaskItem
{
public int Id { get; set; } // Primary Key (EF Core convention)
[Required(ErrorMessage = "Task title is required.")] // Data Annotation for validation
public string Title { get; set; } = string.Empty; // Initialize to prevent null warnings
public string Description { get; set; } = string.Empty; // Optional description
public string AssignedTo { get; set; } = string.Empty; // Who the task is assigned to
public DateTime DueDate { get; set; } = DateTime.Today; // Deadline for the task
public bool IsCompleted { get; set; } = false; // Status of the task
}
}
💡 **Explanation:**
- `Id`: This property will automatically be recognized by EF Core as the **primary key** for the `TaskItem` entity, and its value will typically be auto-incremented by the database.
- `Title`: Marked with `[Required]`, meaning a task must always have a title.
- `Description`: An optional field for more details about the task.
- `AssignedTo`: Could store a user's name or ID, indicating who is responsible for the task.
- `DueDate`: A `DateTime` property to track deadlines.
- `IsCompleted`: A boolean flag to easily track the completion status of a task.
Step 3: Set Up EF Core DbContext
Now, let's configure Entity Framework Core to interact with our database. We'll start by installing the necessary NuGet packages and creating our `DbContext` class.
🔧 Install EF Core Packages
Open your terminal in the `SmartTaskManager.Api` project directory and run:
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
This package provides the SQL Server provider for EF Core.
🧠 Create Data/AppDbContext.cs
Create a new folder named `Data` in your `SmartTaskManager.Api` project, and then add a new C# class file named `AppDbContext.cs` inside it.
// Data/AppDbContext.cs
using Microsoft.EntityFrameworkCore; // Required for DbContext
using SmartTaskManager.Api.Models; // Required for TaskItem model
namespace SmartTaskManager.Api.Data
{
public class AppDbContext : DbContext
{
// Constructor to pass DbContextOptions to the base class
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) {}
// DbSet property for our TaskItem entity, representing the "Tasks" table in the database
public DbSet<TaskItem> Tasks { get; set; }
}
}
💡 **Explanation:**
- `AppDbContext` inherits from `Microsoft.EntityFrameworkCore.DbContext`, which is the main class for interacting with your database using EF Core.
- `public DbSet
Tasks { get; set; }`: This property tells EF Core to create and manage a database table named `Tasks` (by convention) that will store `TaskItem` objects.
Step 4: Register DbContext in Program.cs
Now we need to register our `AppDbContext` with the ASP.NET Core dependency injection container and provide a database connection string.
Open `SmartTaskManager.Api/Program.cs` and add the following code:
// Program.cs
using SmartTaskManager.Api.Data; // For AppDbContext
using Microsoft.EntityFrameworkCore; // For UseSqlServer
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
// Add EF Core DbContext and configure it to use SQL Server
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(); // Enable Swagger UI
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI(); // Enable Swagger UI
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers(); // Maps controller actions to routes
app.Run();
🔧 **Add connection string in `appsettings.json`:** Open `SmartTaskManager.Api/appsettings.json` and add the `ConnectionStrings` section.
// appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=SmartTaskDb;Trusted_Connection=True;MultipleActiveResultSets=true;"
}
}
**Note:** `Server=(localdb)\\mssqllocaldb` points to a local SQL Server Express LocalDB instance, which is convenient for development. `Database=SmartTaskDb` is the name of our database. `Trusted_Connection=True` uses Windows Authentication. `MultipleActiveResultSets=true` is often useful for certain EF Core scenarios, though not strictly required for this basic setup.
Step 5: Create the Database
With our model and `DbContext` defined, we can now use EF Core migrations to create the database schema.
🔧 Install EF CLI if not available
If you haven't already, install the Entity Framework Core command-line tools globally:
dotnet tool install --global dotnet-ef
🔧 Run migrations and update database
Open your terminal in the `SmartTaskManager.Api` project directory and run these commands:
dotnet ef migrations add InitialCreate
dotnet ef database update
The `Add-Migration InitialCreate` command creates a new migration file that represents the initial state of your database schema based on your `TaskItem` model. The `Update-Database` command then applies this migration to your SQL Server instance, creating the `SmartTaskDb` database and the `Tasks` table within it.
Step 6: Create the TasksController
Now we'll create our API controller that exposes CRUD operations for our tasks.
Create a new folder named `Controllers` in your `SmartTaskManager.Api` project, and then add a new C# class file named `TasksController.cs` inside it.
// Controllers/TasksController.cs
using Microsoft.AspNetCore.Mvc;
using SmartTaskManager.Api.Data; // For AppDbContext
using SmartTaskManager.Api.Models; // For TaskItem model
using Microsoft.EntityFrameworkCore; // For ToListAsync, FindAsync, Entry, State
namespace SmartTaskManager.Api.Controllers
{
[ApiController] // Indicates this is an API controller
[Route("api/[controller]")] // Sets the base route for this controller (e.g., /api/tasks)
public class TasksController : ControllerBase
{
private readonly AppDbContext _context; // Inject our DbContext
public TasksController(AppDbContext context)
{
_context = context;
}
// GET: api/tasks
[HttpGet]
public async Task<ActionResult<IEnumerable<TaskItem>>> GetTasks()
{
// Returns all tasks from the database
return await _context.Tasks.ToListAsync();
}
// GET: api/tasks/{id}
[HttpGet("{id}")] // Route with an ID parameter
public async Task<ActionResult<TaskItem>> GetTask(int id)
{
// Finds a single task by its ID
var task = await _context.Tasks.FindAsync(id);
if (task == null)
{
return NotFound(); // Returns 404 Not Found if task doesn't exist
}
return task; // Returns 200 OK with the task
}
// POST: api/tasks
[HttpPost]
public async Task<ActionResult<TaskItem>> CreateTask(TaskItem task)
{
// Adds the new task to the database
_context.Tasks.Add(task);
await _context.SaveChangesAsync(); // Saves changes to the database
// Returns 201 Created status with the location of the new resource
return CreatedAtAction(nameof(GetTask), new { id = task.Id }, task);
}
// PUT: api/tasks/{id}
[HttpPut("{id}")]
public async Task<IActionResult> UpdateTask(int id, TaskItem updatedTask)
{
if (id != updatedTask.Id)
{
return BadRequest(); // Returns 400 Bad Request if ID in route doesn't match ID in body
}
// Marks the entity as modified so EF Core knows to update it
_context.Entry(updatedTask).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync(); // Saves changes
}
catch (DbUpdateConcurrencyException)
{
// Handle concurrency conflicts if the task was deleted by another process
if (!_context.Tasks.Any(e => e.Id == id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent(); // Returns 204 No Content for successful update
}
// DELETE: api/tasks/{id}
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteTask(int id)
{
// Finds the task to delete
var task = await _context.Tasks.FindAsync(id);
if (task == null)
{
return NotFound(); // Returns 404 if task doesn't exist
}
// Removes the task from the database
_context.Tasks.Remove(task);
await _context.SaveChangesAsync(); // Saves changes
return NoContent(); // Returns 204 No Content for successful deletion
}
}
}
Step 7: Test the API
Now that our API is built, let's test it using Swagger UI, which is automatically configured in ASP.NET Core Web API projects.
Run your API project from the terminal:
dotnet run
Once the application starts, open your browser and navigate to the Swagger UI endpoint, typically:
https://localhost:5001/swagger (or similar port if different).
In the Swagger UI, you can:
- **GET /api/Tasks:** Try it out to see an empty list initially.
- **POST /api/Tasks:** Use the "Try it out" feature to create new tasks. Provide a JSON body for the task (e.g., `{"title": "Learn Blazor", "description": "Complete the Blazor course", "assignedTo": "Raushan", "dueDate": "2025-08-31T00:00:00", "isCompleted": false}`).
- **GET /api/Tasks:** Call this again to see your newly created tasks.
- **GET /api/Tasks/{id}:** Retrieve a specific task by its ID.
- **PUT /api/Tasks/{id}:** Update an existing task.
- **DELETE /api/Tasks/{id}:** Delete a task.
💡 Optional Filters:
You can enhance your `TasksController` to support filtering tasks based on criteria like `assignedTo` or `IsCompleted`. Add the following new `HttpGet` action to your `TasksController.cs`:
// Controllers/TasksController.cs (Add this method)
// GET: api/tasks/filter?assignedTo=Raushan&completed=false
[HttpGet("filter")] // Custom route for filtering
public async Task<ActionResult<IEnumerable<TaskItem>>> Filter(string? assignedTo, bool? completed)
{
var query = _context.Tasks.AsQueryable(); // Start with all tasks
// Apply filter for AssignedTo if provided
if (!string.IsNullOrEmpty(assignedTo))
{
query = query.Where(t => t.AssignedTo == assignedTo);
}
// Apply filter for IsCompleted if provided
if (completed.HasValue)
{
query = query.Where(t => t.IsCompleted == completed.Value);
}
// Execute the query and return the filtered list
return await query.ToListAsync();
}
This `Filter` method allows you to query your tasks with optional parameters, providing more flexibility for your frontend.
✅ You’ve Built a Real Web API!
Congratulations! You now have a fully working ASP.NET Core Web API that can manage tasks, complete with CRUD operations, database persistence via Entity Framework Core, and optional filtering capabilities. This API is ready to be connected to any frontend application, including your Blazor WebAssembly client, to build a complete full-stack solution.
Comments
Post a Comment