【问题标题】:Access ControlerBase outside Action (in CQRS handler)Access ControlerBase 外部操作(在 CQRS 处理程序中)
【发布时间】:2017-08-07 13:06:03
【问题描述】:

我正在将我的逻辑从 Controller 转移到 CQRS 处理程序,但我不确定如何处理调用 ControllerBase 的代码,例如:

[HttpPut("users/{id}")]
public IActionResult Put(UserForm userForm)
{
  var user = Users.Get(email);
  if (user == null) 
    return NotFound();
  ...
}

因此,当我将此逻辑移到操作之外时,显然我无法再访问NotFound。我看到了多种解决方法:

  1. 改为抛出一个自定义的 NotFoundException,然后在 ExceptionMiddleware 中捕获它并在那里返回 NotFoundResult。
  2. 将 ControllerBase 注入 CQRS 命令/查询。不喜欢这个选项,因为命令/查询将与 ASP.NET Core 基础架构过于耦合。

我的快速谷歌搜索没有成功,所以我可能遗漏了一些东西。处理这种情况的推荐方法是什么?

【问题讨论】:

    标签: asp.net-core cqrs mediatr


    【解决方案1】:

    此逻辑/验证不属于命令/查询处理程序,因为它处理某些场景(WebAPI、MVC、桌面、移动应用等)和响应高度依赖于基础架构(在 REST 中,您将返回状态代码、MVC 重定向、桌面消息等)

    使用异常是不可接受的,因为这些是常见情况而非例外情况(至少输入验证和“未找到”)。在处理程序中使用IActionResult 也与基础架构紧密耦合。

    在更大的项目中,我使用“结果”类,类似于 ASP.NET Core Identity 中的IdentityResult

    namespace MyProject.Common
    {
        public class QueryResult
        {
            private static readonly QueryResult success = new QueryResult { Succeeded = true };
            private readonly List<QueryError> errors = new List<QueryError>();
    
            public static QueryResult Success { get { return success; } }
    
            public bool Succeeded { get; protected set; }
            public IEnumerable<QueryError> Errors { get { return errors; } }
    
            public static QueryResult Failed(params QueryError[] errors)
            {
                var result = new QueryResult { Succeeded = false };
                if (errors != null)
                {
                    result.errors.AddRange(errors);
                }
    
                return result;
            }
        }
    
        public class QueryResult<T> : QueryResult where T : class
        {
            public T Result { get; protected set; }
    
            public static QueryResult<T> Suceeded(T result)
            {
                var queryResult = new QueryResult<T>
                {
                    Succeeded = true,
                    Result = result
                };
    
                return queryResult;
            }
        }
    }
    

    并从命令 (QueryResult) 或查询 (QueryResult&lt;T&gt;) 返回这些。

    然后您可以编写返回正确IActionResult 的扩展方法。

    public static class QueryResultExtensions
    {
        public IActionResult ToActionResult(this QueryResult result)
        {
            if(result.Success)
            {
                return new OkResult();
            }
    
            if(result.Errors != null)
            {
                // ToModelStateDictionary needs to be implemented by you ;)
                var errors = result.Errors.ToModelStateDictionary();
                return BadRequestResult(errors);
            }
    
            return BadRequestResult();
        }
    
        public IActionResult ToActionResult<T>(this QueryResult<T> result)
        {
            if(result.Success)
            {
                if(result.Result == null)
                {
                    return new NotFoundResult();
                }
    
                return new OkObjectResult(result.Result);
            }
    
            if(result.Errors != null)
            {
                // ToModelStateDictionary needs to be implemented by you ;)
                var errors = result.Errors.ToModelStateDictionary();
                return BadRequestResult(errors);
            }
    
            return BadRequestResult();
        }
    }
    

    然后在你的控制器中调用它

    [HttpPut("users/{id}")]
    public IActionResult Put(CreateUserCommand command)
    {
        var result = commandHandler.Handle(command);
        return result.ToActionResult();
    }
    

    您失去了控制返回码的更细粒度的能力。您可以为命令/查询或不同的扩展方法创建不同的结果类型,以不同的方式处理它.ToCreateActionResult().ToQueryActionResult() 等。

    【讨论】:

    • 谢谢!这正是我一直在寻找的。我将尝试改进的唯一一件事是找到一种不显式调用 ToActionResult 而是将其放在基础架构级别的某个位置以自动调用的方法
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多