Minimal API delete with multiple params

180 Views Asked by At

It seems that the MapDelete expects a single id to be passed, but my situation, I need to pass a pair of ids. I thought passing a JSON object content would work but it doesn't. Having a POST to act as DELETE can work but it has to have a different path. Here is my code that results in the request matched multiple endpoints.

 app.MapPost("/movies/achievements", async (CreateMovieAchievementCommand cmd, ISender sender) =>
 {
     var id = await sender.Send(cmd);
     return TypedResults.Created("/movies/achievements", id);
 });
 app.MapPost("/movies/achievements", async (RemoveMovieAchievementCommand cmd, ISender sender) =>
 {
     await sender.Send(cmd);
     return TypedResults.Ok();
 });

I would like to change last one to either MapDelete or some how make the 2 posts different enough that it would not result in ambiguity (hoping to keep the URLs the same if possible)

RemoveMovieAchievementCommand contains AchievementId and MovieId

1

There are 1 best solutions below

0
On BEST ANSWER

You have defined two identical endpoints. Change the one for RemoveMovieAchievementCommand to be DELETE which would be much more idiomatic in the REST API paradigm (note that explicit FromBodyAttribute is needed):

app.MapDelete("/movies/achievements",
    async ([FromBody] RemoveMovieAchievementCommand cmd, ISender sender) =>
    {
        await sender.Send(cmd);
        return TypedResults.Ok();
    });

Also usually you need only id for delete so you can do something like:

app.MapDelete("/movies/achievements/{id}", async (idType id, ISender sender) =>
{
    await sender.Send(new RemoveMovieAchievementCommand {Id = id});
    return TypedResults.Ok();
});

RemoveMovieAchievementCommand contains AchievementId and MovieId

I would argue that more RESTfull approach would be moving both to the request path:

app.MapDelete("/movies/{movieId}/achievements/{achievementId}",
    async (MovieIdType movieId, AchievementIdType achievementId, ISender sender) =>
    {
        await sender.Send(new RemoveMovieAchievementCommand
        {
            AchievementId = achievementId,
            MovieId = movieId
        });
        return TypedResults.Ok();
    });

Also see: