We've spent a lot of time on uploading and displaying photos - let's delete them!!
Deleting Photos in the API
First, let's add a method in our PhotoService
for deleting photos from Cloudinary. We already have a generic method for deleting entities from the database, so we don't have to write one in our PhotoService.
In IPhotoService.cs
add the following method signatures:
Copy object DeletePhotoFromCloudinary ( string publicId);
Task < Photo > GetPhotoEntity ( int id);
We're adding another GetPhoto
method - previously, we were returning a DTO - this time we need to return an actual entity so we can delete it from the database.
Now, let's implement them in our PhotoService
concrete class:
Copy public async Task < Photo > GetPhotoEntity ( int id)
{
return await _context . Photos . FirstOrDefaultAsync (p => p . Id == id);
}
public object DeletePhotoFromCloudinary ( string publicId)
{
var deleteParams = new DeletionParams (publicId);
return _cloudinary . Destroy (deleteParams). Result ;
}
In the .API project, open up the PhotosController
and add a new method called DeletePhoto()
Copy [ HttpDelete ( "{id}" )]
public async Task < IActionResult > DeletePhoto ( int userId , int id)
{
if (userId != int . Parse ( User . FindFirst ( ClaimTypes . NameIdentifier ). Value ))
return Unauthorized ();
var photoFromRepo = await _photoService . GetPhotoEntity (id);
if (photoFromRepo == null )
return NotFound ();
if ( photoFromRepo . IsMain )
return BadRequest ( "You cannot delete your main photo" );
if ( photoFromRepo . PublicId != null )
{
var result = _photoService . DeletePhotoFromCloudinary ( photoFromRepo . PublicId ). ToString ();
if (result == "ok" )
_userService . Delete (photoFromRepo);
}
if ( photoFromRepo . PublicId == null )
{
_userService . Delete (photoFromRepo);
}
if ( await _photoService . SaveAll ())
return Ok ();
return BadRequest ( "Failed to delete the photo" );
}
Test out the API to see if you're able to successfully delete a photo.
Get a fresh token from the /auth/login
endpoint.
Send a DELETE request to http://localhost:5000/api/users/{userId}/photos/{photoId}
You should get a 200 OK
response:
Deleting Photos in Angular
First, we'll add a method to the user.service.ts
file:
Copy deletePhoto (userId: number , id: number) {
return this . _http .delete ( this .baseUrl + 'users/' + userId + '/photos/' + id);
}
Now, we can use it in the photo-editor.component.ts
:
Copy deletePhoto (id: number) {
this . _alertify .confirm ( 'Are you sure you want to delete this?' , () => {
this . _userService .deletePhoto ( this . _authService . decodedToken .nameid , id) .subscribe (() => {
this . photos .splice ( _ .findIndex ( this .photos , { id : id }) , 1 );
this . _alertify .success ( 'Photo successfully deleted.' );
} , error => {
this . _alertify .error ( 'Failed to delete.' );
});
});
}
And, we can use it in the 'photo-editor.component.html` file:
Copy <div class="row">
<div class="col-md-2" *ngFor="let photo of photos">
<img class="thumbnail" src="{{ photo.url }}" alt="{{ photo.description }}">
<div class="row justify-content-center">
<button
type="button"
class="btn btn-sm btn-secondary"
(click)="setMainPhoto(photo)"
[ngClass]="photo.isMain ? 'btn-secondary active' : 'btn-default'"
[disabled]="photo.isMain">Main</button>
<button
type="button"
class="btn btn-sm btn-warning"
(click)="deletePhoto(photo.id)" <!-- Added -->
[disabled]="photo.isMain"> <!-- Added -->
<i class="fa fa-trash-o"></i></button>
</div>
</div>
</div>
Wrap-up
Great job! Everything should be working now. Feel free to play around in the app a bit and try uploading and deleting photos and see if you find any bugs. If you do - try to figure out how to fix it.
We've done quite a bit in this module and we've learned a lot!