Asp.net mvc 3 执行前验证命令

Asp.net mvc 3 执行前验证命令,asp.net-mvc-3,design-patterns,inversion-of-control,command-pattern,Asp.net Mvc 3,Design Patterns,Inversion Of Control,Command Pattern,在我当前构建的系统中,我使用命令模式执行所有可能的操作。我选择了CommandMessage和CommandHandler方法,将逻辑与数据分离。 目前这还可以,但我遇到了一个问题——验证 如何实际验证命令是否可以执行 现在,我在每个命令上都有一个CanExecute(ICommandExecutionContext上下文),让它负责确定它是否可以执行。然后在每个命令中检查ICommandExecutionContext,查看其上下文类型是否正确,然后检查信息是否使命令在该上下文中可执行 所有内

在我当前构建的系统中,我使用命令模式执行所有可能的操作。我选择了CommandMessage和CommandHandler方法,将逻辑与数据分离。 目前这还可以,但我遇到了一个问题——验证

如何实际验证命令是否可以执行

现在,我在每个命令上都有一个
CanExecute(ICommandExecutionContext上下文)
,让它负责确定它是否可以执行。然后在每个命令中检查
ICommandExecutionContext
,查看其上下文类型是否正确,然后检查信息是否使命令在该上下文中可执行

所有内容都封装在一个
ICommandService
中,该服务可以根据命令的名称、上下文和消息验证和执行命令。此外,它还发布有关命令执行的事件,并执行权限检查

问题源于UI(ASP.NET MVC 3应用程序)。我只想在每个视图中显示有效的命令,但我没有想出一个我真正喜欢的解决方案。当前,我的控制器询问命令服务,在给定具体上下文的情况下,命令是否可以执行:

var executionContext = new SystemCommandExecutionContext("SignInCommand", CurrentPrincial);
var canExecute = _commandService.CanExecute(executionContext);
/* Handle the result to enable or disable the action link */
对于在具体域对象上工作的其他类型的命令,我使用相同的命令服务方法,但使用不同的上下文,在其中传递域对象id,如下所示:

[HttpPost, Authorize, ValidateAntiForgeryToken /* etc. */]
public ActionResult Delete(Guid id)
{
    /* Note the additional object id in the context */
    var executionContext = new EntityCommandExecutionContext("DeletePersonCommand", CurrentPrincipal, id);
    var canExecute = _commandService.CanExecute(executionContext);

    if(canExecute)
    {
        var message = new DeletePersonCommandMessage(id);
        var isValid = _commandService.IsValid(executionContext, message);
        if(isValid)
        {
            var result = _commandService.Execute(executionContext, message);
            /* More logic here... Not very DRY :( */
        }            
    }
}
class ActionLinkViewModel
{
        public string Name { get; set; }
        public string Url { get; set; }
        public bool Enabled { get; set; }
}
我想上面这些现在还可以,虽然不是很干。 但我想完成的是根据CanExecute的结果禁用操作链接

我该怎么做

我已经决定对每个视图上的所有命令链接进行“硬编码”,因此我不必传递命令名集合等-这条路径太难了(除非有人有聪明的想法;)


我的当前堆栈由NHibernate、Castle Windsor、ASP.NET MVC 3、AutoMapper组成。

请注意,您的命令对象是那些被序列化并发送到(可能是远程)服务以由命令处理程序处理的对象,那么这不是GoF意义上的命令模式的实例,因为命令对象本身不提供执行方法。在这种情况下,command message对象的目的是表示一个动作以及所需的参数。一些源称之为可序列化方法调用。消息对象不应包含行为,只应包含数据,命令消息也不例外。这意味着确定给定命令是否可以在特定上下文中执行的过程应该由单独的服务处理。此验证服务的具体实现取决于用于确定给定命令是否可以执行的标准。它可能能够基于某些上下文和命令类型验证命令:

interface ICommandValidationService
{
  bool CanExecute(object context, Type commandType);
}
上下文对象应该独立于正在执行的实际命令。相反,它应该包含更多全局上下文值,例如用户、用户权限等。命令的执行能力将使用此上下文来决定

基于命令的执行状态禁用或隐藏操作链接可以使用如下视图模型实现:

[HttpPost, Authorize, ValidateAntiForgeryToken /* etc. */]
public ActionResult Delete(Guid id)
{
    /* Note the additional object id in the context */
    var executionContext = new EntityCommandExecutionContext("DeletePersonCommand", CurrentPrincipal, id);
    var canExecute = _commandService.CanExecute(executionContext);

    if(canExecute)
    {
        var message = new DeletePersonCommandMessage(id);
        var isValid = _commandService.IsValid(executionContext, message);
        if(isValid)
        {
            var result = _commandService.Execute(executionContext, message);
            /* More logic here... Not very DRY :( */
        }            
    }
}
class ActionLinkViewModel
{
        public string Name { get; set; }
        public string Url { get; set; }
        public bool Enabled { get; set; }
}

其中启用值由
ICommandValidationService
在控制器中分配。此外,还可以扩展以指定给定的站点地图节点是否可见

这和我现在的情况差不多。关于我的命令模式实现,我不确定你的意思。你能详细说明一下吗?我相信(也许我不清楚),你忘了在域对象上运行命令了吗?我不确定如何向验证服务提供包含域信息的上下文?