I'm trying to handle exception in services part in webapi. The goal I try to achieve is:
When service gets an error e.g. when didn't find the todo with certain id controller should return custom json response with custom status code.
Because in my project controller and service are separated don't have any idea how to achieve it.
Thanks in advance.
Below my code:
in Services/TodoRepository.cs
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using test.Data;
using test.DTO;
using test.Interfaces;
using test.Models;
namespace test.Services
{
public class TodoRepository : ITodoRepository
{
private readonly DataContext _context;
public TodoRepository(DataContext context)
{
_context = context;
}
public async Task<IEnumerable<Todo>> GetTodosAsync()
{
return await _context.Todos.ToListAsync();
}
public async Task<Todo> GetTodoAsync(int id)
{
return await _context.Todos.FindAsync(id);
}
public async Task<Todo> AddTodoAsync(TodoInput input)
{
var todo = new Todo
{
Title = input.Title,
Description = input.Description,
IsDone = input.IsDone
};
await _context.Todos.AddAsync(todo);
return todo;
}
public async Task<Todo> SetTodoAsync(int id, TodoInput input)
{
var todo = await _context.Todos.FindAsync(id);
if (todo == null)
//
// CONTROLLER SHOULD RETURN CUSTOM
// JSON RESPONSE WITH CUSTOM STATUS CODE
// INSTEAD OF EXCEPTION WITH INTERNAL SERVER ERROR
//
throw new Exception("Could not find an item with this id");
todo.Title = input.Title;
todo.Description = input.Description;
todo.IsDone = input.IsDone;
todo.Updated = DateTime.Now;
_context.Todos.Update(todo);
return todo;
}
public async Task<Todo> DeleteTodoAsync(int id)
{
var todo = await _context.Todos.FindAsync(id);
if (todo == null)
//
// CONTROLLER SHOULD RETURN CUSTOM
// JSON RESPONSE WITH CUSTOM STATUS CODE
// INSTEAD OF EXCEPTION WITH INTERNAL SERVER ERROR
//
throw new Exception("Could not find an item with this id");
_context.Todos.Remove(todo);
return todo;
}
public async Task<bool> SaveAllAsync()
{
return await _context.SaveChangesAsync() > 0;
}
}
}
in Controllers/TodosController.cs
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using test.Data;
using test.DTO;
using test.Interfaces;
using test.Models;
namespace test.Controllers
{
[ApiController]
[Route("[controller]")]
public class TodosController : ControllerBase
{
private readonly DataContext _context;
private ITodoRepository _repository;
public TodosController(DataContext context, ITodoRepository repository)
{
_context = context;
_repository = repository;
}
[HttpGet]
public async Task<ActionResult<IEnumerable<Todo>>> GetTodos()
{
return Ok(await _repository.GetTodosAsync());
}
[HttpGet("{id}")]
public async Task<ActionResult<Todo>> GetTodo([FromRoute] int id)
{
return Ok(await _repository.GetTodoAsync(id));
}
[HttpPost]
public async Task<ActionResult<Todo>> AddTodo([FromBody] TodoInput input)
{
var todo = await _repository.AddTodoAsync(input);
if (!await _repository.SaveAllAsync())
return BadRequest("something gone wrong");
return Ok(todo);
}
[HttpPut("{id}")]
public async Task<ActionResult<Todo>> SetTodo([FromRoute] int id, [FromBody] TodoInput input)
{
var todo = await _repository.SetTodoAsync(id, input);
if (!await _repository.SaveAllAsync())
return BadRequest("something gone wrong");
return Ok(todo);
}
[HttpDelete("{id}")]
public async Task<ActionResult<Todo>> DeleteTodo([FromRoute] int id)
{
var todo = await _repository.DeleteTodoAsync(id);
if (!await _repository.SaveAllAsync())
return BadRequest("something gone wrong");
return Ok(todo);
}
}
}