Let's simplify it a bit:
public async Task<ActionResult<Todo>> GetTodo(long id)
{
Todo todo = await _context.Todos.FindAsync(id);
return todo ?? NotFound();
}
The problem here is that todo
and NotFound()
have very different types. todo
is a Todo
, but NotFound()
returns a NotFoundResult
. These two are inherently incompatible, and the compiler doesn't know that it should convert both of them to an ActionResult<Todo>
.
If you want to keep the method's return type as ActionResult<Todo>
, you can write:
public async Task<ActionResult<Todo>> GetTodo(long id)
{
return (await _context.Todos.FindAsync(id)) ?? new ActionResult<Todo>(NotFound());
}
Alteratively, you can use a helper method:
public static ActionResult<T> ResultOrNotFound<T>(T item) where T : class
{
return item != null ? new ActionResult<T>(item) : new ActionResult<T>(NotFound());
}
Then you can write:
public async Task<ActionResult<Todo>> GetTodo(long id)
{
return ResultOrNotFound(await _context.Todos.FindAsync(id));
}
Alternatively, if you're OK with returning an IActionResult
instead, then you can do:
public static IActionResult OkOrNull(object item)
{
return item != null ? Ok(item) : null;
}
Then you can write:
public async Task<IActionResult<Todo>> GetTodo(long id)
{
return OkOrNull(await _context.Todos.FindAsync(id)) ?? NotFound();
}
You can make this look a bit nicer if you want, with another overload:
public static async Task<IActionResult> OkOrNull<T>(Task<T> task) where T : class
{
T item = await task;
return item != null ? Ok(item) : null;
}
Meaning you can write:
public async Task<IActionResult<Todo>> GetTodo(long id)
{
return await OkOrNull(_context.Todos.FindAsync(id)) ?? NotFound();
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…