DELETE and PATCH
Tags: csharp, dotnet
Published: 2021-03-07 02:14:37

In this, possibly the final part of the series, we'll focus on implementing DELETE and PATCH actions within our users controller.

We'll start by implementing the DELETE action as it's very simple and easy to do. We'll start by opening up 'AppRepo.cs' and adding a new method called `DeleteUser`.

```csharp
public void DeleteUser(User user)
{
    this._context.Users.Remove(user);
}
```

Now, we'll open up 'UsersController.cs' and create our DELETE action.

```csharp
[HttpDelete("{id}")]
public ActionResult Delete(int id)
{
    User user = this._repo.GetUserById(id);

    if (user != null)
    {
        this._repo.DeleteUser(user);
        this._repo.SaveChanges();

        return NoContent();
    }
    return NotFound();
}
```

That's it. Now, assuming there is a user with the ID of 1 within our database, we can remove them with the following JavaScript.

```javascript
fetch("https://localhost:5001/api/users/1", {
    method: "DELETE"
})
.then(r => console.log(r));
```

Unfortunately creating our PATCH action isn't quite so simple. We'll rely on a few more NuGet packages to help us out. In your terminal, run the following two commands to install the packages we'll be using.

```
dotnet add package Microsoft.AspNetCore.JsonPatch
dotnet add package Microsoft.AspNetCore.Mvc.NewtonsoftJson
```

Now, within 'Startup.cs' we'll need to make some changes to get Newtonsoft JSON serlialization working within our controllers.

First, add the following using statement at the top of the file to reference our newly installed package.

```csharp
using Newtonsoft.Json.Serialization;
```

Now we need to locate the following line within the `ConfigureServices` method.

```csharp
services.AddControllers();
```

This line will need to be changed as follows.

```csharp
services.AddControllers().AddNewtonsoftJson(s => {
    s.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
});
```

Next, we'll create a new DTO and map for handling the transfer of updated properties from the DTO to our user within the database context and vice-versa.

Within the 'Data' folder, create a new file named 'UserUpdateDto.cs', and add the following code.

```csharp
using System.ComponentModel.DataAnnotations;

namespace AspNetCoreWebApiIntro.Dtos
{
    public class UserUpdateDto
    {
        [Key]
        public int Id { get; set; }

        [Required]
        public string FirstName { get; set; }

        [Required]
        public string LastName { get; set; }
    }
}
```

Open up 'UserProfile.cs', and add the following code.

```csharp
using AutoMapper;

using AspNetCoreWebApiIntro.Dtos;
using AspNetCoreWebApiIntro.Models;

namespace AspNetCoreWebApiIntro.Profiles
{
    public class UsersProfile : Profile
    {
        public UsersProfile()
        {
            CreateMap<User, UserReadDto>();
            CreateMap<User, UserUpdateDto>(); // New
            CreateMap<UserUpdateDto, User>(); // New
        }
    }
}
```

Finally, we're able to create our PATCH action. Open 'UsersController.cs' and add the following using statement to the top of the file.

```csharp
using Microsoft.AspNetCore.JsonPatch;
```

Next, add the following action.

```csharp
[HttpPatch("{id}")]
public ActionResult Update(int id, JsonPatchDocument<UserUpdateDto> patchDoc)
{
    User user = this._repo.GetUserById(id);

    if (user != null)
    {
        UserUpdateDto userToUpdate = this._mapper.Map<UserUpdateDto>(user);
        patchDoc.ApplyTo(userToUpdate, ModelState);

        if (!TryValidateModel(userToUpdate))
        {
            return ValidationProblem(ModelState);
        }

        this._mapper.Map(userToUpdate, user);
        this._repo.SaveChanges();

        return NoContent();
    }
    return NotFound();
}
```

Here, we're grabbing the user from our repository as usual, creating a DTO from that user using our mapper, and applying our patch operations using the JSON patch document provided by the Microsoft.AspNetCore.JsonPatch package to the DTO before mapping it back to our user. Traditionally, you'd want to have an `UpdateUser` method within your repository to call prior to `SaveChanges`, however, mapping the user from our edited DTO applies all of the logic needed to update the user.

Again, assuming that there is a user with the ID of 1, we can now change their last name with the following JavaScript.

```javascript
fetch("https://localhost:5001/api/users/5", {
    method: "PATCH",
    headers: {
        "Content-Type": "application/json"
    },
    body: JSON.stringify([
        {
            op: "replace",
            path: "/lastName",
            value: "Doe"
        }
    ])
})
.then(r => console.log(r));
```

I hope that a few people were able to find this series helpful. I may decide to add additional sections in the future, but this should suffice to cover the fundamentals and I'd be glad to answer any questions (if I'm able) in the meantime.

Thanks for reading.