0

我有一个向业务层发送命令的分层应用程序(实际上,该应用程序是基于ncqrs 框架的,但我认为这里并不重要)。

命令如下所示:

public class RegisterUserCommand : CommandBase
{
    public string UserName { get; set; }
    public string Email{ get; set; }
    public DateTime RegistrationDate { get; set; }
    public string ApiKey {get; set;} // edit
}

这个类没有逻辑,只有数据。

我想让用户输入他们的用户名、电子邮件,并且我希望系统使用当前日期来构建命令。

什么是最好的:

  1. 创建基于 RegisterUserCommand 的强类型视图,然后在将其发送到业务层之前注入日期和 APi 密钥?

  2. 创建一个RegisterUserViewModel类,用这个类创建视图并根据视图输入创建命令对象?

我编写了以下代码(用于解决方案 n°2):

public class RegisterController : Controller
{
    //
    // GET: /Register/

    public ActionResult Index()
    {
        return View();
    }

    [HttpPost]
    public ActionResult Index(RegisterUserViewModel registrationData)
    {

        var service = NcqrsEnvironment.Get<ICommandService>();
        service.Execute(
            new RegisterUserCommand
            {
                RegistrationDate = DateTime.UtcNow,
                Email= registrationData.Email,
                UserName= registrationData.Name,
                ApiKey = "KeyFromConfigSpecificToCaller" // edit
            }
            );

        return View();
    }


    public class RegisterUserViewModel
    {
        [Required]
        [StringLength(16)]
        public string Name { get; set; }
        [Required]
        [StringLength(64)]
        public string Email{ get; set; }
    }
}

这段代码正在工作......但我想知道我是否选择了正确的方式......

感谢您的建议

[编辑]由于日期时间似乎引起误解,我添加了另一个属性“ApiKey”,它也应该设置在服务器端,从 web 层(而不是从命令层)

[编辑 2]尝试 Erik 的建议并实施我想象的第一个解决方案:

[HttpPost]
public ActionResult Index(RegisterUserCommand registrationCommand)
{

    var service = NcqrsEnvironment.Get<ICommandService>();
    registrationCommand.RegistrationDate = DateTime.UtcNow;
    registrationCommand.ApiKey = "KeyFromConfigSpecificToCaller";
    service.Execute(
        registrationCommand
        );

    return View();
}

...可以接受吗?

4

3 回答 3

2

我认为使用选项#2 会更好,您将拥有一个单独的 ViewModel 和一个命令。虽然它可能看起来是多余的(在一定程度上),但您的命令实际上是从您的 Web 服务器到您的命令处理程序的消息。这些消息的格式可能与您的 ViewModel 不同,也不应该如此。如果您按原样使用 NCQRS,则必须将您的命令映射到您的 AR 方法和构造函数。

虽然它可能会为您节省一点时间,但我认为您将自己归类为在您的 ViewModel 之后对您的域进行建模,而事实并非如此。您的 ViewModel 应该反映您的用户体验和所见;您的域应该反映您的业务规则和知识,并且并不总是反映在您的视图中。

现在看起来可能需要做更多的工作,但请帮自己一个忙,将命令与视图模型分开。以后你会感谢自己的。

我希望这有帮助。祝你好运!

于 2011-09-13T01:54:29.120 回答
1

我会使用数字 1 并使用system.componentmodel.dataannotations.metadatatype进行验证。

我为另一个 SO 问题Here创建了一个示例(答案)。

这允许您将模型保存在另一个库中,验证字段并显示字段,就像使用 DataAnnotations 的内部/私有类一样。我不喜欢为没有附加价值的视图创建一个完全独立的类,同时必须将数据 ORM 回另一个类。(如果您有其他值,例如下拉列表值或默认值,那么我认为这是有意义的)。

代替

[HttpPost]
public ActionResult Index(RegisterUserViewModel registrationData)
{

    var service = NcqrsEnvironment.Get<ICommandService>();
    service.Execute(
        new RegisterUserCommand
        {
            RegistrationDate = DateTime.UtcNow,
            Email= registrationData.Email,
            UserName= registrationData.Name,
            ApiKey = "KeyFromConfigSpecificToCaller" // edit
        }
        );

    return View();
}

你可以有

[HttpPost]
public ActionResult Index(RegisterUserCommand registrationData)
{

    var service = NcqrsEnvironment.Get<ICommandService>();

    registrationData.ApiKey = "KeyFromConfigSpecificToCaller";

    service.Execute(registrationData);

    return View();
}
于 2011-09-12T14:45:28.023 回答
1

我建议将其放入 RegisterUserCommand 类的构造函数中。这样,默认行为总是将其设置为 DateTime.UtcNow,如果您需要明确地将其设置为某些内容,则可以将其添加到对象初始化程序中。这也将有助于您在项目的其他部分使用此类,并且您忘记显式设置 RegistrationDate 的情况。

public class RegisterUserCommand : CommandBase
{
    public string UserName { get; set; }
    public string Email{ get; set; }
    public DateTime RegistrationDate { get; set; }

    public RegisterUserCommand()
    {
        RegistrationDate = DateTime.UtcNow;
    }
}

和控制器

public class RegisterController : Controller
{
    //
    // GET: /Register/

    public ActionResult Index()
    {
        return View();
    }

    [HttpPost]
    public ActionResult Index(RegisterUserViewModel registrationData)
    {

        var service = NcqrsEnvironment.Get<ICommandService>();
        service.Execute(
            new RegisterUserCommand
            {
                Email= registrationData.Email,
                OpenIdIdentifier = registrationData.OpenIdIdentifier
            }
            );

        return View();
    }


    public class RegisterUserViewModel
    {
        [Required]
        [StringLength(16)]
        public string Name { get; set; }
        [Required]
        [StringLength(64)]
        public string Email{ get; set; }
    }
}
于 2011-09-12T14:54:32.703 回答