
June 18, 2026 07:23 by
Peter
Create + Assign + List + Edit + Complete operations and role-wise views (Admin / Manager / User) are supported by the ASP.NET Core MVC project (SQL Server + EF Core + Identity). I'll provide a finished, opinionated beginning project below that you can copy and run into a new solution. To make it function right out of the box, I made sensible defaults:
Defaults I used

- .NET 8 / ASP.NET Core MVC (minimal hosting Program.cs).
- EF Core with SQL Server (use LocalDB or your SQL Server instance).
- ASP.NET Identity for users & roles (Admin / Manager / User).
- Entity: TaskItem with create/assign/edit/complete flows.
- Role-wise view behavior:
- Admin: sees all tasks and can manage them + manage users/roles.
- Manager: sees tasks they created + tasks assigned to users in their team (simple demo: managers can view all tasks but UI filters for managers).
- User: sees only tasks assigned to them.
- Seeded roles + initial admin user automatically on startup.
- EF Migrations recommended (I show commands).
Below are the main files — copy them into a new project (or I can generate more files if required). I included the essential Controllers, Models, DbContext, Program, Views examples, and steps to run.
1. Create the project
From a terminal:
dotnet new mvc -n TaskManagerApp
cd TaskManagerApp
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools
dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore
2. appsettings.json
Add a SQL Server connection string (LocalDB used here):
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=TaskManagerAppDb;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
3. Models
Models/ApplicationUser.cs
using Microsoft.AspNetCore.Identity;
using System.Collections.Generic;
namespace TaskManagerApp.Models
{
public class ApplicationUser : IdentityUser
{
// Example extra property
public string FullName { get; set; }
// Optional: list of tasks assigned
public ICollection<TaskItem> AssignedTasks { get; set; }
}
}
Models/TaskItem.cs
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace TaskManagerApp.Models
{
public enum TaskStatus
{
Pending,
InProgress,
Completed
}
public class TaskItem
{
[Key]
public int Id { get; set; }
[Required, StringLength(200)]
public string Title { get; set; }
public string Description { get; set; }
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public DateTime? DueDate { get; set; }
public TaskStatus Status { get; set; } = TaskStatus.Pending;
// assigned user
public string AssignedUserId { get; set; }
[ForeignKey("AssignedUserId")]
public ApplicationUser AssignedUser { get; set; }
// who created the task (user id)
public string CreatedByUserId { get; set; }
}
}
4. Data / DbContext
Data/AppDbContext.cs
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using TaskManagerApp.Models;
namespace TaskManagerApp.Data
{
public class AppDbContext : IdentityDbContext<ApplicationUser>
{
public AppDbContext(DbContextOptions<AppDbContext> opts) : base(opts) { }
public DbSet<TaskItem> TaskItems { get; set; }
}
}
5. Program.cs (minimal hosting) — seeds roles & admin
Program.cs
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using TaskManagerApp.Data;
using TaskManagerApp.Models;
var builder = WebApplication.CreateBuilder(args);
// Add services
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = false;
})
.AddEntityFrameworkStores<AppDbContext>()
.AddDefaultTokenProviders();
builder.Services.AddControllersWithViews();
var app = builder.Build();
// Ensure DB and seed roles
using (var scope = app.Services.CreateScope())
{
var services = scope.ServiceProvider;
var db = services.GetRequiredService<AppDbContext>();
db.Database.Migrate();
// Seed roles and admin user
var roleManager = services.GetRequiredService<RoleManager<IdentityRole>>();
var userManager = services.GetRequiredService<UserManager<ApplicationUser>>();
string[] roles = new[] { "Admin", "Manager", "User" };
foreach (var r in roles)
{
if (!await roleManager.RoleExistsAsync(r))
await roleManager.CreateAsync(new IdentityRole(r));
}
// create default admin
var adminEmail = "[email protected]";
var admin = await userManager.FindByEmailAsync(adminEmail);
if (admin == null)
{
admin = new ApplicationUser { UserName = "admin", Email = adminEmail, EmailConfirmed = true, FullName = "System Admin" };
var result = await userManager.CreateAsync(admin, "Admin@123"); // change for prod
if (result.Succeeded)
{
await userManager.AddToRoleAsync(admin, "Admin");
}
}
}
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Tasks}/{action=Index}/{id?}");
app.Run();
6. TasksController (main CRUD + assign + complete + role-wise list)
Controllers/TasksController.cs
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using TaskManagerApp.Data;
using TaskManagerApp.Models;
namespace TaskManagerApp.Controllers
{
[Authorize]
public class TasksController : Controller
{
private readonly AppDbContext _db;
private readonly UserManager<ApplicationUser> _userManager;
public TasksController(AppDbContext db, UserManager<ApplicationUser> userManager)
{
_db = db;
_userManager = userManager;
}
// Role-wise listing
public async Task<IActionResult> Index(string status = null)
{
var user = await _userManager.GetUserAsync(User);
var roles = await _userManager.GetRolesAsync(user);
IQueryable<TaskItem> query = _db.TaskItems.Include(t => t.AssignedUser);
if (roles.Contains("Admin"))
{
// Admin sees all - optionally filter by status
}
else if (roles.Contains("Manager"))
{
// Manager sees tasks they created OR assigned to any user
query = query.Where(t => t.CreatedByUserId == user.Id || t.AssignedUserId != null);
}
else
{
// Regular user sees only tasks assigned to them
query = query.Where(t => t.AssignedUserId == user.Id);
}
if (!string.IsNullOrEmpty(status) && Enum.TryParse<TaskStatus>(status, out var st))
{
query = query.Where(t => t.Status == st);
}
var list = await query.OrderByDescending(t => t.CreatedAt).ToListAsync();
return View(list);
}
// GET: Create
public IActionResult Create()
{
return View();
}
// POST: Create
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(TaskItem model)
{
var user = await _userManager.GetUserAsync(User);
if (ModelState.IsValid)
{
model.CreatedAt = DateTime.UtcNow;
model.CreatedByUserId = user.Id;
_db.TaskItems.Add(model);
await _db.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(model);
}
// GET: Edit
public async Task<IActionResult> Edit(int id)
{
var task = await _db.TaskItems.FindAsync(id);
if (task == null) return NotFound();
return View(task);
}
// POST: Edit
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, TaskItem model)
{
var task = await _db.TaskItems.FindAsync(id);
if (task == null) return NotFound();
if (ModelState.IsValid)
{
task.Title = model.Title;
task.Description = model.Description;
task.DueDate = model.DueDate;
task.Status = model.Status;
task.AssignedUserId = model.AssignedUserId;
await _db.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(model);
}
// GET: Assign (simple assignment UI)
public async Task<IActionResult> Assign(int id)
{
var task = await _db.TaskItems.FindAsync(id);
if (task == null) return NotFound();
var users = await _userManager.Users.ToListAsync();
ViewBag.Users = users;
return View(task);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Assign(int id, string assignedUserId)
{
var task = await _db.TaskItems.FindAsync(id);
if (task == null) return NotFound();
task.AssignedUserId = assignedUserId;
task.Status = TaskStatus.InProgress;
await _db.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
// Mark complete
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Complete(int id)
{
var task = await _db.TaskItems.FindAsync(id);
if (task == null) return NotFound();
task.Status = TaskStatus.Completed;
await _db.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
// Details
public async Task<IActionResult> Details(int id)
{
var t = await _db.TaskItems.Include(x => x.AssignedUser).FirstOrDefaultAsync(x => x.Id == id);
if (t == null) return NotFound();
return View(t);
}
// Delete (Admin only)
[Authorize(Roles = "Admin")]
public async Task<IActionResult> Delete(int id)
{
var t = await _db.TaskItems.FindAsync(id);
if (t == null) return NotFound();
_db.TaskItems.Remove(t);
await _db.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
}
}
7. Views (Razor) — minimal examples
Place under Views/Tasks/
Index.cshtml
@model IEnumerable<TaskManagerApp.Models.TaskItem>
@using TaskManagerApp.Models
@inject Microsoft.AspNetCore.Identity.UserManager<TaskManagerApp.Models.ApplicationUser> UserManager
@{
ViewData["Title"] = "Tasks";
}
<h2>Tasks</h2>
<p>
<a asp-action="Create" class="btn btn-primary">Create Task</a>
</p>
<table class="table table-striped">
<thead>
<tr>
<th>Title</th>
<th>Assigned To</th>
<th>Status</th>
<th>Due</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach(var t in Model) {
<tr>
<td>@t.Title</td>
<td>@(t.AssignedUser?.FullName ?? t.AssignedUser?.UserName ?? "Unassigned")</td>
<td>@t.Status</td>
<td>@(t.DueDate?.ToLocalTime().ToString("yyyy-MM-dd") ?? "-")</td>
<td>
<a asp-action="Details" asp-route-id="@t.Id">Details</a> |
<a asp-action="Edit" asp-route-id="@t.Id">Edit</a> |
<a asp-action="Assign" asp-route-id="@t.Id">Assign</a>
<form asp-action="Complete" asp-route-id="@t.Id" method="post" style="display:inline">
<button type="submit" class="btn btn-link">Complete</button>
</form>
</td>
</tr>
}
</tbody>
</table>
Create.cshtml (simple)
@model TaskManagerApp.Models.TaskItem
@{
ViewData["Title"] = "Create Task";
}
<h2>Create Task</h2>
<form asp-action="Create" method="post">
<div class="form-group">
<label asp-for="Title"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Description"></label>
<textarea asp-for="Description" class="form-control"></textarea>
</div>
<div class="form-group">
<label asp-for="DueDate"></label>
<input asp-for="DueDate" type="date" class="form-control" />
</div>
<button type="submit" class="btn btn-primary">Create</button>
</form>
Assign.cshtml
@model TaskManagerApp.Models.TaskItem
@{
ViewData["Title"] = "Assign Task";
var users = ViewBag.Users as List<TaskManagerApp.Models.ApplicationUser>;
}
<h2>Assign Task: @Model.Title</h2>
<form asp-action="Assign" method="post">
<input type="hidden" asp-for="Id" />
<div class="form-group">
<label>Select User</label>
<select name="assignedUserId" class="form-control">
<option value="">-- Unassigned --</option>
@foreach(var u in users)
{
<option value="@u.Id" @(u.Id == Model.AssignedUserId ? "selected" : "")>@u.FullName ?? u.UserName</option>
}
</select>
</div>
<button class="btn btn-primary" type="submit">Assign</button>
</form>
Edit.cshtml and Details.cshtml are straightforward — follow the pattern above (bind fields and show status dropdown).
8. Identity / Account pages
You can scaffold Identity pages (Register/Login) or rely on the default templates. For simplicity you can scaffold or add links to /Identity/Account/Login. In production, scaffold the pages to capture FullName during registration and to allow role assignment (Admin page for user/role management).
9. Database migrations
From terminal:
dotnet ef migrations add InitialCreate
dotnet ef database update
This will create the DB and tables. Program.cs seeds roles + admin user.
10. Additional suggestions for role-wise UX & security
- Add [Authorize(Roles="Admin,Manager")] attributes where appropriate.
- Create an Admin area (Area = Admin) for user & role management using RoleManager + UserManager.
- For manager-team relationships you might add a Team entity and a ManagerId to associate users with managers.
- For large teams add paging, search, and assignment by team.
11. How to run
- Update connection string in appsettings.json to point to your SQL Server (LocalDB works).
- dotnet ef database update (or let Program.cs migrate on startup).
- dotnet run
- Login with seeded admin: [email protected] / Admin@123 (change immediately in production).