rej*_*y11 9 c# mediatr asp.net-core
因此,我最近开始学习如何将 MediatR 库与 ASP.NET Core Web API 一起使用,但我不确定当对不存在的资源发出 DELETE/PUT/PATCH 请求时如何返回 NotFound()。
如果我们以 DELETE 为例,这是我的控制器操作:
[HttpDelete("{id}")]
public async Task<IActionResult> Delete(int id)
{
await Mediator.Send(new DeleteCourseCommand {Id = id});
return NoContent();
}
Run Code Online (Sandbox Code Playgroud)
命令:
public class DeleteCourseCommand : IRequest
{
public int Id { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
命令处理程序:
public class DeleteCourseCommandHandler : IRequestHandler<DeleteCourseCommand>
{
private readonly UniversityDbContext _context;
public DeleteCourseCommandHandler(UniversityDbContext context)
{
_context = context;
}
public async Task<Unit> Handle(DeleteCourseCommand request, CancellationToken cancellationToken)
{
var course = await _context.Courses.FirstOrDefaultAsync(c => c.Id == request.Id, cancellationToken);
if (course != null)
{
_context.Courses.Remove(course);
var saveResult = await _context.SaveChangesAsync(cancellationToken);
if (saveResult <= 0)
{
throw new DeleteFailureException(nameof(course), request.Id, "Database save was not successful.");
}
}
return Unit.Value;
}
}
Run Code Online (Sandbox Code Playgroud)
正如您在 Handle 方法中看到的,如果保存时出现错误,则会抛出异常,导致 500 内部服务器错误(我相信这是正确的)。但是如果没有找到课程,我如何将其反馈给控制器上的操作?是否只是调用查询以获取控制器操作中的课程,然后在它不存在时返回 NotFound() 或调用命令删除课程的情况?这当然可以工作,但是在我经历过的所有示例中,我还没有遇到使用两个 Mediator 调用的 Action。
MediatR 支持请求/响应模式,它允许您从处理程序类返回响应。要使用这种方法,您可以使用 的通用版本IRequest,如下所示:
public class DeleteCourseCommand : IRequest<bool>
...
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我们声明这bool将是响应类型。bool为了简单起见,我在这里使用:我建议对您的最终实现使用更具描述性的内容,但bool足以解释目的。
接下来,您可以更新您的DeleteCourseCommandHandler以使用这种新的响应类型,如下所示:
public class DeleteCourseCommandHandler : IRequestHandler<DeleteCourseCommand, bool>
{
...
public async Task<bool> Handle(DeleteCourseCommand request, CancellationToken cancellationToken)
{
var course = ...
if (course == null)
return false; // Simple example, where false means it wasn't found.
...
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
在IRequestHandler目前正在实施的有两个泛型类型,命令和响应。这需要更新 的签名Handle以返回一个bool而不是Unit(在您的问题中,Unit未使用)。
最后,您需要更新您的Delete操作以使用新的响应类型,如下所示:
public async Task<IActionResult> Delete(int id)
{
var courseWasFound = await Mediator.Send(new DeleteCourseCommand {Id = id});
if (!courseWasFound)
return NotFound();
return NoContent();
}
Run Code Online (Sandbox Code Playgroud)
我喜欢从我的命令返回事件。该命令告诉您的应用程序客户端希望它做什么。响应是它实际所做的。
\n\nBTW\xe2\x80\x94\'s 表示命令处理程序应该返回任何内容。这实际上仅在完全异步的环境中才是正确的,在该环境中,只有在响应客户端接受命令后的某个时间,命令才会完成。在这种情况下,您将返回Task<Unit>并发布这些事件。一旦它们被提出,客户将通过其他渠道获取它们,例如 SignalR 集线器。无论哪种方式,事件都是告诉客户应用程序中发生了什么的最佳方式。
首先为您的事件定义一个接口
\n\npublic interface IEvent\n{\n\n}\nRun Code Online (Sandbox Code Playgroud)\n\n然后,为命令中可能发生的每件事创建事件。如果您想使用这些信息执行某些操作,则可以在其中包含信息,或者如果类本身就足够了,则将它们留空。
\n\npublic class CourseNotFoundEvent : IEvent\n{\n\n}\n\npublic class CourseDeletedEvent : IEvent\n{\n\n}\nRun Code Online (Sandbox Code Playgroud)\n\n现在,让您的命令返回一个事件接口。
\n\npublic class DeleteCourseCommand : IRequest<IEvent>\n{\n\n}\nRun Code Online (Sandbox Code Playgroud)\n\n你的处理程序看起来像这样:
\n\npublic class DeleteCourseCommandHandler : IRequestHandler<DeleteCourseCommand, IEvent>\n{\n private readonly UniversityDbContext _context;\n\n public DeleteCourseCommandHandler(UniversityDbContext context)\n {\n _context = context;\n }\n\n public async Task<IEvent> Handle(DeleteCourseCommand request, CancellationToken cancellationToken)\n {\n var course = await _context.Courses.FirstOrDefaultAsync(c => c.Id == request.Id, cancellationToken);\n\n if (course is null) \n return new CourseNotFoundEvent();\n\n _context.Courses.Remove(course);\n var saveResult = await _context.SaveChangesAsync(cancellationToken);\n if (saveResult <= 0)\n {\n throw new DeleteFailureException(nameof(course), request.Id, "Database save was not successful.");\n }\n\n return new CourseDeletedEvent();\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n最后,您可以在 Web API 上使用模式匹配来根据返回的事件执行操作。
\n\n[HttpDelete("{id}")]\npublic async Task<IActionResult> Delete(int id)\n{\n var @event = await Mediator.Send(new DeleteCourseCommand {Id = id});\n\n if(@event is CourseNotFoundEvent)\n return NotFound();\n\n return NoContent();\n}\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
7479 次 |
| 最近记录: |