Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions Todo.Api/Models/ToDo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;

namespace Todo.Api.Models
{
// Create ToDo class
public class ToDo
{
public int Id { get; set; }

public string Title { get; set; }

Check notice

Code scanning / CodeQL

Compilation message

Warning CS8618 Non-nullable property 'Title' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

public bool IsDone { get; set; }

public DateTime CreatedDateTime { get; set; }

public DateTime? CompletedDateTime { get; set; }
}
}
203 changes: 104 additions & 99 deletions Todo.Api/Program.cs
Original file line number Diff line number Diff line change
@@ -1,104 +1,109 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;

WebApplicationBuilder? builder = WebApplication.CreateBuilder(args);

// ConfigureServices
builder.Services.AddDbContext<ToDoDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

WebApplication app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}

app.UseHttpsRedirection();

// Map endpoint to get ToDos
app.MapGet("/Todos", async (ToDoDbContext dbContext) =>
{
return Results.Ok(await dbContext.ToDos.ToListAsync());
});

// Map endpoint to get ToDo by id
app.MapGet("/Todos/{id}", async (ToDoDbContext dbContext, int id) =>
{
ToDo? toDo = await dbContext.ToDos.FindAsync(id);
if (toDo is null)
{
return Results.NotFound();
}

return Results.Ok(toDo);
});

// Map endpoint to create ToDo
app.MapPost("/Todos", async (ToDoDbContext dbContext, ToDo toDo) =>
{
await dbContext.ToDos.AddAsync(toDo);
await dbContext.SaveChangesAsync();

return Results.Created($"/Todos/{toDo.Id}", toDo);
});

// Map endpoint to update ToDo
app.MapPut("/Todos/{id}", async (ToDoDbContext dbContext, int id, ToDo toDo) =>
{
if (await dbContext.ToDos.FindAsync(id) == null)
{
return Results.NotFound();
}

toDo.Id = id;
dbContext.ToDos.Update(toDo);

return Results.NoContent();
});

// Map endpoint to delete ToDo
app.MapDelete("/Todos/{id}", async (ToDoDbContext dbContext, int id) =>
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System.Collections.Generic;
using System.Threading.Tasks;
using Todo.Api.Models;

namespace Todo.Api
{
ToDo? toDo = await dbContext.ToDos.FindAsync(id);
if (toDo is null)
{
return Results.NotFound();
}

dbContext.ToDos.Remove(toDo);
await dbContext.SaveChangesAsync();

return Results.NoContent();
});

await app.RunAsync();

// Create ToDo class
public class ToDo
{
public int Id { get; set; }

public string Title { get; set; }

public bool IsDone { get; set; }

public DateTime CreatedDateTime { get; set; }

public DateTime? CompletedDateTime { get; set; }
}

// Create ToDoDbContext with Entity Framework
public class ToDoDbContext : DbContext
{
public DbSet<ToDo> ToDos { get; set; }

public ToDoDbContext(DbContextOptions<ToDoDbContext> options)
: base(options)
public class Program
{
public static async Task Main(string[] args)
{
WebApplicationBuilder? builder = WebApplication.CreateBuilder(args);

// ConfigureServices
builder.Services.AddDbContext<ToDoDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

WebApplication app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}

app.UseHttpsRedirection();

// Map endpoint to get ToDos
app.MapGet("/Todos", async (ToDoDbContext dbContext) =>
{
return Results.Ok(await dbContext.ToDos.ToListAsync());
});

// Map endpoint to get ToDo by id
app.MapGet("/Todos/{id}", async (ToDoDbContext dbContext, int id) =>
{
ToDo? toDo = await dbContext.ToDos.FindAsync(id);
if (toDo is null)
{
return Results.NotFound();
}

return Results.Ok(toDo);
});

// Map endpoint to search ToDo by Title
app.MapGet("/Todos/Search", async (ToDoDbContext dbContext, string title) =>
{
// Introduce a vulnerability for SQL Injection
// Ex: title = ';DROP TABLE dbo.ToDos;--

List<ToDo>? results = await dbContext.ToDos
.FromSqlRaw("SELECT * FROM dbo.ToDos WHERE Title = '" + title + "'")
.ToListAsync();

return Results.Ok(results);
});

// Map endpoint to create ToDo
app.MapPost("/Todos", async (ToDoDbContext dbContext, ToDo toDo) =>
{
await dbContext.ToDos.AddAsync(toDo);
await dbContext.SaveChangesAsync();

return Results.Created($"/Todos/{toDo.Id}", toDo);
});

// Map endpoint to update ToDo
app.MapPut("/Todos/{id}", async (ToDoDbContext dbContext, int id, ToDo toDo) =>
{
if (await dbContext.ToDos.FindAsync(id) == null)
{
return Results.NotFound();
}

toDo.Id = id;
dbContext.ToDos.Update(toDo);

return Results.NoContent();
});

// Map endpoint to delete ToDo
app.MapDelete("/Todos/{id}", async (ToDoDbContext dbContext, int id) =>
{
ToDo? toDo = await dbContext.ToDos.FindAsync(id);
if (toDo is null)
{
return Results.NotFound();
}

dbContext.ToDos.Remove(toDo);
await dbContext.SaveChangesAsync();

return Results.NoContent();
});

await app.RunAsync();
}
}
}
16 changes: 16 additions & 0 deletions Todo.Api/ToDoDbContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Microsoft.EntityFrameworkCore;
using Todo.Api.Models;

namespace Todo.Api
{
// Create ToDoDbContext with Entity Framework
public class ToDoDbContext : DbContext
{
public DbSet<ToDo> ToDos { get; set; }

public ToDoDbContext(DbContextOptions<ToDoDbContext> options)

Check notice

Code scanning / CodeQL

Compilation message

Warning CS8618 Non-nullable property 'ToDos' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
: base(options)
{
}
}
}
1 change: 0 additions & 1 deletion Todo.Api/Todo.Api.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
Expand Down