0

I am trying to learn how to create REST API using ASP.NET Core, and I've managed to create working GET and POST requests, but for some reason, the DELETE request is not working. What am I missing?

This is my delete route setup

app.MapDelete("/todo/{id}", Results<Ok, NotFound> ([FromRoute] int id, [FromServices] TodoDb db) =>
{
    var result = db.todos.Where<TodoModel>(model => model.id == id).First();

    if (result is null)
    {
        return TypedResults.NotFound();
    }

    db.todos.Remove(result);
    db.SaveChanges();

    return TypedResults.Ok();
});

When I send a DELETE request, I get this response:

HTTP/1.1 405 Method Not Allowed
Content-Length: 0
Connection: close
Date: Fri, 13 Dec 2024 04:46:32 GMT
Server: Kestrel
Allow: GET, POST

The URL is:

http://localhost:5168/todo?id=2

This is my program.cs:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.EntityFrameworkCore;
using Todo.Model;
using Todo.TodoDb;
using System.ComponentModel;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Rewrite;


WebApplicationBuilder builder = WebApplication.CreateBuilder(args);

// add the data base connection
builder.Services.AddDbContext<TodoDb>(options => options.UseInMemoryDatabase("TodoList"));

//builder.Services.AddDatabaseDeveloperPageExceptionFilter();

WebApplication app = builder.Build();

//builder.Services.AddEndpointsApiExplorer();

// builder.Services.AddOpenApiDocument(config =>
// {
//     config.DocumentName = "TodoAPI";
//     config.Title = "TodoAPI v1";
//     config.Version = "v1";
// });

/// redirects to the todo
app.UseRewriter(new RewriteOptions().AddRedirect("tasks/(.*)", "todo/$1"));

// custom middler ware
app.Use((context, next) => next(context));

app.MapGet("/todo", Results<Ok<List<TodoModel>>, NotFound> ([FromServices] TodoDb db) =>
{
    List<TodoModel> result = db.todos.ToList();

    return result is null ?
    TypedResults.NotFound() :
    TypedResults.Ok<List<TodoModel>>(result);
});

app.MapGet("/todo/{id}", Results<Ok<TodoModel>, NotFound> ([FromRoute] int id, [FromServices] TodoDb db) =>
{
    TodoModel result = db.todos.Where<TodoModel>(model => model.id == id).First();

    Console.WriteLine(result);
    // await db.SaveChangesAsync();

    return result is null ?
        TypedResults.NotFound() : TypedResults.Ok(result);
});

app.MapPost("/todo", Results<Ok<TodoModel>, NotFound> ([FromBody] TodoModel todo, [FromServices] TodoDb db) =>
{
    db.todos.Add(todo);
    db.SaveChanges();

    return TypedResults.Ok<TodoModel>(todo);
});

app.MapDelete("/todo/{id}", Results<Ok, NotFound> ([FromRoute] int id, [FromServices] TodoDb db) =>
{
    var result = db.todos.Where<TodoModel>(model => model.id == id).First();
 
    if (result is null)
    {
        return TypedResults.NotFound();
    }

    db.todos.Remove(result);
    db.SaveChanges();

    return TypedResults.Ok();
});

app.Run();

I have this TodoModel class:

namespace Todo.Model;

public class TodoModel
{
    public int id { get; set; }
    public required string name { get; set; }

    public DateTime dueDate { get; set; }

    public bool isCompleted { get; set; }

    public static implicit operator List<object>(TodoModel v)
    {
        throw new NotImplementedException();
    }
} 

And a DbContext class that uses in memory Entity Framework Core:

namespace Todo.TodoDb;
using Microsoft.EntityFrameworkCore;
using Todo.Model;

public class TodoDb : DbContext
{
    public TodoDb(DbContextOptions<TodoDb> options) : base(options) { }

    public DbSet<TodoModel> todos => Set<TodoModel>();
    // public required DbSet<TodoModel> todos { get; set; }
}
6
  • First(); should be FirstOrDefault(); Commented Dec 13, 2024 at 4:30
  • 3
    It should be http://localhost:5168/todo/2 not http://localhost:5168/todo?id=2 given that is what you told it it would look like - "/todo/{id}". Commented Dec 13, 2024 at 4:52
  • Okay that fixed it!!. Can you explain why ? I intended to use query parameters. Commented Dec 13, 2024 at 4:54
  • 2
    You do a bit of research and come back here and tell us what you tried. Commented Dec 13, 2024 at 4:55
  • 1
    Can you explain why ? Because it matches "/todo/{id}". Commented Dec 13, 2024 at 4:56

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.